BlogDocker for Developers: The Concepts That Actually Matter
DevOps

Docker for Developers: The Concepts That Actually Matter

By Madhukar May 8, 2026 6 min read

Docker is one of those tools where learning commands before concepts leads to confusion that persists for months. You can memorize docker run flags without understanding why they are needed. Let me fix the concept layer first.

Images vs Containers

An image is a static, immutable template — a snapshot of a filesystem and metadata describing how to run it. Think of it like a class definition in object-oriented programming.

A container is a running instance of an image. You can run many containers from one image. When a container stops, the image is unchanged.

bash
# Pull the image (download the template)
docker pull python:3.11-slim

# Run a container from the image
docker run -it python:3.11-slim python3
# Container exits when you close the Python REPL — image unchanged

Layers and the Build Cache

Every instruction in a Dockerfile creates a layer. Layers are cached — if the instruction and everything before it has not changed, Docker reuses the cached layer instead of rebuilding.

This has a practical implication for build performance: put things that change less frequently earlier in the Dockerfile:

dockerfile
FROM python:3.11-slim

# Dependencies change rarely — copy and install first
COPY requirements.txt .
RUN pip install -r requirements.txt

# Application code changes frequently — copy last
COPY . .

CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0"]

If you put COPY . . before installing dependencies, every code change invalidates the pip install cache. Layer ordering is not cosmetic — it is a significant build time optimization.

Volumes for Persistent Data

Containers are ephemeral. When a container is deleted, its filesystem is gone. For data that should persist (databases, uploaded files), use volumes:

bash
docker run -v postgres_data:/var/lib/postgresql/data postgres:15

The named volume postgres_data persists independently of the container lifecycle. Delete the container, recreate it with the same volume mount, and the data is still there.

Networking Between Containers

By default, containers are isolated. A frontend container cannot reach a database container by hostname. Docker networks solve this:

yaml
# docker-compose.yml
services:
  api:
    build: .
    networks: [app-network]
  db:
    image: postgres:15
    networks: [app-network]

networks:
  app-network:

Within the same network, containers can reach each other by service name. The API container connects to the database at hostname db, not localhost.

M

Madhukar

Founder & Lead Engineer, Devpads

Building lightweight, high-performance, and privacy-first developer utilities. Madhukar specializes in modern web architectures, code editor tooling, and developer workspace experiences. Read more about our mission on our dedicated About Page or get in touch via Contact Us.

Stack: React · Vite · Tailwind · FastAPI · PostgreSQL