<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Oluwatofunmi okedeji</title>
    <description>The latest articles on DEV Community by Oluwatofunmi okedeji (@21toffy).</description>
    <link>https://dev.to/21toffy</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F650009%2F2ff948bf-f47d-4522-9260-7ce8cbad548b.jpg</url>
      <title>DEV Community: Oluwatofunmi okedeji</title>
      <link>https://dev.to/21toffy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/21toffy"/>
    <language>en</language>
    <item>
      <title>From GitHub to AWS ECS: A Step-by-Step Guide to Deploying Flask Apps with Docker and Docker Hub.</title>
      <dc:creator>Oluwatofunmi okedeji</dc:creator>
      <pubDate>Tue, 23 Sep 2025 19:17:21 +0000</pubDate>
      <link>https://dev.to/21toffy/from-github-to-aws-ecs-a-step-by-step-guide-to-deploying-flask-apps-with-docker-and-docker-hub-4me1</link>
      <guid>https://dev.to/21toffy/from-github-to-aws-ecs-a-step-by-step-guide-to-deploying-flask-apps-with-docker-and-docker-hub-4me1</guid>
      <description>&lt;p&gt;Deploying applications seamlessly is a crucial skill in today's software engineering and DevOps landscape. In this guide, I’ll show you how to deploy a Flask app using GitHub Actions, Docker Hub, and AWS ECS.&lt;br&gt;
We’ll explore the repository structure, including the Dockerfile, docker-compose.yml, and cicd.yml, which collectively form the backbone of this deployment pipeline.&lt;br&gt;
By the end of this tutorial, you’ll have a fully automated CI/CD pipeline for your Flask app that deploys updates directly to ECS.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;&lt;br&gt;
Before starting, ensure you have:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A Flask application in a GitHub repository.&lt;/li&gt;
&lt;li&gt;A Docker Hub account and repository.&lt;/li&gt;
&lt;li&gt;AWS Account.&lt;/li&gt;
&lt;li&gt;Basic familiarity with Docker.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  The Flow (High Level)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Write Code: You write and commit your Flask app code to GitHub.&lt;/li&gt;
&lt;li&gt;GitHub Actions: When you push your changes:&lt;/li&gt;
&lt;li&gt;The workflow builds a Docker image.&lt;/li&gt;
&lt;li&gt;The image is pushed to Docker Hub.&lt;/li&gt;
&lt;li&gt;AWS ECS is updated to use the latest image.&lt;/li&gt;
&lt;li&gt;AWS ECS: ECS pulls the Docker image from Docker Hub and runs your app on the cloud.&lt;/li&gt;
&lt;li&gt;Access Your App: Your app is live and accessible via a URL or public IP.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Why This Pipeline Works Well
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;GitHub: Centralized code repository with version control.&lt;/li&gt;
&lt;li&gt;Docker: Standardizes your app for consistent performance.&lt;/li&gt;
&lt;li&gt;Docker Hub: Reliable storage for container images.&lt;/li&gt;
&lt;li&gt;GitHub Actions: Automates the entire process, saving time and reducing human error.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Step 1: Creating IAM Policies for ECS Deployment
&lt;/h2&gt;

&lt;p&gt;To ensure your ECS deployment has the necessary permissions, follow the steps below to create two critical IAM policies. These policies allow ECS to pull images from Docker Hub or Amazon ECR and create CloudWatch log streams.&lt;/p&gt;

&lt;p&gt;** Steps to Create Policies **&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to the IAM Console.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5xz5xoj7pr0ic9wtq9m2.png" alt=" " width="800" height="582"&gt;
&lt;/li&gt;
&lt;li&gt;In the left navigation menu, click Policies.&lt;/li&gt;
&lt;li&gt;Click Create Policy.&lt;/li&gt;
&lt;li&gt;Select the JSON tab and replace the default content with one of the JSON configurations provided below.&lt;/li&gt;
&lt;li&gt;Click Next: Tags (you can skip adding tags).&lt;/li&gt;
&lt;li&gt;Click Next: Review.&lt;/li&gt;
&lt;li&gt;Provide a name and description for the policy:&lt;/li&gt;
&lt;li&gt;Example Name: #### ECS-Pull-Image-Policy&lt;/li&gt;
&lt;li&gt;Example Description: #### Permissions for ECS to pull images from Docker Hub or ECR.&lt;/li&gt;
&lt;li&gt;Click Create Policy.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;__Repeat the process for the second JSON configuration.&lt;/p&gt;

