FastAPI Docker and CI
Introduction
Docker packages FastAPI, dependencies, and Uvicorn into a reproducible image. GitHub Actions runs pytest on every push. This chapter builds a production-oriented Dockerfile, docker compose with MySQL, and CI workflow linked to the Git track.
Prerequisites
Dockerfile
Dockerfile:
Production with workers:
CMD ["gunicorn", "app.main:app", "-k", "uvicorn.workers.UvicornWorker", "-w", "4", "-b", "0.0.0.0:8000"]Build and run:
docker build -t fastapi-app .
docker run -p 8000:8000 \
-e SECRET_KEY=dev-docker-key \
-e DATABASE_URL=sqlite:///./app.db \
fastapi-appCompare Flask Docker.
.dockerignore
.venv/
__pycache__/
.git/
.env
.pytest_cache/
tests/
*.mddocker compose
docker-compose.yml:
Sync apps may use mysql+pymysql instead of aiomysql—match your SQLAlchemy mode.
Run:
export SECRET_KEY=$(python -c "import secrets; print(secrets.token_hex(16))")
docker compose up --build
curl http://localhost:8000/healthGitHub Actions CI
.github/workflows/fastapi-ci.yml:
Code explanation:
- Tests use in-memory SQLite via
dependency_overridesinconftest.py - Remove
|| trueonpip auditwhen enforcing strictly
Protect main—require CI pass before merge per Git CI/CD.
Deploy Pipeline (Concept)
push → CI (pytest) → build image → push registry → server pull → compose up -dTag images with Git SHA for rollback.
Migrations in Containers
Run alembic upgrade head in container start command or one-off init job before traffic switch.
Secrets in Compose
Use .env file (gitignored):
SECRET_KEY=replace-me
MYSQL_PASSWORD=replace-meNever commit real passwords in docker-compose.yml.
FAQ
ModuleNotFoundError app.main?
WORKDIR, PYTHONPATH, or missing COPY of package.
DB not ready on start?
depends_on + healthcheck; retry logic optional.
Image too large?
Slim base, multi-stage build, .dockerignore.
CI passes, prod fails?
Prod uses MySQL—add optional MySQL service job in CI for integration tests.
Build and push image in CI?
Add docker/build-push-action after tests on main.
Redis service unused?
Remove from compose until Redis chapter features needed.