Containerize an app and put it behind CI
A team ships by running scripts on their laptops, and "works on my machine" is a daily phrase. You give them a reproducible image and a pipeline that proves every change before it merges.
What you'll build
A lean, multi-stage Docker image and a CI pipeline that builds, tests, and publishes it on every push, red builds block merges.
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:
const http = require('http');
const server = http.createServer((req, res) => {
if (req.url === '/healthz') {
res.writeHead(200, { 'content-type': 'application/json' });
return res.end(JSON.stringify({ status: 'ok' }));
}
res.writeHead(200, { 'content-type': 'text/plain' });
res.end('hello from the container');
});
const port = process.env.PORT || 3000;
server.listen(port, () => {
// One structured startup line so logs are greppable.
console.log(JSON.stringify({ level: 'info', msg: 'listening', port }));
});
module.exports = server;Reading this file
req.url === '/healthz'A health endpoint. Load balancers and the Docker HEALTHCHECK hit this to ask "are you alive?" before sending real traffic.process.env.PORT || 3000Read the port from the environment, never hard-code it. The platform tells the container which port to use.console.log(JSON.stringify(...))Log one structured JSON line, not free text. Machines can parse it, so later you can search and alert on your logs.
A minimal service with the /healthz endpoint the HEALTHCHECK and milestone 4 depend on.
That's 1 of 8 explained code blocks in this single project.
The build, milestone by milestone
- 1
Write a real Dockerfile
6 guided stepsA bloated image with the whole build toolchain inside it is slow to pull, slow to start, and a bigger attack surface. Multi-stage builds ship only what runs.
- 2
Build the CI
6 guided stepsCI is the contract that "main is always shippable." If tests are green and the image builds, anyone can trust the branch.
- 3
Publish it
5 guided stepsAn image only on the CI runner is gone when the job ends. Publishing to a registry makes a specific, immutable build deployable anywhere.
- 4
Prove it runs healthy and costs little
5 guided stepsAn image that builds but has no signal of "alive vs wedged" is undeployable, and a registry/CI bill that nobody has ever looked at is how a weekend project quietly becomes a recurring charge.
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