&lt;p&gt;** Policy 1: Pull Images from Docker Hub or Amazon ECR **&lt;br&gt;
This policy grants ECS permissions to pull container images.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ecr:GetAuthorizationToken",
                "ecr:BatchCheckLayerAvailability",
                "ecr:GetDownloadUrlForLayer",
                "ecr:BatchGetImage"
            ],
            "Resource": "*"
        }
    ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Policy 2: Create CloudWatch Log Streams&lt;/strong&gt;&lt;br&gt;
This policy allows ECS to create and write log streams to CloudWatch.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:PutLogEvents",
                "logs:CreateLogGroup"
            ],
            "Resource": [
                "arn:aws:logs:*:*:log-group:/ecs/*:*",
                "arn:aws:logs:*:*:log-group:/ecs/*:log-stream:*"
            ]
        }
    ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Additional Notes&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why These Policies Are Important:&lt;/li&gt;
&lt;li&gt;Pulling Images: ECS needs to fetch your container images from Docker Hub or Amazon ECR to deploy your app.&lt;/li&gt;
&lt;li&gt;CloudWatch Logs: Logs are essential for debugging and monitoring. This policy ensures ECS can write logs for your app's tasks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;-Best Practices:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Assign descriptive names to your policies (e.g., ECS-Log-Policy or ECS-Pull-Image-Policy).&lt;/li&gt;
&lt;li&gt;Add clear descriptions for better management.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 2: Creating IAM Roles for ECS Deployment
&lt;/h2&gt;

&lt;p&gt;IAM roles allow ECS to perform specific actions like pulling images and writing logs on your behalf. Follow the steps below to create a role for ECS tasks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Steps to Create the Role&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to the &lt;a href="https://console.aws.amazon.com/iam/" rel="noopener noreferrer"&gt;IAM console&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;In the left navigation menu, click Roles.&lt;/li&gt;
&lt;li&gt;Click Create Role.&lt;/li&gt;
&lt;li&gt;Under Trusted entity type, select Custom trust policy.&lt;/li&gt;
&lt;li&gt;Paste the following JSON code into the Custom trust policy editor:
json
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Statement1",
            "Effect": "Allow",
            "Principal": {
                "Service": "ecs-tasks.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Click Next.&lt;/li&gt;
&lt;li&gt;On the Permissions page:&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Attach the two policies you created earlier:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ECS-Pull-Image-Policy&lt;/li&gt;
&lt;li&gt;ECS-Log-Policy&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click Next.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide a Role Name and Description:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Example Role Name: ECSExecutionRole&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Example Description: Role to allow ECS tasks to pull images and write logs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click Create Role.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  What are Trust policies ?
&lt;/h3&gt;

&lt;p&gt;Define WHO can assume a role (the "Principal")&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can be AWS services (like ecs-tasks.amazonaws.com)&lt;/li&gt;
&lt;li&gt;Other AWS accounts&lt;/li&gt;
&lt;li&gt;IAM users&lt;/li&gt;
&lt;li&gt;Web identity providers (like Google or Facebook)
Always use the "sts:AssumeRole" action
Can only have one trust policy per role&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 3: Set Up ECS Cluster
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Understanding ECS: Key Concepts and Nomenclature&lt;/strong&gt;&lt;br&gt;
Amazon Elastic Container Service (ECS) is a managed container orchestration service that helps deploy, manage, and scale containerized applications. Let’s break down the critical components and concepts you need to know for working with ECS effectively.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Core ECS Dynamics&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Task Definitions:&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A task definition is like a blueprint for your application. It defines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The container images to use (e.g., from Docker Hub or ECR).&lt;/li&gt;
&lt;li&gt;The resource requirements (CPU, memory).&lt;/li&gt;
&lt;li&gt;Network settings and environment variables.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tasks:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A task is an instantiation of a task definition.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It’s the actual running instance of your application.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Services:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A service manages and maintains the desired number of task instances.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Example: If you want three containers of your app running, the service ensures this even if one fails.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Clusters:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A cluster is a logical grouping of resources. It hosts the infrastructure where your tasks run (either EC2 instances or Fargate).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Container Instances:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If using EC2 launch type, these are the EC2 instances where containers are deployed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If using Fargate, AWS manages the infrastructure for you (serverless approach).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Launch Types:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fargate: Serverless, AWS manages the instances. Ideal for most use cases as it eliminates infrastructure management.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;EC2: You manage the instances (more flexibility but also more responsibility).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Load Balancers (Optional):&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Distributes incoming traffic across multiple containers to ensure availability and fault tolerance.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;ECS Workflow in Practice&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Define a Task:

&lt;ul&gt;
&lt;li&gt;Write a task definition with the container details.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Create a Cluster:

&lt;ul&gt;
&lt;li&gt;Set up a logical grouping for the infrastructure.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Deploy Services:

&lt;ul&gt;
&lt;li&gt;Use a service to manage and scale tasks.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Monitor:

&lt;ul&gt;
&lt;li&gt;Use CloudWatch for logs and metrics to ensure the application runs as expected.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Define A Task&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv2etludglkv7vwytl9n9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv2etludglkv7vwytl9n9.png" alt=" " width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;create a taskdefinition family name similar to the project you are tryingtodeploy.&lt;br&gt;
select a launch type, I will go with Fargate&lt;/p&gt;

&lt;p&gt;for Operating system/Architecture&lt;br&gt;
I will go with linux/x86_64&lt;br&gt;
CPU, I will check 1cpu, memory 2GB&lt;br&gt;
for Task execution role.  and task role choose the role. you crreated before. ECSExecutionRole&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/..." class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/..." alt="Uploading image" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;** Create a Cluster: **&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open the &lt;a href="https://console.aws.amazon.com/ecs/" rel="noopener noreferrer"&gt;ECS console.&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Click "Create Cluster" and choose:
select. thename of the cluster EG DevCluster
select the name of the namespace, this would have automatically been created and named the same as the cluster, you could change it to something else in the. dropdown
for infrastructure select Fargate for serverless deployments.
EC2 if you want to manage instances manually.
dlick on the dropdown for monitoring and select 'Container Insights with enhanced observability'
You can leave everything else as it is and click on create, It takes a while to be completely created also.
after is has been created, click on the clister and righr below the pageon the service tab, click on create&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ov4hb34teryly8bh6zy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ov4hb34teryly8bh6zy.png" alt=" " width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Compute configuration
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxuain8ii6u6u82ug63d1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxuain8ii6u6u82ug63d1.png" alt=" " width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let me explain the compute configuration options available when setting up an ECS service:&lt;/p&gt;

&lt;p&gt;Compute Options - You have two main choices:&lt;br&gt;
a) Capacity Provider Strategy&lt;/p&gt;

