Docker Advanced: Security, Limits and Production
Builds, CI and Deployment
In this lesson you will
- Describe a build, test, scan and push pipeline for images
- Tag images so every deployment can be traced and rolled back
- Apply twelve-factor style configuration
Introduction
Building and running images on your laptop does not scale to a team. In production, images should be built the same way every time, by an automated pipeline, and deployed in a way you can trace and undo.
A typical pipeline
- Commit triggers the pipeline.
- Build the image from the Dockerfile.
- Test, often by running tests inside the built image.
- Scan for vulnerabilities and leaked secrets.
- Tag and push to a registry.
- Deploy that exact image to staging, then production.
The most important idea: build once, deploy the same image everywhere. Do not rebuild for production. Differences between environments come from configuration, not from different images.
Tagging for traceability
Tag each image with something that tells you exactly what it contains, such as the Git commit:
Terminal
docker build -t registry.example.com/team/my-app:3f9a2c1 .
docker push registry.example.com/team/my-app:3f9a2c1You can add human-friendly tags such as a release number too. With a commit-based tag, you can always answer "which code is running?", and rollback is simply deploying the previous tag.
Quick quiz
Why is tagging an image with the Git commit hash useful?
Configuration from the environment
The twelve-factor app guidelines suggest keeping config out of the code and in the environment, for example database addresses and API keys. The same image then runs in development, staging and production with different values. Keep secrets in a secrets store, not in the image or the repository.
Also design containers to be stateless: keep data in databases, volumes or external services, so any container can be replaced at any time.
Build speed
- Order the Dockerfile so dependency layers stay cached.
- Use a cache in CI, since fresh build servers start empty.
- Use multi-stage builds and a tidy
.dockerignore. - Consider building for more than one CPU architecture if your servers differ from your laptop, for example Intel versus ARM.
A simple deployment
For a single server, Compose can be enough:
Terminal
docker compose pull # get the new image version
docker compose up -d # recreate changed containers
docker compose ps # check they are healthyKeep the previous version available so you can switch back quickly. Add health checks, so a bad release is noticed. For bigger setups, move to an orchestrator (next lesson).
Release habits
- Small, frequent releases are easier to understand and undo.
- Staging first: test with production-like config before real users see it.
- Monitor after each deployment, and know your rollback command.
- Record what was deployed, when, and by whom.
Try it yourself
Write down your pipeline as a numbered list for one of your projects. Mark which steps are automatic and which are manual, and decide your tag format and how you would roll back.
Summary
- Build once in a pipeline, test and scan, then deploy the same image everywhere.
- Tag with commit hashes for traceability, and roll back by deploying the previous tag.
- Keep configuration in the environment and containers stateless, and release in small steps.
Lesson complete
+20 XP
Nice work. Keep going while it is fresh.
Sources and further reading