Section 6.3: Containers, Databases and Pipelines
A service that runs on one laptop, from one folder, still depends on everything that laptop happens to hold. This section packs the prediction service into a Docker image that carries its own Python, its locked libraries and its exported model, puts PostgreSQL beside it in a container of its own so every prediction is written to a real database, rebuilds the image in layers that keep a code change to seconds, starts both with one docker compose file, and ends with a GitHub Actions workflow that tests every push to main and every pull request against a fresh database and builds and smoke-tests the image before anything is shipped.
Section 6.2 served the champion from the project's own process. Here the service leaves it, and each boundary has its own way to fail. A first image built from the whole folder weighs 2.06 GB, the project's own .venv copied in and then rebuilt, where a .dockerignore makes it 1.12 GB. A server that listens on 127.0.0.1 inside its container answers nobody outside it. A connection string that says localhost inside a container reaches the container itself, so the service stops at startup, while the same string worked from the host. And a lock left behind by a hand edit of pyproject.toml passes every test on the laptop and stops the workflow at its first command.
Lessons
- Docker - Images and Containers - exporting the model into the project, a first Dockerfile, building the image and its layers, the build context and
.dockerignore, and running a container with-pand--host 0.0.0.0. - A Real Database Behind the Service - PostgreSQL in its own container, the connection string and psycopg,
db.pywith one connection and ajsonbtable, every prediction written, a database test that skips, andlocalhostinside a container. - Containers Done Right - the service's dependencies apart from the tools', a Dockerfile in layers, the cache mount, retraining after the split,
docker composeand the.envfile, and healthchecks,depends_onand the named volume. - Automated Pipelines - a workflow file, the test job and its database, the image job and its smoke test, pushing to GitHub and reading the run, and a stale lock that stops it.
By the end you will be able to:
- Build an image that serves the model, read its layers and its size, keep the build context small, and run it so the host can reach it.
- Run PostgreSQL in its own container, reach it by name on a network, and write and read every prediction through psycopg.
- Split what the service needs from what the tools need, layer a Dockerfile so a code change rebuilds in seconds, and run the service and its database together with
docker compose. - Write a GitHub Actions workflow that tests against a database, builds and smoke-tests the image, and stops on a lock that no longer matches.