Featured image of post Docker for Beginners: Docker Networking Explained

Docker for Beginners: Docker Networking Explained

Learn how Docker containers communicate using networks and port mapping. This guide covers custom networks, inter-container DNS, host access, and common troubleshooting tips to master Docker networking from the ground up.

Introduction: From One Container to Many

You’ve built and deployed a Docker container. You’ve written a Dockerfile, built an image, ran it locally, and even deployed it to the cloud. That’s a huge leap — but it’s only the beginning.

Most real-world applications aren’t made of just one container. They’re made of many — working together. A web API that talks to a database. A frontend that queries a backend. A message processor that queues up jobs.

And none of that works without networking.

In this article, we’re going to explore one of Docker’s most powerful — and often misunderstood — features: networking.

You’ll learn how containers communicate with each other and with the outside world. We’ll show you how to:

  • Create a custom Docker network
  • Run multiple containers on it
  • Let them talk using their names — no IPs needed
  • Map container ports to your host machine
  • And troubleshoot common network issues along the way

If you’ve ever wondered “How do these containers actually talk to each other?” — this is your moment.

By the end of this guide, you won’t just be running containers. You’ll be orchestrating them into a connected system.

Let’s start by making two containers talk.

Creating a Custom Network and Running Multiple Containers

To see container networking in action, let’s build a simple setup: two containers on the same custom Docker network. They won’t do anything fancy — no real API or database — but they’ll be able to ping each other by name.

This gives us a clean, focused way to learn Docker’s networking model — without getting distracted by application wiring or runtime quirks.

Step 1: Create a Custom Network

Let’s start by creating a new Docker network. This is like giving your containers their own private LAN:

1
docker network create my-demo-network

This creates a bridge network named my-demo-network. It’s isolated from other networks and supports automatic DNS resolution — meaning containers can talk to each other using their names.

To verify:

1
docker network ls

You should see my-demo-network listed in the output.

Step 2: Start Two Containers on the Same Network

We’ll run two containers using the Alpine image (a tiny Linux distro) and install a simple ping utility in one to test communication.

  1. Start the first container and name it container-a:

    1
    
    docker run -dit --name container-a --network my-demo-network alpine ash
    
  2. Start the second container and name it container-b:

    1
    
    docker run -dit --name container-b --network my-demo-network alpine ash
    

These two containers are now on the same virtual network.

Step 3: Test That the Containers Can Talk

Let’s jump into container-a and try to ping container-b by name.

1
docker exec -it container-a ash

Once inside the shell:

1
2
apk update && apk add iputils
ping container-b

You should see ping replies — proof that Docker’s internal DNS is working and these containers can discover each other by name.

To exit:

1
exit

Why This Matters

What you just did is powerful.

  • You created a private network just for your containers.
  • You launched two isolated containers into that network.
  • You let them communicate by name, without any manual IP management.

This is exactly how real-world apps work — one service calls another by hostname, not by hard-coded IPs.

Next, let’s explore what other types of Docker networks exist, and why you might (or might not) use them.

Understanding Docker’s Network Types and Why bridge Is the Default

Now that you’ve created a custom Docker network and seen two containers talk to each other by name, let’s step back and answer a deeper question:

What exactly just happened, and how did Docker make it work so seamlessly?

Docker has several built-in ways to connect containers, each with different trade-offs. These are called network drivers, and they determine how traffic flows between containers, the host, and the outside world.

Let’s look at the three most common ones:

1. bridge (default for most containers)

This is what you just used.

  • It creates an isolated virtual network inside the Docker host.
  • Containers on the same bridge can talk to each other directly.
  • Docker assigns each container a private IP address.
  • Automatic DNS resolution: containers can refer to each other by name.

When you run a container without specifying --network, Docker automatically connects it to the default bridge network.

You just made your own bridge network (my-demo-network), which works the same way but with better defaults (like DNS support).

Think of bridge as the “home Wi-Fi” of your containers. Everyone on it can talk, and they’re protected from the outside unless you open ports.

