Docker Compose, Networks & Volumes for Beginners

How container DNS networking and persistent data volumes clear the path for multi-container stacks with Docker Compose.

Four-panel Kermit the Frog meme captioned "me, diving into Docker"

If you've read the intro to Docker, you know what a container is. A single container is clean: your app, its dependencies, isolated and portable.

But no real backend app is a single container.

Your API needs a database. The database needs persistent storage. The frontend needs to talk to the API. Your local dev stack needs hot-reloading. Before you know it you're juggling five separate docker run commands with flags you've already forgotten, and you have no idea what order they need to run in.

This is the problem Docker Compose solves. But before getting there, you need to understand what it's actually managing under the hood: networks and volumes.


Container Networking: How Containers Talk to Each Other

By default, containers are isolated. They can't reach each other by IP address either. Those are dynamic, assigned at runtime, change every time a container restarts. Hardcoding IPs is a terrible idea.

Docker fixes this with virtual networks. Containers on the same Docker network can find each other by name instead of IP. Docker's internal DNS resolves it automatically.

Three network drivers worth knowing:

In practice, bridge is almost always the answer. You create a named network, attach your containers, and they find each other by service name:

docker network create my-app-network
docker run --network my-app-network --name api my-api-image
docker run --network my-app-network --name db postgres:16

Now api can reach db at postgres://db:5432. No hardcoded IPs, no config files, no fuss.

The official Docker networking docs go deeper on overlay networks (multi-host Swarm) and Macvlan if you need containers to show up as physical devices on your LAN.


Volumes: Containers Are Temporary, Your Data Isn't

Here's something that surprises a lot of people: containers throw away everything when they stop.

As covered in the production builds post, each container has a thin writable layer on top of read-only image layers. That writable layer lives only as long as the container. Run docker rm and it's gone.

For a stateless API, that's fine. For a database, that's catastrophic.

Docker's answer is volumes: storage that lives completely outside the container lifecycle.

Named Volumes

Docker manages these entirely. They live at /var/lib/docker/volumes/ on the host:

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

The volume postgres_data outlives every container it's ever mounted into. Kill the container, spin up a new one with the same flag, all the data is right there.

Bind Mounts

Maps a specific folder on your host directly into the container:

docker run -v $(pwd):/app my-node-app

Save a file on your host, the container sees it instantly, dev server hot-reloads. Bind mounts are a local dev thing. Don't use them for production data.


So What Is Docker Compose?

"This is fine" dog sitting calmly in a burning room, captioned "docker-compose up" and "publish-all-projects"

Now that you know about networks and volumes, Compose becomes obvious.

Managing all of this manually is tedious and breaks constantly. Creating networks, defining volumes, passing the right flags to five docker run commands in the right order. You'd write a shell script. That script becomes its own maintenance nightmare.

Docker Compose is a declarative way to describe your entire stack in one file.

You write a docker-compose.yml that says: here are my services, here's how they connect, here's where their data lives. One command, docker compose up, and the whole thing boots in the right order with all the wiring done.

It's not Kubernetes. It's not for production at scale. It's a local dev and CI tool that wraps the same Docker primitives you'd use manually, just without the ceremony of doing it by hand every time.

The official Compose docs are genuinely good when you're ready to go deep. CLI reference, spec, all of it is there.


What Compose Actually Handles for You

When you run docker compose up:

Networks let containers find each other. Volumes let data outlive containers. Compose ties it all together so you're not scripting it from scratch every time.

Curious how any of this actually works at the kernel level? Namespaces, cgroups, OverlayFS. That's all in Docker Engine Under the Hood.

Docker Compose, Networks & Volumes for Beginners | dmix writes