AcademyContainment Breach: The Architect's ShipZone 2: Structural Blueprints (Images)

Lesson 2: The Assembly Line (Writing Dockerfiles)

A Dockerfile is the recipe that tells Docker how to build an image. It's a simple text file with step-by-step instructions — like an assembly line for your application.

Dockerfile Anatomy

# Start from a base image
FROM node:18-alpine

# Set the working directory inside the container
WORKDIR /app

# Copy dependency files first (for caching)
COPY package*.json ./

# Install dependencies
RUN npm install --production

# Copy the rest of the application
COPY . .

# Expose the port the app listens on
EXPOSE 3000

# Define the startup command
CMD ["node", "server.js"]

Dockerfile Instructions

| Instruction | Purpose | Example | |-------------|---------|---------| | FROM | Base image to start from | FROM python:3.11-slim | | WORKDIR | Set the working directory | WORKDIR /app | | COPY | Copy files from host to image | COPY . . | | ADD | Like COPY, but handles URLs and archives | ADD archive.tar.gz /opt/ | | RUN | Execute a command during build | RUN apt-get install -y curl | | ENV | Set environment variables | ENV NODE_ENV=production | | EXPOSE | Document which port the app uses | EXPOSE 8080 | | CMD | Default command when container starts | CMD ["python", "app.py"] | | ENTRYPOINT | Fixed command (CMD becomes arguments) | ENTRYPOINT ["python"] |

Building an Image

docker build -t my-app:v1 .
  • -t my-app:v1 — Tag (name) the image.
  • . — The build context (current directory).

The Order Matters (Layer Caching)

Docker caches each layer. If a layer hasn't changed, Docker skips rebuilding it. This means order your Dockerfile from least-changing to most-changing:

# ✅ GOOD: Dependencies change rarely, code changes often
COPY package.json ./          # Layer 1: Rarely changes
RUN npm install               # Layer 2: Cached if package.json unchanged
COPY . .                      # Layer 3: Changes with every edit

# ❌ BAD: Busts cache on every code change
COPY . .                      # Layer 1: Changes every time
RUN npm install               # Layer 2: Rebuilt every time too!

CMD vs. ENTRYPOINT

| | CMD | ENTRYPOINT | |---|-----|-----------| | Can be overridden? | Yes, by docker run args | No (args are appended) | | Use case | Default command | Fixed executable |

# CMD: Overridable
CMD ["python", "app.py"]
# docker run my-app python test.py  ← overrides CMD

# ENTRYPOINT: Fixed
ENTRYPOINT ["python"]
CMD ["app.py"]
# docker run my-app test.py  ← runs "python test.py"
booting...

Mission Objective

Build your first Docker image:

  1. Write the recipe: Create a Dockerfile with touch Dockerfile.
  2. Build it: Run docker build -t my-app:v1 . to build your image.
  3. Run it: Launch your container with docker run my-app:v1.

Mission Control

Create a Dockerfile

Expected Command

touch Dockerfile

Build an image from the Dockerfile

Run a container from your custom image