2. host (share the host’s network directly)

With --network host, Docker skips creating an isolated network and just drops your container into the host machine’s network stack.

  • No port mapping needed — the container can bind directly to ports like 80 or 443.
  • No network isolation — useful for performance-critical apps like reverse proxies.
  • Only available on Linux.

Think of host as giving your container a front door key to your house.

3. none (completely isolated)

Use --network none if you want your container to have no network access at all.

  • No communication with other containers or the host.
  • Used for batch jobs, testing, or containers that don’t need a network.

Think of none as placing your container in a soundproof, Wi-Fi-free room.

So Why Is bridge the Default?

Because it strikes the best balance between isolation, connectivity, and safety.

  • It isolates containers from the host and each other by default.
  • You explicitly allow communication by connecting them to the same network.
  • It works on all platforms (Linux, macOS, Windows).
  • It supports port mapping for controlled external access.

If Docker didn’t give you a bridge by default, every new container would require full manual setup. It’s the sane, safe default.

Recap

Network Type Containers Can Talk to Each Other Access to Host Requires Port Mapping Use Case
bridge ✅ Yes (if on same network) ❌ Not directly ✅ Yes Most apps
host ✅ Yes (shares host) ✅ Full access ❌ No (binds directly) High-performance networking
none ❌ No ❌ No ❌ No Offline tasks or testing

Now that you understand the types of networks and the role of the bridge driver, let’s zoom in and see how port mapping works — that’s what lets the outside world talk to your container.

Ready to open the door?

👉 Let’s dive into port mapping next.

Port Mapping: Letting the Outside World In

So far, your containers have been talking to each other inside a private Docker network. But what happens when you want the outside world — your browser, your API client, your mobile app — to talk to a containerized service?

That’s where port mapping comes in.

What Is Port Mapping?

By default, containers are invisible to the outside world. They might be running a web server or an API internally, but unless you expose and map ports, they remain locked inside the Docker network.

Port mapping creates a bridge between:

  • A port on your host machine (e.g. port 8080)
  • A port inside the container (e.g. port 80)

So when you visit http://localhost:8080, Docker forwards that traffic to port 80 inside your container.

Running a Container with Port Mapping

Let’s walk through an example using Nginx — a lightweight web server.

1
docker run -d --name web -p 8080:80 nginx

Here’s what each part means:

  • -d: Run in detached mode (background)
  • --name web: Name this container web
  • -p 8080:80: Map host port 8080 to container port 80
  • nginx: Use the official Nginx image

Now open your browser and go to:

1
http://localhost:8080

You’ll see the default Nginx welcome page — served from inside a container!

Diagram: How Port Mapping Works

1
2
3
4
5
6
7
8
[Your Browser] --> localhost:8080 ─┐
                         [Docker Host Machine]
                          ┌────────────────┐
                          │ Container: web │
                          │ Port: 80       │
                          └────────────────┘

Multiple Mappings for Multiple Services

You can map multiple containers to different host ports:

1
2
docker run -d --name app1 -p 5000:3000 my-node-app
docker run -d --name app2 -p 6000:3000 my-other-node-app
  • Both apps expose port 3000 internally
  • You map them to different host ports to avoid conflicts

Common Pitfalls to Avoid

  1. Port already in use

    • If port 8080 is already taken on your host, Docker will fail to start the container.
    • Solution: Choose another port (e.g. -p 8081:80)
  2. Wrong port direction

    • -p 8080:80 means “host:container”, not the other way around.
    • 8080 is your host port, 80 is your container port
  3. Accessing from the wrong IP

    • If you’re inside WSL, Docker Desktop, or a remote VM, localhost might not resolve to the Docker host.
    • Use the correct IP or setup port forwarding from your Docker environment to your host

Recap

Concept Description
Port Mapping Exposes a container’s internal port to the host machine
-p 8080:80 Maps host port 8080 to container port 80
Access http://localhost:8080 now routes to the container
Use Case Web apps, APIs, or anything that needs external access

