Chapter 4

Containerize a Static nginx Page

Build a small immutable nginx image, run it locally, and inspect its HTTP health endpoint.

Just started Saved in this browser.

A container packages your application and its runtime so it behaves the same on your laptop and in Kubernetes. Think of it as a shipping box: the contents and instructions travel together, so the destination does not need a custom install of nginx.

Source becomes an image, then a running container

Last updated: 2026-07-20

Audience

Who this chapter is for

This chapter is for beginners who completed Chapter 3 (or already have a working Docker engine). You will build and run one small image. No Kubernetes commands are required here.

Step by step

Download this chapter's files

Use your browser to download either ivia-chapter-04.tar.gz or ivia-chapter-04.zip. The archive is self-contained; you do not need this tutorial repository.

Open a terminal after the browser download:

cd ~/Downloads
tar -xzf ivia-chapter-04.tar.gz
cd ivia-chapter-04

All remaining relative paths in this chapter start from that extracted directory.

Do this

The challenge

Challenge: build simple-static:local, run it as a non-interactive container, and retrieve both the page and health endpoint.

Prepare

Prerequisites

  • Docker or a Docker-compatible CLI with a running engine.
  • The extracted Chapter 4 package, with your terminal in its top-level directory.
  • Port 8080 available locally.
  • No Kubernetes knowledge beyond Chapter 3 is required.
Outcome

Learning goals

After this chapter, you will be able to:

  • Read a simple Dockerfile from top to bottom
  • Distinguish image build time from container runtime
  • Map a host port to a container port
  • Validate HTTP behavior and clean up safely
  • Spot common build-context and port-binding mistakes
Step by step

Inspect the complete Dockerfile

We open the full file first so you can copy and understand it as one unit.

find static-app -maxdepth 2 -type f -print
sed -n '1,120p' static-app/Dockerfile

A typical reading of this Dockerfile:

  • FROM chooses the base image that already contains nginx.
  • COPY places your HTML, CSS, and nginx config into fixed paths inside the image.
  • EXPOSE documents the container port (8080); publishing that port happens at docker run.
  • CMD (or the base image’s default command) starts nginx when the container runs.

The COPY instructions make the page immutable: changing a source file does not change an already-built image until you rebuild. nginx listens on 8080, serves /usr/share/nginx/html, and returns ok from /healthz.

Also skim the nginx config:

sed -n '1,160p' static-app/nginx.conf

A .dockerignore (when present) keeps build context small by excluding files Docker should not send to the builder. Keep the final build argument as the static-app directory so paths inside the Dockerfile stay correct.

Step by step

Build and run

We tag the image simple-static:local so later chapters can find it by a stable name.

docker build \
  -t simple-static:local \
  static-app

docker image inspect simple-static:local --format '{{.RepoTags}}'
docker run --rm --name simple-static -d -p 8080:8080 simple-static:local

You should see a build that ends with Successfully tagged simple-static:local (wording may vary) and a container ID from docker run.

Validate from another terminal:

curl --fail http://localhost:8080/
curl --fail http://localhost:8080/healthz
docker logs simple-static

You should see HTML containing Hello from Kubernetes!, a health body of ok, and nginx access lines in the logs. Open http://localhost:8080 in a browser.

When finished:

docker stop simple-static

Because the container used --rm, stopping it also removes the container. The image remains available for Minikube in the next chapter.

Step by step

What each option means

  • -t simple-static:local gives the image a readable repository and tag.
  • -d runs in the background.
  • -p 8080:8080 forwards host port 8080 to container port 8080.
  • --rm removes the stopped container, keeping your environment tidy.
  • curl --fail returns a nonzero status for HTTP errors, which makes validation reliable.
Verify

Expected validation

The page response should contain Hello from Kubernetes!; the health response should be exactly ok. docker ps should show 0.0.0.0:8080->8080/tcp while the container runs. After stopping, this should return no row:

docker ps --filter name=simple-static
Troubleshoot

Troubleshooting and common pitfalls

  • Port already allocated: find the existing owner or map another host port, for example -p 8081:8080, then use http://localhost:8081.
  • Build context error: run from the extracted chapter directory and keep static-app as the final argument.
  • Page changes do not appear: rebuild the image; source is copied at build time. Browser hard-refresh if it cached the old page.
  • Container exits immediately: run docker logs simple-static before cleanup, or temporarily omit --rm so the stopped container remains inspectable.
  • Ignoring .dockerignore: large unrelated folders in the context slow builds; keep context scoped to static-app.
  • Apple Silicon warning about platform: use a multi-architecture official nginx image as provided; do not force amd64 unless your deployment requires it.
  • Using localhost inside a container: there it means that container, not your host or another container.
Practice

Recap and practice

Recap: You built an immutable nginx image, published port 8080, and verified page and health endpoints.

Try to explain in your own words:

  1. Why does editing HTML require a rebuild before the running container changes?
  2. What does -p 8080:8080 map, left side versus right side?

Exercise: Rebuild after a tiny HTML text change and confirm curl shows the new text.

Stretch (safe): Note the image size with docker images simple-static:local. Read the Dockerfile’s FROM line and, if you are comfortable experimenting, try an alpine-based nginx variant in a copy of the Dockerfile, rebuild under a different tag (for example simple-static:alpine-try), and compare sizes. Keep the original simple-static:local for Chapter 5.

Reference

Official references

Just started Saved in this browser.