A Dockerfile is a script composed of instructions to build a Docker image. Each instruction creates a layer in the image.
# Comment INSTRUCTION arguments FROMSpecifies the base image.
FROM ubuntu:20.04 FROM node:22-alpine LABELAdds metadata to the image.
LABEL maintainer="you@example.com" LABEL version="1.0" description="My App" ENVSets environment variables.
ENV NODE_ENV=production ENV PATH="/app/bin:$PATH" RUNExecutes commands in a shell during build.
RUN apt-get update && apt-get install -y curl RUN npm install Use RUN ["executable", "param1", "param2"] for JSON array form.
COPYCopies files from host to image.
COPY . /app COPY config.json /app/config.json ADDSimilar to COPY, but supports remote URLs and auto-extracts archives.
ADD https://example.com/file.tar.gz /app/ ADD archive.zip /app/ CMDSets default command to run when container starts.
CMD ["node", "server.js"] # Preferred exec form CMD node server.js # Shell form Only one CMD allowed; later ones override earlier.
ENTRYPOINTConfigures a container to run as an executable.
ENTRYPOINT ["python", "app.py"] Use with CMD to pass default arguments.
WORKDIRSets the working directory for subsequent instructions.
WORKDIR /app EXPOSEDocuments the port the container listens on.
EXPOSE 80 EXPOSE 443 Note: This does not publish the port.
VOLUMECreates a mount point for persistent or shared data.
VOLUME ["/data"] USERSets the user to run subsequent instructions.
USER appuser ARGDefines build-time variables.
ARG VERSION=1.0 RUN echo $VERSION Use --build-arg VERSION=2.0 during docker build.
ONBUILDTriggers instructions when the image is used as a base.
ONBUILD COPY . /app alpine) for smaller size.RUN commands to reduce layers..dockerignore to exclude unnecessary files.COPY over ADD unless you need archive extraction.ENTRYPOINT for fixed commands and CMD for arguments.FROM node:22-alpine LABEL maintainer="guillaume@example.com" WORKDIR /app COPY package*.json ./ RUN npm install COPY . . EXPOSE 3000 ENV NODE_ENV=production CMD ["node", "index.js"] # Build image docker build -t my-app . # Run container docker run -p 3000:3000 my-app node_modules *.log Dockerfile .git Multistage builds allow you to use multiple FROM statements in one Dockerfile to optimize image size and separate build dependencies from runtime.
# Stage 1: Build FROM node:22-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm install COPY . . RUN npm run build # Stage 2: Production FROM nginx:alpine COPY --from=builder /app/dist /usr/share/nginx/html You can name each stage using AS <name> and reference it later with --from=<name>.
FROM golang:1.21 AS build WORKDIR /src COPY . . RUN go build -o myapp FROM alpine:latest COPY --from=build /src/myapp /usr/local/bin/myapp ENTRYPOINT ["myapp"] Use COPY --from=<stage> to copy files from one stage to another.
COPY --from=builder /app/output /app/output You can copy:
Multistage builds help you avoid bloated images:
# Without multistage: includes compilers, source code, etc. # With multistage: only includes runtime essentials # Build stage FROM node:22 AS build WORKDIR /app COPY package*.json ./ RUN npm install COPY . . RUN npm run build # Serve stage FROM nginx:alpine COPY --from=build /app/build /usr/share/nginx/html EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]