Containerization with Docker Assignment
Assignment Metadata
| Field | Description |
|---|---|
| Assignment Name | Containerizing a Python Application with Best Practices |
| Course | Basic DevOps Essentials for Developer |
| Project Name | docker-python-app |
| Estimated Time | 120 minutes |
| Framework | Docker 24+, Python 3.11+ |
Learning Objectives
After completing this assignment, you will be able to:
- Create optimized Dockerfiles for Python applications
- Implement multi-stage builds to reduce image size
- Configure proper layer caching for faster builds
- Apply security best practices (non-root users, secrets management)
- Utilize .dockerignore to exclude unnecessary files
- Verify image security using vulnerability scanning tools
Prerequisites
- Docker installed locally (Docker Desktop or Docker Engine)
- Basic understanding of Python application structure
- Familiarity with command line operations
Tasks
Task 1: Create a Basic Dockerfile (20 points)
-
Create a simple Python web application (FastAPI or Flask):
- Create
app.pywith a basic health endpoint (/health) - Create
pyproject.tomlorrequirements.txtwith dependencies
- Create
-
Write an initial Dockerfile that:
- Uses
python:3.11-slimas base image - Sets appropriate environment variables (
PYTHONDONTWRITEBYTECODE,PYTHONUNBUFFERED) - Copies and installs dependencies
- Exposes the application port
- Sets the default command to run the application
- Uses
-
Build and test the image:
docker build -t myapp:v1 .
docker run -d -p 8000:8000 myapp:v1
Task 2: Optimize Layer Caching (20 points)
-
Analyze the current Dockerfile for caching issues
-
Refactor to optimize caching:
- Copy dependency files before application code
- Combine RUN commands to reduce layers
- Order instructions from least to most frequently changed
-
Document the changes and explain why each optimization improves build time
Task 3: Implement Multi-stage Build (25 points)
-
Create a multi-stage Dockerfile with:
- Builder stage: Install build dependencies and compile/install packages
- Runtime stage: Copy only necessary artifacts from builder
-
Compare image sizes:
Stage Image Size Single-stage ? MB Multi-stage ? MB -
Implement build targets for different environments:
development: Include dev tools (pytest, ruff)production: Minimal runtime only
-
Build specific targets:
docker build --target development -t myapp:dev .
docker build --target production -t myapp:prod .
Task 4: Implement Security Best Practices (25 points)
-
Create a non-root user and run the container as that user
-
Create a
.dockerignorefile excluding:.git,__pycache__,.venv- Test files and documentation
- Environment files (
.env)
-
Add a HEALTHCHECK instruction to monitor application health
-
Scan the image for vulnerabilities using Docker Scout or Trivy:
docker scout cves myapp:prod
# or
trivy image myapp:prod -
Document any vulnerabilities found and mitigation strategies
Task 5: Volume and Port Configuration (10 points)
-
Configure volumes for:
- Persistent data storage
- Configuration files (read-only)
-
Document port mapping requirements
-
Create a
docker-compose.ymlfor local development that includes:- Volume mounts for hot-reload
- Environment variable configuration
- Health check configuration
Submission Requirements
Required Deliverables
- Source code for Python application
- Optimized multi-stage
Dockerfile -
.dockerignorefile -
docker-compose.ymlfor development -
README.mdwith build and run instructions - Screenshots of running container and vulnerability scan results
Submission Checklist
- Docker image builds without errors
- Application runs correctly in container
- Multi-stage build implemented with measurable size reduction
- Non-root user configured
- Health check working
- Vulnerability scan completed
Evaluation Criteria
| Criteria | Points |
|---|---|
| Basic Dockerfile creation | 20 |
| Layer caching optimization | 20 |
| Multi-stage build implementation | 25 |
| Security best practices | 25 |
| Volume and port configuration | 10 |
| Total | 100 |
Hints
- Use
docker history <image>to inspect layer sizes - Use
docker imagesto compare image sizes before and after optimization - Start with the official Python slim images for smaller base size
- Always specify exact version tags for reproducibility
- Test your health check with
docker inspect --format='{{.State.Health.Status}}' <container>