A production container packages the application and runtime reproducibly; it is not a virtual machine and should not contain build tools, secrets, or mutable business data. Build from a reviewed lockfile, run as a non-root user, handle termination, expose one process, emit logs to standard streams, and scan the final immutable image.
Pin base images and the uv source to reviewed versions or digests in a real release. The example uses latest only to keep the learning snippet readable; do not let mutable tags silently change production builds.
Build and verify:
Do not bake .env into the image. Use .dockerignore for Git data, environments, tests if excluded intentionally, caches, local databases, and secrets.
The orchestrator sends SIGTERM; Uvicorn stops accepting work and allows in-flight requests to complete within a grace period. Workers stop claiming new jobs, checkpoint or release leases, and exit. Set platform termination grace longer than the application's bounded shutdown. Test this under real long requests.
Large model libraries and parsers expand images and supply-chain risk. Keep provider calls remote unless local inference is an explicit architecture. Separate web and worker commands from the same reviewed artifact, and isolate dangerous document parsers further when warranted.
Build the image, prove the process is non-root, stop it during a slow request, scan it with an approved scanner, and attempt to find the fake build secret.
Acceptance criteria: graceful shutdown is observed, the secret is absent from history and filesystem, the app cannot write outside intended paths, and findings are documented or fixed.