Cloud / DevOps Engineer · Projects
Project 1: An environment from code
Marking guide version 1 · Lessons: CD1 lessons 2–4, CD2 lessons 1–2 and 4–5, CD3 lessons 2–5, CD10 lesson 2
The problem and who it's for
RouteRani's environment works, but only just. The image is 1.6 GB and runs as root; the database password is written in the Terraform files;
the database is published on the host and keeps its data inside the container; there's one API copy using latest; and nobody is sure a
rebuild would come out the same. Priya, who books the Jaipur–Udaipur bus every month, shouldn't lose her booking because someone replaced a
container.
Scope
- Rebuild the image: pinned slim base, two stages,
.dockerignore, a non-root user, a health check on/ready, and starting Node.js directly. - Pin the providers, generate the database password, and remove every literal password and
latesttag from the Terraform files. - Make the database private (no published port), give it a named volume, a health check and
wait = true. - Run
app_countAPI copies (default 2) withapp_version, unique names,create_before_destroy, memory limits andwait = true. - Add the
app_containersandapp_versionoutputs, and show no drift, drift repair and a clean destroy and rebuild.
Not included
- A real cloud account (CD6's design notes cover the cloud version on paper).
- Remote state (CD4's design notes cover it).
- Kubernetes (CD5).
Before you start
- Core: Module 63 (Introduction to Linux), Module 68 (Cloud Architecture), Module 69 (Docker).
- Path: CD1, CD2 and CD3 complete.
- The kit installed, with
npm run test:infrarunning (most of its 10 tests fail at first).
Starter files
routerani/README.md: setup, run and test commands.routerani/app/Dockerfile: a full, unpinned base, everything copied in, root user, no health check, started through npm.routerani/infra/main.tf: a literal password, a published database with no volume, one copy usinglatest.routerani/infra/versions.tf: the Docker provider with no version.routerani/infra/variables.tf: noapp_versionorapp_countyet.routerani/tests/infra.test.js: the 10 acceptance tests for this project.
Download everything at once: starter/cloud-devops-starter.zip.
Milestones
- Run
npm run test:infraand note which of the 10 tests fail and why. - Rewrite the Dockerfile and add
.dockerignore(test 3). - Pin providers, generate the password and remove
latest(tests 1 and 2). - Make the database private with a volume and health check (tests 6 and 9).
- Add the variables, copies, outputs and lifecycle settings (tests 4, 5, 7 and 8).
- Run destroy and rebuild (test 10), then all 10 tests twice in a row.
Expected outputs
- 10 of 10 infra tests passing, twice in a row.
- Image size before and after, and
docker run --rm --entrypoint id routerani:1.0.0 -uprinting a number other than 0. terraform plan -detailed-exitcodereturning 0 right after apply.
Acceptance tests
| # | Input | Expected result |
|---|---|---|
| 1 | npm run test:infra |
10 of 10 pass, twice in a row |
| 2 | git grep -n routerani123 in your kit |
No results |
| 3 | docker inspect on the database container |
No published ports; status healthy (test 6) |
| 4 | A booking, then terraform apply -replace=docker_container.db |
The booking is still there (test 9) |
| 5 | docker rm -f one API copy, then terraform plan -detailed-exitcode and apply |
Exit code 2, then the copy is back and the next plan exits 0 (tests 7 and 8) |
| 6 | terraform destroy, then terraform apply |
Nothing left behind after destroy; 40 routes served after the rebuild (test 10) |
Failure and recovery exercises
- Stop the database container by hand during traffic. Write down what
/readyreturns, what nginx does, and whatterraform planshows. Then repair it withterraform apply. - Add
depends_on = [docker_container.db]to the API copies and tryterraform apply -replace=docker_container.db. Explain the error in two sentences, then remove it. - Remove
memory_swapand runterraform planright after an apply. Explain the change it shows, then put it back.
Evidence to submit
- Link to your repository or a shared folder with the kit and your changes: the deliverable link.
- The output of
npm run test:infrashowing 10 passed, pasted into test evidence. - The image sizes before and after, and the output of the destroy and rebuild.
- Your explanation: where the password comes from, why the database is private, and how a new version can start before the old one stops.
Marking guide and self-check
Pass rule: every Safety-critical (S) and Mandatory (M) item must be met. A single unmet safety item means the project is not complete, whatever else is done. Quality items are for your own improvement.
Your answers are saved in this browser on this device. Self-checked means you checked your own work against this guide; it is not a reviewer's approval. Never paste passwords, keys, tokens or real customer data here.