&lt;p&gt;More flexible and automated approach&lt;br&gt;
Allows mixing of different compute types (like FARGATE and FARGATE_SPOT)&lt;br&gt;
Can set up rules for task distribution&lt;br&gt;
Better for cost optimization and availability&lt;/p&gt;

&lt;p&gt;b) Launch Type&lt;/p&gt;

&lt;p&gt;Simpler, more direct approach&lt;br&gt;
Choose a single compute type (like FARGATE or EC2)&lt;br&gt;
Less flexible but easier to understand&lt;br&gt;
Good for simple use cases&lt;/p&gt;

&lt;p&gt;Capacity Provider Strategy Options:&lt;br&gt;
a) Use Cluster Default&lt;/p&gt;

&lt;p&gt;Uses whatever strategy is set at the cluster level&lt;br&gt;
Good for consistency across services&lt;/p&gt;

&lt;p&gt;b) Use Custom&lt;/p&gt;

&lt;p&gt;FARGATE: Regular, predictable pricing&lt;br&gt;
FARGATE_SPOT: Up to 70% cheaper but can be interrupted&lt;br&gt;
Can set for each provider:&lt;/p&gt;

&lt;p&gt;Base: Minimum number of tasks&lt;br&gt;
Weight: Relative distribution of tasks&lt;/p&gt;

&lt;p&gt;Platform Version&lt;/p&gt;

&lt;p&gt;LATEST: Automatically uses newest platform features&lt;br&gt;
Specific versions available (like 1.4.0):&lt;/p&gt;

&lt;p&gt;1.4.0: Enhanced network performance, security patches&lt;br&gt;
1.3.0: Earlier version with basic features&lt;br&gt;
Choose specific versions if you need stability or specific features&lt;/p&gt;

&lt;p&gt;Example strategy:&lt;/p&gt;

