IT 3300 : Virtualization

Docker — Building Images

Why build your own

  • Public images are great, but your app is yours
  • A Dockerfile is a repeatable recipe for an image
  • Check it into git — your build becomes version-controlled

A first Dockerfile

FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 5000
CMD ["python", "app.py"]

Common instructions

  • FROM — base image to start from
  • WORKDIR — set the working directory
  • COPY — copy files into the image
  • RUN — execute a command at build time
  • CMD / ENTRYPOINT — what runs at container start
  • EXPOSE — document the port

Build and run

    docker build -t myapp:1.0 .
    docker run -d -p 5000:5000 myapp:1.0
  • -t myapp:1.0 — name and tag the image
  • . — build context (this directory)

Layers and caching

  • Each instruction creates a layer
  • Docker caches layers and reuses unchanged ones
  • Order matters: copy dependency files and install before copying
    your source, so code changes don't bust the dependency cache

Multi-stage builds

  • Build in one stage, ship only the result in a tiny final stage

      FROM golang:1.22 AS build
      WORKDIR /src
      COPY . .
      RUN go build -o app
    
      FROM gcr.io/distroless/base
      COPY --from=build /src/app /app
      USER nonroot
      ENTRYPOINT ["/app"]
    
  • Final image has no compiler, no source — smaller and safer

Best practices

  • Small base images (-slim, alpine, distroless)
  • Run as a non-root user (USER)
  • Use a .dockerignore to keep junk out of the context
  • One concern per image; pin base image versions
  • Fewer, deliberate layers

Pushing to a registry

    docker tag myapp:1.0 <user>/myapp:1.0
    docker push <user>/myapp:1.0
  • Now teammates (and your cluster) can pull it
  • Use tags for versions; treat pushed images as immutable

BuildKit

  • The modern builder (default in current Docker)
  • Faster, parallel builds, better caching, build secrets
  • You're likely already using it — good

Lab goals

  • Containerize a small app (e.g. the fortune/identidock app)
  • Rebuild it as a multi-stage image and compare the size
  • Push it to a registry and pull it on a different VM