Updated on June 3, 2025 in #docker
We'll cover published ports, IP addresses, gateways and how Docker Compose makes DNS entries for each service.
Have you ever wondered how you’re able to automatically access something like web:8000 or db:5432 inside of your containers after upping your project with Docker Compose? Let’s unwind a few things and eventually get to that point.
Over the years I’ve written about a few networking concepts with Docker like exposing vs publishing ports and accessing host.docker.internal. If you’re looking on how to publish ports so localhost:8000 is available on your Docker host or you want to access services running on your Docker host from within a container check out those posts.
In this post we’re going to focus on how networks get created and set up for you automatically with Compose.
# A Basic Example
I like learning by example so let’s see the end result before we go into the details.
The grace period is set to 1s because we’ll be upping / downing this project a bit, it’ll save us time!
If you already have a project named “example” and get an error with the command below then you can use something else or omit that so it uses your directory name by default.
Upping the Project
So far so good.
Making a Few curl Requests
From our http-client container we can make curl requests to both services. http-echo echos a string of your choosing and it defaults to listening on 5678.
In the Docker Compose terminal output you should see the logs too:
172.27.0.4 is the IP address of the http-client container. It might be different for you. We’ll see how this works in a few.
All of this works because all 3 of these services are on the same network and Docker Compose wired all of that up out of the box.
The example Network
When we upped the project, example_default was created for us. That was in the Docker Compose logs near the top.
I’ve omit some of the output to keep it short but I kept the bits that are important for the sake of this post, such as IAM.Config and Containers.
Your values might look different depending on how you installed Docker and how many networks you already have. The likely difference will be the 172.27.X.X IP addresses. 27 in your case might be a lower or higher number based on how many networks you have.
Here’s a couple of takeaways:
- It is a bridge network
- It’s on a specific subnet (172.27.0.0/16)
- This provides network separation between your different networks / projects
- Each of your containers have their own IP address on the above subnet and a name
- The Name is a DNS based way of accessing that container
- ... http-client curl example-a-1:5678 works the same as a:5678
- The Name is a DNS based way of accessing that container
Solving the DNS Mystery
We can investigate the /etc/hosts file of a container:
Notice the last line’s 172.27.0.4 lines up with the IP address above. The 24c0 value is also the container name that’s the object key in the Containers above.
Now we can inspect that container (by name or ID) and check out its networking properties:
Here’s a couple of takeaways:
- NetworkID matches the example_default network’s Id
- IPAddress matches what we saw in the network’s output
- Aliases includes our original DNS name and a new http-client name
- Docker Compose added this for us automatically!
- We can add our own custom aliases too, more on that soon
- DNSNames combines Aliases and the container ID
- This is what ultimately allows us to reach this container by any name included
Feel free to experiment on your own by making a request to a. At this point you have all the info you need to find out what a’s container name is (you can inspect it):
Custom Aliases / DNS Names
If you have a use case where you want to customize which aliases are available for a service you can do that. Aliases are scoped to a specific network.
We can modify our a service to this:
If you have a custom network you can change “default” to your network’s name.
You can stop and up the Docker Compose project again for the changes to apply.
Then you can access everything we did before and also docker compose exec http-client curl apple:5678. If you inspect the container like we did before you’ll see apple was added to both Aliases and DNSNames:
Bonus Tip on the Gateway IP Address
When we inspected the network and container we saw "Gateway": "172.27.0.1". All of the containers on that network have the same gateway IP address.
We can ping it from any container:
With the way we have things set up we can’t do this which is expected:
But technically if you publish a port back to your host for a service we could use the gateway’s IP address to access that service, such as 172.27.0.1:5678 and 172.27.0.1:5679.
For example, you can modify both services to this and re-up the project:
Then suddenly this works along with everything else we did before:
$ docker compose exec http-client curl 172.27.0.1:5678 Hello from A! $ docker compose exec http-client curl 172.27.0.1:5679 Hello from B!When we publish the port and make a request to the gateway IP address this is getting routed back to the Docker host which forwards the request to the container.
Here’s a couple of takeaways:
- 5678:5678 works because the left side is bound to 0.0.0.0 by default
- If you tried using 127.0.0.1:5678:5678 the gateway IP address wouldn’t work on that port
- In normal use cases you wouldn’t use the gateway IP to talk between containers
- It’s intended for containers to talk back with the host
- In this case you may want to use host.docker.internal instead!
- It’s intended for containers to talk back with the host
I wanted to include this last tip because over the years when setting up all sorts of different networking things I sometimes noticed I could connect containers through the gateway IP address but other times I could not. I only recently learned it was due to publishing a port on all interfaces which enables that.
Clean Up
You can run docker compose down to stop everything, remove those stopped containers and also delete the example network that was created automatically.
The video below runs all of the commands we covered above.
# Demo Video
Timestamps
- 0:56 – The example compose project
- 2:34 – Curling each service by name
- 3:26 – Inspecting the Docker network
- 5:07 – Connecting by other DNS names and IP addresses
- 6:44 – Inspecting a container’s network properties
- 8:47 – Creating a custom alias / DNS name
- 10:04 – The gateway IP address
- 12:22 – Cleaning things up
What’s your favorite Docker Compose networking tip? Let me know below.
Like you, I'm super protective of my inbox, so don't worry about getting spammed. You can expect a few emails per year (at most), and you can 1-click unsubscribe at any time. See what else you'll get too.