Image Creation, Management, and Registry
Layers and instructions
Every Dockerfile instruction that changes the filesystem makes a layer; RUN, COPY, and ADD are the big three. Order them least-volatile to most-volatile so the build cache survives: base OS packages, then dependency manifests, then source code. Chain shell commands with && and clean up in the same RUN - deleting files in a later layer does not shrink the image.
CMD supplies a default command; ENTRYPOINT is the executable. Exec form (["nginx","-g","daemon off;"]) skips the shell and handles signals correctly; shell form spawns /bin/sh -c and can swallow SIGTERM. ENTRYPOINT plus CMD combine - CMD becomes the default arguments.
Traps
ADD auto-extracts local tarballs and can fetch URLs; COPY does neither and is preferred. ARG exists only at build time; ENV is baked into the image and visible at runtime. EXPOSE documents a port but publishes nothing. Tags are mutable pointers; digests (image@sha256:...) are immutable, so production pinning uses digests. Multi-stage builds (FROM golang AS build … COPY --from=build) keep toolchains out of the final image.
Registry workflow: docker login, docker tag local user/repo:tag, docker push, docker pull. docker save/load move images as tar archives; docker export/import move a container filesystem and lose metadata like ENTRYPOINT. docker image prune -a removes unused images.
Rule of thumb
If you would not commit it to git, it belongs in .dockerignore - a fat build context slows every layer, even ones that hit cache.