BeginnerCloud Engineer

Containerise and deploy a FastAPI app

Take a simple FastAPI application and write a production-quality Dockerfile: multi-stage build to minimise image size, a /health endpoint that returns 200, and a non-root user for the container process. Deploy the image to AWS ECS Fargate via ECR and confirm the health check passes in the AWS console.

Why this matters

Containerisation is now a baseline skill for any cloud role, and the gap between a working Dockerfile and a production-ready one is large. Multi-stage builds, non-root users, and health checks are not optional in a real environment; they are the difference between an image your security team accepts and one they reject at the gate.

Before you start

Step-by-step guide

  1. 1

    Add a /health endpoint

    Add a GET /health route to your FastAPI app that returns {status: ok} with a 200 status code. This is the endpoint ECS will poll to know whether your container is healthy. Keep it dependency-free; it should return 200 even if your database is unavailable.

  2. 2

    Write the multi-stage Dockerfile

    Stage 1 (builder): use python:3.12-slim, install dependencies into a virtual environment. Stage 2 (runtime): copy only the venv from the builder, not the build toolchain. This typically halves the final image size. Add EXPOSE 8000 and a CMD that starts uvicorn.

  3. 3

    Add a non-root user

    In the runtime stage, add: RUN adduser --disabled-password appuser and USER appuser before the CMD. Build and run the container locally. Exec into it with docker exec -it <id> sh and verify whoami returns appuser, not root.

  4. 4

    Push to ECR

    Create an ECR repository, authenticate Docker to ECR with aws ecr get-login-password, tag your image, and push it. Verify the image appears in the ECR console before touching ECS; it is a common mistake to push to the wrong registry URI.

  5. 5

    Deploy to ECS Fargate and verify the health check

    Create an ECS task definition pointing to your ECR image. Configure the health check as: command ['CMD-SHELL', 'curl -f http://localhost:8000/health || exit 1'], interval 30s, timeout 5s. Deploy the task and watch the health check status in the ECS console; it should transition from UNKNOWN to HEALTHY within 90 seconds.

Relevant Axiom pages

What to do next

Back to Practice Lab