Docker Compose — Build — Practice Exercises
Test your understanding of building images with Docker Compose.
Exercise 1: Basic Build
Create a simple Node.js Dockerfile and build it using Compose.
Solution
api/Dockerfile:
FROM node:20-alpine
WORKDIR /app
COPY package.json .
RUN echo '{"name":"api","scripts":{"start":"node server.js"}}' > package.json
RUN echo 'require("http").createServer((req,res)=>{res.end("OK")}).listen(3000)' > server.js
CMD ["node", "server.js"]
compose.yml:
services:
api:
build: ./api
ports:
- "3000:3000"
docker compose build
docker compose up -d
curl http://localhost:3000 # OK
Exercise 2: Build Args
Pass a NODE_VERSION build arg to select the base image version.
Solution
Dockerfile:
ARG NODE_VERSION=20
FROM node:${NODE_VERSION}-alpine
WORKDIR /app
CMD ["node", "--version"]
services:
api:
build:
context: .
args:
NODE_VERSION: "18"
docker compose build
docker compose run --rm api # Should show v18.x.x
Exercise 3: Multi-Stage Target
Create a multi-stage Dockerfile with development and production stages. Use target: to select one.
Solution
FROM alpine AS development
RUN echo "dev mode"
CMD ["echo", "development"]
FROM alpine AS production
RUN echo "prod mode"
CMD ["echo", "production"]
services:
app:
build:
context: .
target: production
docker compose build
docker compose run --rm app # production
Exercise 4: Tag and Push
Build an image, tag it with a version, and list the result.
Solution
services:
api:
build: ./api
image: myregistry/api:v1.0.0
docker compose build
docker compose images # Shows myregistry/api:v1.0.0
Exercise 5: Dynamic Version Tag
Use .env to set the version tag dynamically.
Solution
.env:
VERSION=2.1.0
services:
api:
build: ./api
image: myregistry/api:${VERSION}
docker compose build
docker compose images # Shows myregistry/api:2.1.0