You’ve now seen both sides of Docker networking:

  • Internal communication (containers talking to each other)
  • External communication (containers talking to the outside world)

And with this, you’re ready to troubleshoot, design, and scale multi-container apps that play nicely with your host environment and with each other.

Next up: Let’s explore how to diagnose common Docker networking issues and wrap up with some best practices.

Troubleshooting and Best Practices for Docker Networking

You’ve now seen how containers talk to each other and how to expose those containers to the outside world. But sometimes things don’t go as planned. Let’s look at how to troubleshoot Docker networking issues — and a few best practices to keep your setups clean and reliable.

Common Networking Issues and Fixes

Here are some of the most common problems Docker users run into — and how to resolve them quickly.

1. I can’t access my container at localhost:PORT.

Check:

  • Did you use -p when running the container?
  • Is the host port (e.g. 8080) already in use by another application?

Fix:

  • Double-check your run command includes -p, like -p 8080:80
  • Try another port (e.g. -p 8081:80) if the first one is already in use

2. Containers on the same network can’t talk to each other.

Check:

  • Are both containers on the same custom network?
  • Are you using the correct container names in communication?

Fix:

  • Run docker network inspect <network-name> to verify
  • Ping using container names, not IPs: e.g. ping db

3. DNS resolution fails between containers.

Check:

  • Are you on the default bridge network?

Fix:

  • Create and use a custom bridge network. The default bridge doesn’t support automatic DNS between containers.
1
docker network create my-network

4. My container loses connectivity after restart.

Check:

  • Did you manually reconnect it to a custom network?

Fix:

  • If you use docker run, include --network my-network
  • If using docker start, you can’t change network config. Use docker run again with the correct options

5. Port mappings stop working after container restart.

Fix:

  • Remember that Docker containers are immutable. Restarting a container that was originally started with docker run will preserve its settings only if you use docker start, not docker run again without flags.

  • Use docker ps -a to find the container, or remove and re-run with the right port mapping.

Best Practices to Keep in Mind

Here are a few tips that will help you avoid common Docker networking headaches as you build more complex applications:

Use Custom Networks

  • Always create your own bridge networks for container-to-container communication.
  • This gives you DNS resolution, better isolation, and clearer intent.
1
docker network create my-app-network

Use Clear Container Names

  • This makes container communication predictable.
  • Instead of docker run -d nginx, do:
1
docker run -d --name frontend --network my-app-network nginx

Now you can ping it with ping frontend from another container.

Avoid Hard-Coded IPs

  • IP addresses can change — especially if containers restart.
  • Use container names on custom networks instead. It’s like using domain names instead of IPs in the real world.

Clean Up Often

  • When you’re done testing or deploying, clean up containers, networks, and images:
1
2
3
docker stop my-container
docker rm my-container
docker network rm my-app-network
  • Avoid dangling networks and containers that clutter your environment.

Recap: What You’ve Learned

Let’s zoom out and reflect on the journey through Docker networking:

Concept What You Did
Custom Networks Created a private bridge network for your containers
Container Communication Let two containers talk to each other by name
Port Mapping Exposed internal container ports to your host machine
Network Types Compared bridge, host, and none networking options
Troubleshooting Diagnosed and fixed common issues
Best Practices Learned how to keep your networking clean and maintainable

You’re No Longer Just Running Containers — You’re Orchestrating Them

Networking is what turns isolated services into real systems. And now you know how to:

  • Build those systems from scratch
  • Wire them together with Docker networks
  • Make them accessible to the outside world
  • Debug and manage those connections with confidence

Next Up: Storage and Volumes — Making Containers Remember

In the next article, we’re tackling another misunderstood but critical concept: Docker storage.

Containers are ephemeral by design — but what if you want them to remember things?
User uploads, logs, databases — they all need persistent storage.

That’s where Docker volumes come in.

👉 Learn how to persist data in Docker using volumes →

Let’s make your containers stateful.