Docker: Development and Production Environments
Picture by Mohammad Rahmani on Unsplash
Using Docker allows you to create isolated and replicable environments for both development and production. However, each environment has different needs: in development, you may require debugging tools, while in production, you prioritize efficiency and security. This is where the need for different configurations for both the Dockerfile
and the docker-compose.yml
file comes into play. Let’s look at how to achieve this with a Flask application connected to a PostgreSQL database.
To begin, we’ll create two different Dockerfile
files. The first one will be for development (Dockerfile.dev
), where we include tools useful for the developer, such as debuggers and hot-reloading modules like flask-reload
. An example of a Dockerfile.dev
could look like this:
## Dockerfile.dev
FROM python:3.10-slim
WORKDIR /app
# Install dependencies
COPY requirements.txt .
RUN pip install -r requirements.txt
# Copy all the code into the container
COPY . .
# Port for the API
EXPOSE 5000
# Start command with hot-reload
CMD ["flask", "run", "--host=0.0.0.0", "--reload"]
In this file, the --reload
option is essential for development, as it allows the Flask server to automatically restart when code changes are detected, improving development speed.
For production, you need a different Dockerfile
, one that is lighter and optimized for stability and security. In this case, it’s better to remove development tools and use a more robust web server like gunicorn
to handle traffic instead of Flask’s development server. A Dockerfile.prod
might look like this:
# Dockerfile.prod
FROM python:3.10-slim
WORKDIR /app
# Install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy all the code into the container
COPY . .
# Port for the API
EXPOSE 5000
# Start command with gunicorn
CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:5000", "app:app"]
Here, gunicorn
is used, a WSGI HTTP server suitable for production, and hot-reloading or unnecessary tools are avoided.
Now, for the PostgreSQL database and the overall infrastructure, we can use docker-compose
to define and bring up containers for both Flask and PostgreSQL. Just like with the Dockerfile
, we can have different configurations for development and production. In development (docker-compose.dev.yml
), you can expose additional ports and mount local volumes to edit code without needing to rebuild the image:
# docker-compose.dev.yml
version: '3'
services:
web:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- "5000:5000"
volumes:
- .:/app
environment:
- FLASK_ENV=development
depends_on:
- db
db:
image: postgres:15
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: mydatabase
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
This file allows developers to change code locally and see the changes immediately. Additionally, the database ports are exposed for testing and debugging.
In production, the docker-compose.prod.yml
file will be more restrictive. You won’t need local volumes or debugging tools, and you likely won’t want to expose unnecessary ports:
# docker-compose.prod.yml
version: '3'
services:
web:
build:
context: .
dockerfile: Dockerfile.prod
ports:
- "5000:5000"
environment:
- FLASK_ENV=production
depends_on:
- db
db:
image: postgres:15
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: mydatabase
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
With these separate files, you can easily run your application in either development or production simply by specifying which configuration file to use with Docker Compose. For example, to bring up the development environment, you would run:
docker-compose -f docker-compose.dev.yml up --build
And for production:
docker-compose -f docker-compose.prod.yml up --build
By having clear and separate configurations for each environment, you can ensure that your Flask application with PostgreSQL runs optimally in both development and production, without risking stability or development speed.
o/

Marco
Romero
Hi! I am a software developer with a solid development background and experience in various technical areas. I complement my technical skills with studies in teaching, which has enhanced my ability to communicate complex concepts clearly and effectively, as well as to collaborate in dynamic environments.
I have a proven track record in problem solving and incident management, applying a methodical and results-oriented approach. I quickly adapt to new technologies and methodologies, keeping up with industry trends to deliver innovative and efficient solutions.
- Name
- Phone
- Web
- Home
- Marco Antonio Romero Torrez
- +54 280 484 2576
- marcoromero.dev@gmail.com
- marcoromero.com.ar
- Puerto Madryn, Chubut - Argentina