Docker Fundamentals · Module 12 of 12

Troubleshooting and Compose capstone

Use a repeatable troubleshooting method and assemble the course concepts into a small multi-service Compose project.

Learning objectives

By the end of this module, you should be able to:

  • Troubleshoot container failures from process, image, network, storage and configuration evidence.
  • Use docker compose config, ps, logs and exec systematically.
  • Complete a multi-service capstone using build, network, storage and health concepts.

Troubleshoot from facts, not guesses

Start with the symptom and scope. Confirm container state, exit code, logs, image reference, runtime configuration, mounts and network membership. Reproduce with the smallest useful test before changing multiple variables at once.

Common failure domains

Immediate exit often points to the main process or command. Connection failures can involve listening addresses, wrong ports, missing network membership or name resolution. Permission errors can involve UID/GID, read-only paths or host bind-mount permissions. Missing data often means the expected volume was not mounted.

Capstone: one reproducible project

The capstone uses a custom static web image plus Redis in Compose. It demonstrates image build, service naming, private networking, published frontend access, persistent Redis storage and health checks. The web page is static; Redis is included as an infrastructure service so learners can inspect a multi-service topology without requiring application dependencies.

Worked examples

See the idea in practice.

First-response command set

docker compose config
docker compose ps -a
docker compose logs --tail 100
docker inspect CONTAINER_NAME
docker network inspect NETWORK_NAME
docker volume inspect VOLUME_NAME
  • Validate configuration before changing it.
  • Inspect the failed object and the resources it depends on.
  • Use targeted commands rather than broad cleanup operations.

Exit-code evidence

docker inspect failed-container --format 'status={{.State.Status}} exit={{.State.ExitCode}} error={{.State.Error}}'
  • The Engine state can reveal whether the process exited and with what code.
  • Application logs explain why more often than the exit code alone.
Hands-on lab

Capstone — Build and operate a small Compose stack

Goal: Build a custom frontend image, run it with a private Redis service and persistent volume, verify health/networking, then recreate the stack safely.

Before you start

  • Ports 8080 must be available.
  • The lab pulls nginx:alpine and redis:7-alpine from a registry.
STEP 1

Create project files

mkdir -p ~/docker-fundamentals/capstone && cd ~/docker-fundamentals/capstone
printf '<h1>GNU Group Docker Capstone</h1>\n' > index.html
cat > Dockerfile <<'EOF'
FROM nginx:alpine
COPY index.html /usr/share/nginx/html/index.html
HEALTHCHECK --interval=10s --timeout=3s --retries=3 CMD wget -qO- http://127.0.0.1/ >/dev/null || exit 1
EOF
STEP 2

Create compose.yaml

cat > compose.yaml <<'EOF'
services:
  web:
    build: .
    ports:
      - "8080:80"
    depends_on:
      cache:
        condition: service_healthy
  cache:
    image: redis:7-alpine
    command: ["redis-server", "--appendonly", "yes"]
    volumes:
      - redis-data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 5
volumes:
  redis-data:
EOF
STEP 3

Validate and start

docker compose config
docker compose up -d --build
docker compose ps
STEP 4

Verify web, shared network and Redis service

curl http://127.0.0.1:8080/
docker inspect "$(docker compose ps -q web)" --format '{{json .NetworkSettings.Networks}}'
docker inspect "$(docker compose ps -q cache)" --format '{{json .NetworkSettings.Networks}}'
docker compose exec cache redis-cli SET course docker
docker compose exec cache redis-cli GET course
STEP 5

Recreate containers without deleting the volume

docker compose down
docker compose up -d
docker compose exec cache redis-cli GET course
STEP 6

Inspect and clean up deliberately

docker compose ps
docker compose logs --tail 50
docker compose down -v

Verify

  • The custom web image builds and serves the expected page.
  • Compose waits for cache to report healthy before starting the dependent web service; the web service's own health check separately reports whether web itself becomes healthy.
  • The Redis value survives docker compose down/up because the named volume remains.
  • The final down -v intentionally removes the lab volume.

Expected outcome

  • curl returns the capstone heading; Redis returns docker before and after container recreation.

If it fails

  • If web remains pending/start fails, inspect docker compose ps and cache health logs.
  • If Redis data disappears before down -v, verify the redis-data:/data volume mapping and that append-only persistence is enabled.
  • If port 8080 is occupied, change only the host side of the port mapping.
Real-world connection

A disciplined operator validates the declarative model, observes state/logs, isolates the failing dependency and makes the smallest controlled change—skills that transfer directly into Kubernetes troubleshooting later.

Avoid these traps

Common mistakes

  • Running docker system prune -a or docker compose down -v as a first troubleshooting step.
  • Changing image, network and storage settings simultaneously, which destroys useful evidence.
  • Treating successful startup as proof that persistence and recovery have been tested.
Knowledge check

Can you explain it without looking back?

Open each answer only after you have tried to answer the question yourself.

1What should you do before changing a broken Compose stack?

Validate the resolved Compose configuration and collect state/log evidence so you know which failure domain you are addressing.

2Why does the capstone use a named Redis volume?

To keep Redis data outside the lifecycle of individual cache containers.

3What is the conceptual bridge from Docker Compose to Kubernetes?

Both describe multi-component applications declaratively, but Kubernetes adds cluster scheduling, controllers, service abstractions and broader orchestration capabilities.