&lt;p&gt;Complete the setup with networking configurations (e.g., VPC and subnets).&lt;/p&gt;

&lt;p&gt;Clone the Flask App Repository&lt;br&gt;
Start by cloning the repository containing the Flask application. Use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/21toffy/docker-ecs-deployment-test.git

cd docker-ecs-deployment-test

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Explore the Repository
&lt;/h2&gt;

&lt;p&gt;Let’s break down the critical files in the repository:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dockerfile&lt;/strong&gt;&lt;br&gt;
The Dockerfile describes how to containerize the Flask app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM python:3.10-slim

WORKDIR /app

# Install build dependencies
RUN apt-get update &amp;amp;&amp;amp; apt-get install -y \
    build-essential \
    &amp;amp;&amp;amp; rm -rf /var/lib/apt/lists/*

COPY requirements.txt requirements.txt
RUN pip install --no-cache-dir -r requirements.txt

# Copy the application code
COPY . .

# Set environment variables
ENV PYTHONPATH=/app
ENV FLASK_APP="app:create_app()"
ENV FLASK_ENV=development
ENV PYTHONUNBUFFERED=1

EXPOSE 5000

CMD ["flask", "run", "--host=0.0.0.0", "--port=5000"]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explanation:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Base Image: Uses python:3.10-slim for a lightweight Python environment.&lt;/li&gt;
&lt;li&gt;Dependencies: Installs essential tools and Python dependencies from requirements.txt.&lt;/li&gt;
&lt;li&gt;Environment Variables: Configures Flask to run in development mode and sets the app entry point (app:create_app()).&lt;/li&gt;
&lt;li&gt;Expose Port: Opens port 5000 for the Flask app.&lt;/li&gt;
&lt;li&gt;CMD: Runs the Flask app on 0.0.0.0 to make it accessible externally.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;** Docker Compose File (docker-compose.yml) **&lt;/p&gt;

&lt;p&gt;The docker-compose.yml simplifies running the container and connecting services:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: "3.8"

services:
  web:
    build: .
    image: oluwatofunmi/question-answer:v1
    container_name: flask_app
    environment:
      - POSTGRES_USER=${POSTGRES_USER}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - POSTGRES_DB=${POSTGRES_DB}
      - DATABASE_URL=${DATABASE_URL}
      - FLASK_ENV=${FLASK_ENV}
      - FLASK_APP=app:create_app()
    env_file:
      - .env
    ports:
      - "5000:5000"
    volumes:
      - .:/app
    networks:
      - app-network
    command: flask run --host=0.0.0.0 --port=5000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explanation:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Service Definition: Defines a web service using the Flask app.
Environment Variables: Reads sensitive credentials from the .env file.&lt;/li&gt;
&lt;li&gt;Ports: Maps port 5000 of the container to port 5000 of the host.&lt;/li&gt;
&lt;li&gt;Volumes: Mounts the project directory into the container for live updates during development.&lt;/li&gt;
&lt;li&gt;Networks: Sets up an isolated network for communication between services.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;** GitHub Actions Workflow (cicd.yml) **&lt;br&gt;
The cicd.yml automates the CI/CD process:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: CI/CD Pipeline

on:
  push:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v2

      - name: Build Docker image
        run: |
          docker build -t oluwatofunmi/question-answer:latest .

      - name: Login to Docker Hub
        uses: docker/login-action@v2
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Push Docker image to DockerHub
        run: docker push oluwatofunmi/question-answer:latest

  deploy-to-ecs:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v3
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: us-east-1
      - name: Deploy to ECS
        run: |
          aws ecs update-service \
            --cluster selftestcluster \
            --service selftestservice \
            --force-new-deployment

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;** Explanation:**&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Trigger: Runs on every push to the main branch.&lt;/li&gt;
&lt;li&gt;Build Job:&lt;/li&gt;
&lt;li&gt;Checks out the code.&lt;/li&gt;
&lt;li&gt;Builds the Docker image.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pushes the image to Docker Hub.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deploy Job:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Configures AWS credentials using repository secrets.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Updates the ECS service to deploy the new Docker image.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 3: Set Up Environment Variables
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Create a .env File: Add the following to a .env file in your repository:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DATABASE_URL=
OPENAI_API_KEY=
SECRET_KEY=
POSTGRES_USER=
POSTGRES_PASSWORD=
POSTGRES_DB=
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Add Secrets to GitHub: In the GitHub repository:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Go to Settings &amp;gt; Secrets and Variables &amp;gt; Actions &amp;gt; New Repository Secret.&lt;/p&gt;

&lt;p&gt;Add the following secrets:&lt;br&gt;
DOCKERHUB_USERNAME&lt;br&gt;
DOCKERHUB_TOKEN&lt;br&gt;
AWS_ACCESS_KEY_ID&lt;br&gt;
AWS_SECRET_ACCESS_KEY&lt;/p&gt;

</description>
      <category>docker</category>
      <category>aws</category>
      <category>cicd</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Connect To A Locally Hosted PostgreSQL From A Docker Container</title>
      <dc:creator>Oluwatofunmi okedeji</dc:creator>
      <pubDate>Mon, 15 May 2023 07:44:39 +0000</pubDate>
      <link>https://dev.to/21toffy/connect-to-locally-hosted-postgresql-from-a-docker-container-109o</link>
      <guid>https://dev.to/21toffy/connect-to-locally-hosted-postgresql-from-a-docker-container-109o</guid>
      <description>&lt;p&gt;If you are running a postgreSQL database on your host machine and want to connect it to a Docker container running on the same host machine, there are a few steps you need to follow. In this article, we will go through the process of connecting a Docker container running on a host machine to a database running on the same host machine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisite&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before we start, make sure you have the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Docker installed on your host machine&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A database running on your host machine&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Basic knowledge of Docker and databases&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;I write the article using the following.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;OS: Debian 11 (bullseye)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PostgreSQL: 15 (Hosted on Debian)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Docker: Server Application (which connects to PostgreSQL)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I am using docker-compose.yml to build application.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  STEP 1:
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Please add host.docker.internal:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: '3'
services:
  bank-server:
    ...
    depends_on:
      ....
    restart: on-failure
    ports:
      - 9090:9090
    extra_hosts:
      - "host.docker.internal:&amp;lt;docker0 IP&amp;gt;"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;To find IP of docker i.e.  you can use:&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;$&amp;gt; ifconfig docker0&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker0: flags=4099&amp;lt;UP,BROADCAST,MULTICAST&amp;gt;  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OR&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$&amp;gt; ip a&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1: docker0: &amp;lt;NO-CARRIER,BROADCAST,MULTICAST,UP&amp;gt; mtu 1500 qdisc noqueue state DOWN group default
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  STEP 2:
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Update the listen_addresses setting in postgresql.conf.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This will allow PostgreSQL to listen on all available network interfaces.&lt;/p&gt;

&lt;p&gt;In postgresql.conf, change listen_addresses to listen_addresses = '*'. Use the command bellow to edit postgres conf&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo nano /etc/postgresql/&amp;lt;your_postgres_version&amp;gt;/main/postgresql.conf&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3:
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Add a new entry to pg_hba.conf&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the pg_hba.conf file, add a new entry that allows connections from all IP addresses.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;host    all             all             0.0.0.0/0               md5

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4:
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Restart PostgreSQL&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After making the changes, restart the PostgreSQL service using the following command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo service postgresql restart&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  STEP 5:
&lt;/h2&gt;

&lt;p&gt;Use host.docker.internal hostname to connect database from Server Application.&lt;/p&gt;

&lt;p&gt;Ex: &lt;code&gt;jdbc:postgresql://host.docker.internal:5432/bankDB&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If you are encountering issues with the host.docker.internal hostname not being recognized on Ubuntu, you can try replacing it with the local Docker IP address, which is typically &lt;code&gt;172.17.0.1&lt;/code&gt;. This should allow your container to connect to the database running on the host machine.&lt;/p&gt;

&lt;p&gt;It's always a good idea to restrict access to your database to only the necessary IP addresses for security purposes. Using the Docker bridge IP as the allowed IP address can help ensure that only the container connected to the same network can access the database.&lt;/p&gt;

&lt;p&gt;you can use the docker bridge IP (use &lt;code&gt;ip -h -c a&lt;/code&gt; to find that IP)&lt;/p&gt;

&lt;p&gt;&lt;em&gt;There may be other solutions to this problem, but this solution has been tested and verified to work with The technologies and their respective versions I highlighted above.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Thanks 😀.&lt;/p&gt;

</description>
      <category>postgres</category>
      <category>docker</category>
      <category>linux</category>
      <category>dockercompose</category>
    </item>
  </channel>
</rss>
