CodeOath
← All posts
Docker65 min total · 19 parts

Docker Fundamentals: Images, Containers, and Writing a Good Dockerfile

Contents — Part 19 of 19: Common Mistakes Worth Remembering
Part 19 of 19 · ~2 min

Common Mistakes Worth Remembering

  • COPY . . before installing dependencies — invalidates the dependency-install layer's cache on every single code change, turning a cached, near-instant step into a full reinstall on every build.
  • Deleting a large file in a later RUN than the one that created it — the bytes are already committed to an earlier layer and still ship in the image; clean up within the same RUN, or use a multi-stage build.
  • Using the shell form of CMD/ENTRYPOINT for a process that needs to shut down gracefully — the shell becomes PID 1 and can silently swallow the signal docker stop sends.
  • Relying on depends_on alone (without a healthcheck + condition: service_healthy) to wait for a dependency like a database to actually be ready, not just started.
  • Running a container as root in production with no reason to, or baking a secret into an image layer via ENV/COPY and assuming a later "delete" step removes it from history.
  • Treating a container's own filesystem as durable storage — it isn't, without an explicit volume, and disappears the moment the container is removed.
  • Massive images from an unnecessary base (ubuntu instead of alpine/slim/distroless) or a missing .dockerignore sending the whole repo (including .git and node_modules) into the build context.
  • Pinning nothing — FROM node:latest means your "identical everywhere" promise silently breaks the moment upstream publishes a new latest.

Containers are usually one piece of a larger deployment story — see CI/CD Pipelines Explained for how an image actually gets built, tested, and promoted to production, and Microservices vs. Monolith for how container boundaries tend to map onto service boundaries once a system has more than one of them. This project's own infra/ folder has a real Docker Compose setup for a self-hosted code-execution engine, if you want to see one in context. Practice the concepts here as runnable exercises in the code lab.