Images and scans
After this you can answer: Why build an image once and deploy the same bytes, and what does the scan block?
Picture it
Section titled “Picture it”flowchart TB C["commit 1a2b3c4"] --> CI["CI: build x86 + Trivy scan<br/>(nothing pushed)"] C --> P["CD publish: build ARM64<br/>push :1a2b3c4"] P --> E[("ECR, immutable tags")] E -->|"same bytes"| D["deploy: run :1a2b3c4<br/>tag deployed-1a2b3c4"]How it works
Section titled “How it works”- CI proves the Dockerfiles: it builds all three images for x86 and scans them. Nothing is pushed.
- CD publish builds the real images for ARM64 on an ARM runner (Fargate and Lambda run ARM64)
and pushes them as
:<sha>. An existing tag is skipped, so a rerun succeeds. - ECR scans on push too (
scanOnPush, a basic scan). - deploy runs those bytes. It never builds. In phase B it adds a second tag,
deployed-<sha>, to the same image (same digest). - Lifecycle rules clean up without deleting rollback targets.
In MiniTickets
Section titled “In MiniTickets”| Lifecycle rule (per repository) | Keeps |
|---|---|
1. tag deployed-* | the newest 10 deployed images: the rollback targets |
| 2. any other tag | the newest 30 published images |
| 3. untagged | 1 day |
Rule 1 runs first, so a deployed image is safe even when 30 newer, never-deployed images exist. Before this rule, the running image could be expired after enough pushes, and ECS could not start a replacement task.
The Trivy scan (severity: CRITICAL, ignore-unfixed: true, exit-code: 1) fails CI on critical
findings that have a fix. .trivyignore holds one dated exception, CVE-2023-45853 in Debian’s zlib,
which expires on 2026-11-14 and must then be reviewed again.
The api and web images run as the unprivileged node user. The worker image starts from AWS’s
Lambda base image.
See it in AWS
Section titled “See it in AWS”ECR → Repositories → minitickets-dev-api → Images (each SHA, and deployed- tags) →
Lifecycle policy.
aws ecr describe-images --repository-name minitickets-dev-api
infra/src/registry.ts → createRegistry and the scan steps in
.github/workflows/ci.yml → docker.
Break it
Section titled “Break it”| Symptom | Cause | Where to look |
|---|---|---|
CannotPullContainerError | The tag was never pushed, or the image is not ARM64 | ECR → the repository |
| A push is refused: tag already exists | Tags are immutable; publish should have skipped it | The publish job’s check step |
| CI fails at a scan step | A fixable critical CVE in a base image or a dependency | Trivy’s table in the log |
Say it in an interview
Section titled “Say it in an interview”Follow-ups
Section titled “Follow-ups”Why not rebuild the image in the deploy job?
A rebuild can pull newer base images or packages, so it would not be what was tested and scanned. Promoting one build removes that difference.
Why ignore unfixed findings?
A finding with no fix cannot be acted on, and failing on it would block every build. The trade-off: those findings stay invisible unless someone reads the full report.
How do you add a deployed tag without a new image?
Read the image’s manifest and put it again under the new tag. Same manifest bytes give the same digest, and CD checks that the digest did not change.
Advanced: Details: the publish build
Source difference: docs/20-deploy-day.md says unfixed Trivy findings are included in the
failure gate. The book follows .github/workflows/ci.yml: ignore-unfixed: true (the
--ignore-unfixed option) excludes findings without a fix. The old step notes stay frozen.
provenance: false keeps each tag one plain ARM64 image; Lambda refuses image indexes. Layer
caches are per image and per platform (api-arm64 in CD, api in CI), so they do not overwrite each
other (.github/workflows/cd.yml → publish).
Checkpoint
Section titled “Checkpoint”Answer these without scrolling up. If one feels hard, reread that section.
- What does “immutable tag” guarantee?
- Why does CI build images it never pushes?
- Which lifecycle rule protects rollback targets?
- What does the Trivy scan fail on?
- Why must the images be ARM64?
Redraw it from memory: commit → CI (x86 build + Trivy, no push) and CD publish (ARM64 → ECR :sha) → deploy runs the same digest + deployed-sha tag
Try this: on the map, select the ECR repositories and see which jobs and services connect to them
Read this book online: https://book.theversehub.in/