Docker & Production Deployment Expert
When to Apply
- •Writing or reviewing Dockerfiles for Python apps
- •Managing env vars and secrets in containers
- •Defining dependencies (requirements.txt) or build context (.dockerignore)
- •Setting up CI/CD for Docker builds and tests
Dockerfile Best Practices
Single-Stage (Typical Python App)
- •Base:
FROM --platform=linux/arm64 python:3.11-slim(or match target platform). - •
WORKDIR /app. - •Install system deps only if needed (
gcc,g++for compiled packages); clean apt cache. - •
COPY requirements.txt .thenpip install --no-cache-dir -r requirements.txt. - •Copy app (
src/,main.py,data/), create output dirs. - •Set
ENV PYTHONUNBUFFERED=1,ENV PYTHONPATH=/app. - •Run as non-root: create user,
chown,USER appuser. - •
CMD ["python", "main.py"]. - •Optional:
HEALTHCHECKwith a simple probe.
Multi-Stage (When Build Deps Differ from Runtime)
- •Builder stage: install build deps and Python packages into
/root/.local(or venv). - •Runtime stage: same slim base;
COPY --from=builder /root/.local /root/.local; setPATH; copy app only. Reduces image size and separates build/runtime.
Secrets and Environment
- •Do not hardcode API keys or secrets in Dockerfile or image.
- •Use empty placeholders in Dockerfile if needed:
ENV GEMINI_API_KEY="". - •Pass at run time:
docker run --env-file .env ...or-e VAR=value. Add.envto.gitignoreand.dockerignoreso it never goes into the image.
Volume Mounting (Development)
- •Mount data read-only:
-v $(pwd)/data:/app/data:ro. - •Mount outputs read-write:
-v $(pwd)/outputs:/app/outputs:rw.
Requirements.txt
- •Pin versions:
numpy==1.24.3,pandas==2.0.3, etc. - •Group logically: core (numpy, pandas, matplotlib, seaborn), LLM APIs, config (python-dotenv, pydantic), logging, optional (statsmodels), dev (pytest, mypy).
.dockerignore
Exclude to keep build context small and avoid copying secrets or caches:
- •Python:
__pycache__/,*.py[cod],*.so,venv/,env/,*.egg-info/,dist/,build/ - •IDE:
.vscode/,.idea/ - •Env:
.env,.env.local,*.key - •Git:
.git/,.gitignore - •Docs/tests:
README.md,docs/,tests/,*.pytest_cache/ - •Outputs:
outputs/(generated in container)
Docker Commands Reference
bash
# Build docker build --platform linux/arm64 -t llm-forecaster . # Run docker run --rm --env-file .env llm-forecaster # Run with volumes (dev) docker run --rm --env-file .env \ -v $(pwd)/data:/app/data:ro \ -v $(pwd)/outputs:/app/outputs:rw \ llm-forecaster # Debug docker run --rm -it --env-file .env llm-forecaster /bin/bash docker logs <container_id>
CI/CD Pattern (e.g. GitHub Actions)
- •On push/PR to
main: checkout, set up Docker Buildx, build image (e.g.--platform linux/arm64), tag with${{ github.sha }}. - •Run tests inside container:
docker run -e GEMINI_API_KEY=${{ secrets.GEMINI_API_KEY }} llm-forecaster:${{ github.sha }} python -m pytest tests/. - •Store API keys in repository secrets; never in workflow file or image.
Checklist
- • No secrets in Dockerfile or committed files
- • Non-root user in container
- • PYTHONUNBUFFERED and PYTHONPATH set
- • requirements.txt versions pinned
- • .dockerignore excludes venv, cache, .env, outputs
- • Build platform matches deployment (e.g. linux/arm64)
- • CI runs tests in built image with secrets from vault/secrets
Additional Resources
- •For Dockerfile snippets, .dockerignore list, run commands, and CI snippet, see reference.md.