Dockerinfrastructure

Why Docker

Consistent environments from development to production

v1.1·9 min read·Kenneth Pernyér
dockercontainersdevopsdeploymentinfrastructure

The Problem

"It works on my machine" is the most expensive phrase in software development.

Environment differences cause bugs that only appear in production. Different Node versions, different system libraries, different file system behaviors—all create gaps between what you test and what you ship.

The problem compounds with AI-assisted development.

When AI generates code, it doesn't know your production environment. It generates code that works in isolation but may fail when deployed. Without environment consistency, you're testing AI output against the wrong target.

We needed a solution that:

  • Makes development match production exactly
  • Eliminates "works on my machine" bugs
  • Enables reproducible builds across any machine
  • Simplifies deployment and scaling

Current Options

OptionProsCons
Virtual MachinesFull OS virtualization. Maximum isolation, maximum overhead.
  • Complete environment isolation
  • Run any OS on any host
  • Well-understood security model
  • Heavy resource usage
  • Slow startup times
  • Large disk footprint
  • Complex management
DockerContainer-based virtualization. Process isolation with shared kernel.
  • Lightweight—starts in seconds
  • Consistent environments everywhere
  • Huge ecosystem of base images
  • Compose for multi-container setups
  • Linux kernel required (or VM on Mac/Windows)
  • Networking can be complex
  • Security requires careful configuration
  • Image size management needed
Native DevelopmentRun everything directly on host. No virtualization overhead.
  • Maximum performance
  • Direct access to system tools
  • No container abstraction to learn
  • Environment drift between machines
  • Version conflicts between projects
  • Production parity not guaranteed
  • Onboarding new developers is painful

Future Outlook

Containers are infrastructure now. The debate isn't whether to use containers but how to orchestrate them.

The trend is toward simpler container workflows.

Docker Compose handles most development needs. Kubernetes is for production scale. The middle ground—Swarm, Nomad, ECS—serves specific niches.

Bun and Deno are changing the equation slightly. Single-binary deployment reduces the need for complex containers. But for services with dependencies (databases, caches, queues), containers remain essential.

The future is likely serverless containers—managed platforms that handle orchestration while you define the container. But the container itself remains the unit of deployment.

Our Decision

Why we chose this

  • Environment parityDevelopment, CI, staging, and production run identical environments
  • Fast onboardingNew developers run one command to get the full stack
  • Dependency isolationEach project has its own versions, no conflicts
  • Reproducible buildsSame Dockerfile always produces the same image

×Trade-offs we accept

  • Mac/Windows overheadDocker Desktop runs a Linux VM, which adds latency
  • Learning curveNetworking, volumes, and multi-stage builds require study
  • Image size managementBloated images slow CI and deployment

Motivation

Every service we build runs in a container. Development, CI, production—all use the same Dockerfile. When a test passes locally, it passes in CI. When it passes in CI, it works in production.

This eliminates an entire class of bugs. No more debugging environment-specific issues. No more "but it worked yesterday" mysteries.

For AI-assisted development, containers provide a stable target. AI-generated code is tested against the same environment it will run in. This catches issues early, before they become production incidents.

Recommendation

Use Docker for all backend services. Create a Dockerfile that:

  1. Uses multi-stage builds to minimize image size
  2. Runs as non-root user
  3. Includes only production dependencies
  4. Uses specific version tags, not latest

For development, use Docker Compose to orchestrate your full stack—API, database, cache, message queue—with a single command.

Consider alternatives to Docker Desktop on Mac: OrbStack is faster and uses less memory. Colima is open-source and works well.

Examples

Dockerfiledockerfile
# Build stage
FROM oven/bun:1 AS builder
WORKDIR /app
COPY package.json bun.lockb ./
RUN bun install --frozen-lockfile
COPY . .
RUN bun run build

# Production stage
FROM oven/bun:1-slim
WORKDIR /app
RUN adduser --disabled-password --gecos "" appuser
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package.json ./
COPY --from=builder /app/node_modules ./node_modules
USER appuser
EXPOSE 3000
CMD ["bun", "run", "dist/server.js"]

Multi-stage build for Bun applications. Build stage installs all dependencies, production stage contains only what is needed to run.

Related Articles

Stockholm, Sweden

Version 1.1

Kenneth Pernyér signature