Containerize Python with Docker on ECR
Containerize a Python app with Docker on ECR — AWS Cloud & DevOps with Python.
Focus: containerize a python app with docker on ecr
Your Python app runs perfectly on your laptop. Push it to a server, and suddenly it crashes because someone installed the wrong version of a library, or the OS is missing a system dependency. This "works on my machine" problem is the #1 cause of deployment failures in real-world DevOps. Docker solves that by packaging your app, its dependencies, and its runtime into a single, immutable artifact — a container image. In this lesson, you'll learn how to containerize a Python app with Docker on ECR, the AWS container registry, so you can deploy that image anywhere on AWS with total consistency.
The problem this lesson solves
Imagine you're a DevOps engineer. You've just finished a Flask web app that uses Redis and a custom Python package. You hand it to the ops team, but their Linux box has Python 3.6, your app needs 3.11. The Redis client is missing, and someone installed a conflicting version of requests. Deployment becomes a nightmare of manual fixes.
Docker eliminates this entire class of problems. By containerizing your Python app, you create a self-contained image that includes your code, all Python dependencies (from pip), and the base OS layer. When you push that image to Amazon ECR (Elastic Container Registry), you have a single, versioned artifact that can be pulled and run on any Docker-compatible host — EC2, ECS, EKS, or even your local machine. This is the foundation of modern CI/CD pipelines, so mastering it is essential for any cloud developer.
Core concept / mental model
Think of a container image as a shipment box for your app. Inside the box, you have everything needed to run: a tiny Linux OS, Python interpreter, your source code, and all third-party libraries. Docker is the packing factory — it uses a Dockerfile as the instruction manual for exactly how to build that box.
ECR is the warehouse where you store these boxes. Instead of physically moving them, you push your image to ECR and later pull it on any server. Each image has a unique tag (like v1.0.0 or latest) so you can keep multiple versions and roll back instantly.
Here's the mental map:
- Dockerfile → defines how to build the image (the recipe).
- docker build → executes the recipe and produces an image.
- docker push → uploads the image to ECR.
- docker pull → downloads the image to a deployment target.
- ECR → private or public registry that stores your images securely.
How it works step by step
Containerizing a Python app with Docker on ECR is a linear process. Here's the logical flow:
- Write a
Dockerfilein your project root. This file defines the base image (e.g.,python:3.11-slim), copies your code, installs dependencies, and sets the command to run your app. - Build the image locally with
docker build -t my-app .to verify it works. - Create an ECR repository in your AWS account to hold your images.
- Authenticate Docker to your ECR registry using the
aws ecr get-login-passwordcommand. - Tag your image with the ECR repository URI.
- Push the image to ECR.
- Optionally test by pulling the image and running a container from it.
Each step has a cause-and-effect: a well-formed Dockerfile yields a reproducible build; correct authentication gives push access; a versioned tag enables rollbacks.
Hands-on walkthrough
Let's containerize a simple Python Flask app. You'll need Docker installed and the AWS CLI configured with credentials that have ECR permissions.
Step 1: Create a minimal Flask app
First, create a project folder and add these files:
# app.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def home():
return 'Hello from containerized Python!'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
# requirements.txt
flask==3.0.0
Step 2: Write the Dockerfile
# Dockerfile
FROM python:3.11-slim
WORKDIR /app
# Copy only requirements first to leverage Docker caching
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy the rest of the application
COPY app.py .
EXPOSE 5000
CMD ["python", "app.py"]
Pro tip: Copy
requirements.txtseparately and runpip installbefore copying your code. This way, Docker can cache the dependency layer, so rebuilds are blazing fast when you only change app code.
Step 3: Build and test locally
docker build -t flask-hello .
docker run -d -p 5000:5000 --name test-app flask-hello
curl http://localhost:5000
# Output: Hello from containerized Python!
# Clean up if needed
docker stop test-app && docker rm test-app
Step 4: Create an ECR repository
aws ecr create-repository --repository-name flask-hello --region us-east-1
# Output includes the repositoryUri, e.g., 123456789012.dkr.ecr.us-east-1.amazonaws.com/flask-hello
Step 5: Authenticate and push
# Authenticate Docker to your ECR registry
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 123456789012.dkr.ecr.us-east-1.amazonaws.com
# Tag your image with the ECR repository URI
docker tag flask-hello:latest 123456789012.dkr.ecr.us-east-1.amazonaws.com/flask-hello:latest
# Push to ECR
docker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/flask-hello:latest
If you run docker images, you'll see your locally tagged image. The push output shows compressed layer uploads — that's ECR storing your image in AWS.
Step 6: Verify by pulling and running
# Optionally test from a separate machine
docker pull 123456789012.dkr.ecr.us-east-1.amazonaws.com/flask-hello:latest
docker run -d -p 5000:5000 flask-hello
You've now containerized a Python app with Docker on ECR — a production-ready artifact that can be deployed to ECS, EKS, or EC2 with zero environment surprises.
Compare options / when to choose what
There are several ways to containerize and store a Python app. Here's how Docker+ECR stacks up:
| Approach | Pros | Cons | Best for |
|---|---|---|---|
| Docker + ECR | Fully managed, secure, integrates with ECS/EKS | Requires AWS CLI setup | Production AWS deployments |
| Docker + Docker Hub | Simpler, public/private options | Extra cost for private repos, slower pull from AWS | Local dev, open-source projects |
| VMs (EC2 without containers) | Full control over OS | Heavier, slower startup, env drift | Legacy apps |
| AWS Elastic Beanstalk | Abstracts Docker, auto-scaling | Less control over image lifecycle | Simple web apps |
Choose ECR when you're all-in on AWS. Choose Docker Hub if you want a quick public demo. Use a VM if you're migrating a legacy monolith that can't be containerized.
Troubleshooting & edge cases
Here are common issues you'll hit:
denied: Your Authorization Token has expired: Re-runaws ecr get-login-password— tokens expire after 12 hours.no space left on deviceduring build: Docker cache and old images accumulate. Rundocker system pruneto clean up.- Port already in use (failure on
docker run -p 5000:5000): Change the host port, e.g.,-p 5001:5000. exec: "python": executable file not found: Your Dockerfile's CMD uses a Python that isn't in the image base. Double-check yourFROMbase (e.g.,python:3.11-slimincludes python).- ECR push fails with
retrying in X seconds: Network issue or large image. Check your internet connection and consider using a smaller base image. - Image size too large: Switch to
python:3.11-slimoralpinevariants, and use--no-cache-dirin pip.
What you learned & what's next
You now understand the core concept of containerize a Python app with Docker on ECR, from authoring a Dockerfile to pushing a versioned image to AWS. You applied the process hands-on with Flask, and you know how to troubleshoot common Docker and ECR errors.
This skill is the backbone of deploying Python services on AWS. The natural next step is learning to run your containerized app on Amazon ECS (Elastic Container Service) or EKS (Kubernetes) — that's where your image truly goes to work with auto-scaling and load balancing. You're ready to move from packaging to orchestration.
Practice recap
Now that you've containerized a Flask app, try containerizing a small Python CLI tool or a FastAPI service. Add a .dockerignore file to keep your image clean, and practice tagging with v1.0.0 before pushing. Then next lesson: we'll run that ECR image on ECS with a load balancer — see how it all glues together.
Common mistakes
- Forgetting to run
aws ecr get-login-password— you must re-authenticate Docker every 12 hours before pushing to ECR. - Copying the entire source code before installing dependencies — this breaks Docker layer caching and slows every rebuild.
- Using
latestas a tag for production — always use a versioned tag (e.g.,v1.0.0) to enable rollbacks. - Using
python:latestorpython:alpineblindly —slimis more reliable with compiled dependencies thenalpineif you're not comfortable with musl libc. - Not exposing the correct port — the
EXPOSEin your Dockerfile must match the port your app listens on or containers won't be reachable.
Variations
- Alternative registry: Use Docker Hub or GitHub Container Registry (GHCR) if you prefer a non-AWS option.
- Multi-stage Dockerfiles: Build dependencies in a temp stage, then copy only the ready virtualenv to a slim runtime image — reduces final image size dramatically.
- Use
docker-compose.ymlfor local multi-service Python apps (e.g., Flask + Redis) instead of running severaldocker runcommands manually.
Real-world use cases
- Deploy a Python Flask REST API to Amazon ECS with manual scaling — team uses ECR to version images and rollback in seconds.
- Run a Python data processing job (e.g., using pandas) on AWS Batch — image is stored on ECR and pulled on-demand.
- Ship a Python ML model (e.g., TensorFlow) served by FastAPI — model and dependencies packaged for GPU-enabled EC2 with Docker.
Key takeaways
- Docker packages your Python app, dependencies, and runtime into a portable image — fixing the 'works on my machine' problem.
- ECR is a fully managed registry that integrates naturally with ECS, EKS, and other AWS services.
- The workflow is: Dockerfile → build → tag → authenticate → push → pull/run.
- Use
python:3.11-slimas a reliable base image and install dependencies before copying your code for faster rebuilds. - ECR login tokens expire after 12 hours — re-authenticate with
aws ecr get-login-passwordbefore any push. - Tag images with semantic versions in production to enable rollbacks and traceability.
Keep learning
Related tutorials, quizzes, and articles for this topic.
Discussion
Questions, corrections, and tips help everyone reading this page.
0 comments
Add a comment
No comments yet — start the thread.