How to Deploy Python Apps with Docker Compose
How to Deploy Python Apps with Docker Compose
Stop wrestling with conflicting dependencies and environment variables across your team. The moment you run pip install on a new machine, something breaks—maybe a library version is outdated, maybe a system path is missing, and suddenly your perfectly working local app is a ghost. Docker Compose solves this by treating your entire application stack as a single, reproducible unit. Instead of manually configuring servers, databases, and environments, you define everything in a simple YAML file and spin up your entire Python app with one command. This isn’t just about containerization; it’s about shipping confidence.
Why Docker Compose is the Right Tool for Python
Python’s flexibility is its strength, but it’s also the source of most deployment headaches. You might have a Flask app that needs Redis for caching, a PostgreSQL database for storage, and Celery workers for background tasks. Managing these separately on your local machine is tedious, and deploying them to production often requires complex infrastructure scripts.
Docker Compose lets you define all these services in one file. It orchestrates container creation, networking, and startup order automatically. When you run docker compose up, Compose builds your images, links your containers together, and exposes the right ports—all without you touching a single terminal command for each service.
For Python developers, this means:
- Consistency: Your dev, test, and prod environments run the exact same code.
- Speed: Spin up a full stack in seconds, not hours.
- Simplicity: No need for complex deployment scripts or manual server setup.
Building Your First Python App with Docker
Let’s get hands-on. We’ll create a simple Flask app that serves a JSON response, then containerize it with Docker and orchestrate it with Docker Compose.
Step 1: Create the Flask Application
First, create a new directory for your project and add a main.py file:
from flask import Flask, jsonify
app = Flask(__name__)
@app.route("/")
def home():
return jsonify({"message": "Hello from Dockerized Python!", "status": "success"})
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)
This is a minimal but functional Flask app. It listens on port 5000 and returns a JSON response when you hit the root endpoint.
Step 2: Create a requirements.txt File
Next, create a requirements.txt file to list your dependencies:
flask==2.3.3
This ensures Docker installs the exact version you need, avoiding compatibility issues.
Step 3: Write the Dockerfile
Now, create a Dockerfile in the same directory. This file tells Docker how to build your image:
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "main.py"]
This Dockerfile:
- Uses a lightweight Python 3.11 image (
slimreduces size). - Sets
/appas the working directory. - Installs dependencies without caching (to save space).
- Copies your code into the container.
- Runs
main.pywhen the container starts.
Step 4: Create the docker-compose.yml File
Finally, create docker-compose.yml to define your service:
version: '3.8'
services:
web:
build: .
ports:
- "5000:5000"
restart: always
This Compose file:
- Builds the image from the current directory (
build: .). - Maps port 5000 on your machine to port 5000 in the container.
- Ensures the container restarts if it crashes.
Running Your App with Docker Compose
With all files in place, you’re ready to deploy. Run this command in your project directory:
docker compose up --build
The --build flag ensures Docker builds your image before running it. You’ll see output showing the build process, followed by your Flask app starting:
[+] Building 2 steps
...
web_1 | * Running on http://0.0.0.0:5000
Now, open your browser or use curl to test:
curl http://localhost:5000
You should see:
{"message": "Hello from Dockerized Python!", "status": "success"}
Your Python app is now running in a container, isolated from your system, and ready to be shared.
Scaling Up: Adding Databases and Workers
What if your app needs more than just Flask? Let’s add a PostgreSQL database and a Redis cache.
Update your docker-compose.yml:
version: '3.8'
services:
web:
build: .
ports:
- "5000:5000"
depends_on:
- db
- redis
environment:
- DATABASE_URL=postgres://user:password@db:5432/mydb
- REDIS_URL=redis://redis:6379
db:
image: postgres:15-alpine
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: mydb
volumes:
- db_data:/var/lib/postgresql/data
redis:
image: redis:7-alpine
ports:
- "6379:6379"
Now, your web service depends on db and redis, so Compose starts them first. The volumes line ensures your database data persists even if you restart the container.
Update your main.py to use these services (example with psycopg2 and redis):
import redis
from flask import Flask, jsonify
app = Flask(__name__)
redis_client = redis.Redis(host="redis", port=6379)
@app.route("/")
def home():
count = redis_client.incr("hits")
return jsonify({"message": f"Hello! You are the {count}th visitor.", "status": "success"})
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)
Add psycopg2-binary and redis to your requirements.txt, rebuild, and run:
docker compose up --build
Visit http://localhost:5000 again. Each request increments a counter in Redis, proving your multi-service stack is working.
Debugging and Maintenance Tips
When things go wrong, Docker Compose makes debugging easier:
-
View logs:
docker compose logs web -
Stop services:
docker compose down -
Restart a service:
docker compose restart web -
Run a command in a container:
docker compose exec web python -c "print('Hello')"
For production, add a restart: always policy and use environment variables for secrets (never hardcode passwords). You can also push your image to Docker Hub with docker compose push if you defined an image name.
Take Action: Deploy Your App Today
You now have a complete, production-ready workflow for deploying Python apps with Docker Compose. No more manual setup, no more environment conflicts. Just define your stack, run one command, and ship.
Your next step: Clone this setup, replace main.py with your own app, and run docker compose up --build. Share your results on Dev.to and tag me—I’d love to see what you build.
Docker Compose isn’t just a tool; it’s your new standard for Python deployment. Start using it today, and never debug a dependency issue on a teammate’s machine again.
If you found this helpful, consider buying me a coffee ☕ — it keeps these articles coming!
Also check out my AI tools collection: AI 次元世界 — free AI tools for developers.
🛠️ Recommended Tool
If you found this useful, check out Content Creator Ultimate Bundle (Save 33%) — $29.99 and designed for developers like you.
Get instant access to our best-selling AI Dev Boost, HTML Landing Page Templates, AI Prompts for Developers, and Python Automation Scripts Pack, perfect for content creators and marketers looking to elevate their game. This bundle is a must-have for anyone looking to create stunning content, build high-converting landing pages, and drive real results. With these tools, you'll be able to create engaging content, build beautiful landing pages, and boost your online presence.
Top comments (0)