docker build -t <name>:<tag> .
Build an image from the Dockerfile in the current directory (the build context).
docker build -t api:1.4.2 --target runtime .
-t NAME:TAG- Name and tag the result.
-f FILE- Use another Dockerfile.
--target STAGE- Stop at a named multi-stage stage.
--build-arg K=V- Build-time variable (not for secrets).
--no-cache- Rebuild every layer.
Gotcha Everything in the context is sent to the builder. Without a .dockerignore you ship .git, node_modules and maybe .env into the image.
docker images
List local images with tags, IDs and sizes.
-a- Include intermediate layers.
--digests- Show content digests.
-f dangling=true- Untagged images left by rebuilds.
docker pull <image>@<digest>
Download an image. Pinning a digest guarantees the same bytes every time, unlike a mutable tag.
docker pull nginx:1.27
:TAG- Mutable name; latest is only a convention.
@sha256:...- Immutable content address.
--platform linux/amd64- Choose an architecture explicitly.
Gotcha Built on an ARM Mac, deployed on x86? 'exec format error' means an architecture mismatch. Use buildx with --platform.
docker tag <src> <registry>/<repo>:<tag>
Name an image for a registry and push it.
docker tag api:1.4.2 ghcr.io/acme/api:1.4.2 && docker push ghcr.io/acme/api:1.4.2
tag- Adds a name; does not copy data.
push- Upload missing layers to the registry.
login REGISTRY- Authenticate first.
docker history <image>
Show each layer, its size and the instruction that created it, to find what makes an image big.
docker history --no-trunc api:1.4.2
--no-trunc- Full instructions.
--format '{{.Size}} {{.CreatedBy}}'- Compact size breakdown.
Gotcha A file deleted in a later RUN still takes space in the earlier layer. Delete it in the same RUN that created it.
docker buildx build --platform <list> --push
Build multi-architecture images and push them as a single manifest list.
docker buildx build --platform linux/amd64,linux/arm64 -t ghcr.io/acme/api:1.4.2 --push .
--platform- Target architectures.
--push- Push directly; multi-platform results cannot load into the local image store.
--cache-from / --cache-to- Registry or CI cache for layers.
Multi-stage Dockerfile
Build with the full toolchain, ship a small runtime image that runs as a non-root user.
FROM node:20-bookworm AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build && npm prune --omit=dev
FROM node:20-bookworm-slim AS runtime
WORKDIR /app
ENV NODE_ENV=production
COPY --from=build --chown=node:node /app/node_modules ./node_modules
COPY --from=build --chown=node:node /app/dist ./dist
USER node
EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=3s CMD node dist/healthcheck.js
CMD ["node", "dist/server.js"]
COPY package*.json first- Dependency layers stay cached until the lockfile changes.
AS build / --from=build- Only artifacts reach the final image, not compilers.
USER node- Do not run as root inside the container.
CMD ["..."] exec form- The app is PID 1 and receives SIGTERM directly.
.dockerignore
Keep secrets, VCS data and local build output out of the build context.
.git
node_modules
dist
*.log
.env
.env.*
coverage
Dockerfile*
.env- Never let local secrets reach an image layer.
node_modules- Install inside the image for the right platform.