TestForge | Aidevops | 📊 Plogger ✍️ Blog 📚 Docs
plogger

AI DevOps Korea

Turn AI service development and operations into one improvement loop

Aidevops.kr covers LLMOps, RAG, agents, observability, evaluation, and cost-performance optimization for production AI services.

Docker from Fundamentals to Production Practice

· Updated Apr 16
Docker from Fundamentals to Production Practice diagram
Visual guide to the key flow, architecture, and decision points covered in this post.
Docker can standardize development environments, but more fundamentally it is a technology for standardizing the unit of application execution. In practice, what matters is not memorizing `docker run`, but understanding how images are built and what kind of state should never live inside a container.

A container is not a virtual machine

Containers do not virtualize an entire operating system. They isolate processes while sharing the kernel. That makes them lightweight and fast, but it also means you need to understand the file system, networking, volumes, and process lifecycle.

Image design is operational quality

FROM node:22-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:22-alpine
WORKDIR /app
COPY --from=build /app/dist ./dist
COPY --from=build /app/package*.json ./
RUN npm ci --omit=dev
CMD ["node", "dist/server.js"]

A good Dockerfile is not just a file that works. It should meet the following goals.

  • Avoid inflating image size unnecessarily
  • Take advantage of the build cache well
  • Separate the build environment from the runtime environment
  • Avoid baking secrets into the image

Multi-stage builds are the most common foundational pattern for that.

Perspective matters more than memorizing common commands

docker build -t my-app .
docker run -p 3000:3000 my-app
docker ps
docker logs <container-id>
docker exec -it <container-id> sh

Knowing these commands is only the starting point. In practice, the more important questions are:

  • Are logs collected outside the container?
  • Is configuration injected through environment variables?
  • Is data stored in volumes?
  • Does the application shut down cleanly when it receives a termination signal?

State belongs outside the container

It is usually best to treat a container as a replaceable execution unit. If you keep persistent state such as uploaded files, database data, or session files inside the container file system, replacement and scaling become much harder in production.

  • Persistent data: volumes or external storage
  • Configuration values: environment variables or secret management
  • Logs: collection based on standard output

Development images and production images have different goals

In development, fast rebuilds and hot reload matter most. In production, small and predictable images matter more. Instead of trying to satisfy both goals with one Dockerfile, it is usually better to split roles with docker-compose or separate stages when needed.

Problems commonly seen in production

  • Using only the latest tag so you cannot tell which image was deployed
  • Treating a container as healthy just because it is running, without a health check
  • Running images directly as root
  • Accidentally COPYing .env files or key files into the image
  • Letting the build context grow so large that CI time becomes excessive
  • Keep both a version tag and a git SHA
  • Manage .dockerignore aggressively
  • Separate health check and readiness concerns
  • Add image scanning and baseline security checks to CI
  • Optimize local developer convenience separately from production images

Summary

The core of Docker is not the commands. It is the mindset of standardizing the execution unit. Once you start drawing clear boundaries around images, configuration, data, logs, and termination signals, Docker stops being just a developer convenience tool and becomes a foundation for more stable deployment and operations.

What Gets Hard in Production

  • Docker basics matter because container behavior shapes build repeatability, runtime isolation, and deployment confidence.
  • The early mistakes are usually not around syntax, but around image size, secret handling, and misunderstanding what belongs inside the container.
  • Containerization amplifies good boundaries and exposes bad ones.

Architecture Decisions That Matter

  • Use multi-stage builds and small runtime images by default.
  • Keep configuration external and build artifacts immutable.
  • Design images around one clear process responsibility per container.

Practical Example

A practical build keeps dependencies in earlier stages and ships only what the runtime needs:

FROM node:20 AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:20-alpine
WORKDIR /app
COPY --from=build /app/dist ./dist

Anti-Patterns to Avoid

  • Using containers as mini virtual machines full of debug tools and mutable state.
  • Baking secrets and environment-specific values into the image.
  • Ignoring layer caching and rebuild cost in CI.

Operational Checklist

  • Scan image size and vulnerability baseline regularly.
  • Verify container startup time and readiness behavior.
  • Keep Dockerfiles reviewable and deterministic.
  • Test image reproducibility in CI.

Final Judgment

Docker is simple at the CLI level and unforgiving at the boundary level. Teams gain the most when they treat images as immutable deployment units rather than handy packaging blobs.

Continue Reading

Related posts

Next Path

Keep exploring this topic as a system