Harden the container it ships in
Continues from the last build: Dependencies are scanned, an SBOM exists, and updates are automated.
Last rung you got dependency risk under control: Trivy scans the lockfile, an SBOM lists every package that ends up in the image, and Dependabot opens PRs when a CVE lands.
What you'll build
The image is a multi-stage build on a distroless or slim runtime base with no toolchain and no shell where you can avoid it, and no secrets in any layer, verified with docker history and trivy image --scanners secret. It runs as a non-root USER with a read-only root filesystem and a scoped tmpfs. Trivy image scanning is wired into the pipeline as a hard gate: HIGH and CRITICAL findings fail the build and the image is never pushed to the registry. You can point to a real before and after finding count, and explain exactly what remains in the after count and why it cannot be fixed by changing your Dockerfile.
See how we teach, before you sign up
You don't just get code dumped on you. Every starter file and every solution is explained line-by-line, in plain English. Here's one real file from this project:
FROM node:20 WORKDIR /app COPY . . COPY .env /app/.env RUN npm install RUN npm run build EXPOSE 3000 CMD ["npm", "start"]
Reading this file
FROM node:20full Debian-based image, ships apt, python3, build-essential, and a shell, all of it ends up in the image you run in productionCOPY .env /app/.envbakes the secret file into a layer permanently, deleting it in a later RUN would not remove it from image historyRUN npm installsingle unstaged install pulls in devDependencies too, and there is no later stage to leave them behindCMD ["npm", "start"]runs as whatever user the base image defaults to, root, because there is no USER instruction anywhere in this file
The current production Dockerfile. Single stage, full Debian base, root user, and a secret copied straight into a layer.
That's 1 of 8 explained code blocks in this single project.
The build, milestone by milestone
- 1
Scan the image and establish the baseline
5 guided stepsYou cannot prove you hardened anything without a before number. Teams that skip this end up hand-waving 'much more secure' with nothing to show a reviewer or an auditor.
- 2
Multi-stage build and minimize the runtime image
5 guided stepsEvery extra binary in the final image, a shell, a compiler, curl, apt, is a tool a compromised process can use to explore, pivot, or exfiltrate. The build toolchain has zero reason to exist in production.
- 3
Drop root and privileges
5 guided stepsA root process in a container is one kernel exploit or misconfigured mount away from root on the host. The injection and IDOR bugs fixed in earlier rungs become far less dangerous to an attacker if the shell they eventually land in has no write access and no root.
- 4
Re-scan and compare, document what remains
5 guided stepsA green scan is not the same as secure. A reviewer or an auditor will ask what is still open and why you accepted it, and an honestly documented exception beats a silently ignored finding every time.
- 5
Gate image builds in the pipeline
6 guided stepsA hardened Dockerfile that nobody enforces drifts back toward root and bloat within a few pull requests. The gate is what makes the hardening durable instead of a one-time cleanup.
What's inside when you start
You'll walk away with
This is portfolio-grade. Build it free.
Sign up to unlock every milestone step-by-step, the code skeletons, full reference solutions, and checkable tasks, with your progress saved as you build.
Start building