Networking is all about communication between processes. Docker’s networking does the same. Docker networking is used primarily to establish communication between Docker containers and the outside world via the host computer where the Docker daemon runs. Docker supports various types of networks that are suitable for different use cases. This article will focus on Docker compose networking. However, before I get into that, let me briefly describe the different docker network drivers.
Below are the network drivers that Docker uses:
- Bridge
- Host
- None
- Overlay
- Macvlan
Bridge
- It’s a private default network that is created on the host
- Each container connected to the network has an internal IP address that allows them to communicate easily with one another.
- The Docker server (daemon), creates a virtual Ethernet bridge docker0, which operates automatically by sending packets between various network interfaces.
- These can be used for applications that are carried out in a separate container.
Host
- It is a public network.
- It uses the host’s IP address as well as TCP port space in order to display services that are running within the container.
- This driver effectively disables network isolation between docker containers and docker hosts. Users will not be able to run multiple containers from the same host using this network driver.
None
- This network driver will prevent Docker containers from accessing external networks or communicating with other containers.
- This option can be used when a user wishes to disable networking access to a container.
- None is a loopback interface. It has no external network interfaces.
Overlay
- This is used to create an internal private network for the Docker nodes within the Docker Swarm cluster.
- Docker Swarm allows developers to manage and build a cluster of Docker nodes.
- It is an important network driver for Docker networking. It facilitates the interaction between the Docker swarm service and the stand-alone container.
Macvlan
- It makes it easier to communicate between containers.
- The network assigns a MAC to the Docker container. This Mac address is used by the Docker server (daemon), to route network traffic to a router.
- Note: Docker Daemon, a server that interacts with the Operating System and performs all kinds of services, is called Docker Daemon.
- This is useful when the user wishes to connect directly to the container to the physical network rather than to the Docker host.
Networking with Compose
Compose automatically creates one network for your app. Each service container joins a default network. It can also be reached by other containers, and they will discover it at the same hostname as the container name.
Let’s assume your app is in the myapp directory. This is how your docker-compose.yml should look:
version: "3.9"
services:
web:
build: .
ports:
- "8000:8000"
db:
image: postgres
ports:
- "8001:5432"
The following occurs when you run docker–compose up:
- It is created a network called myapp_default.
- Web’s configuration creates a container. It joins the network myapp_default with the name web.
- A container is created by using db’s configuration. It joins the network myapp_default with the name db.
Now each container can look up the hostname web and db to get the correct container’s IP address. Web’s application code can connect to URL postgres://db.5432 to access the Postgres database.
It is important that you distinguish between CONTAINER_PORT and HOST_PORT. For db, HOST_PORT is 8001 while the container port 5432 is (postgres default). The CONTAINER_PORT is used for networked service to-service communication. The service can also be accessed outside of the swarm if HOST_PORT has been defined. Within the web container, your connection string to db would look like postgres://db:5432, and from the host machine, the connection string would look like postgres://{DOCKER_IP}:8001.
When you make a configuration modification to a service, and then run docker-compose to update it, the old container will be removed. The new container joins the network with a different IP address and the same name. Containers can connect to the new address by looking up the name but the old address will not work anymore. Containers that have connections to an older container should be sealed. Containers are responsible for identifying this condition and reconnecting.
You can use the overlay driver built into Docker Engine to enable multi-host communication when you deploy a Compose app on it.
Linking Containers
Services may be able to use additional aliases. Services can reach each other through the same network. In the following example, web can reach db using one of two hostnames: db or database.
version: '2'
services:
web:
build: .
links:
- "db:database"
db:
image: postgres
Docker Compose uses Docker Compose’s service name (db) if you don’t specify a second hostname, such as – db or – db:database. Links are dependent like depend_on does. This means that links determine the order in which service startup takes place.
Configuring the Default network
You can also configure the default network to replace or add to your custom network. You can simply create a default entry in networks.
version: '2'
services:
web:
build: .
ports:
- "8000:8000"
db:
image: postgres
networks:
default:
driver: custom-driver-1
Custom Networks
To create more complex topologies, specify your network drivers and options. This configuration can be used to connect services to external networks Docker Compose doesn’t manage. Each service can choose which networks it wants to connect to using its service-level network keys.
This example shows two custom networks. Proxy cannot connect to db as they don’t share a network. However, app can connect both. The front network specifies the IPv4 address and IPv6 addresses. We also need to create an ipam block that defines the subnet configurations and gateway configurations. You could customize one network or both, but we want separate drivers to seperate the networks. (Review Basic Networking with Docker to refresh your memory)
version: '2'
services:
proxy:
build: ./proxy
networks:
- front
app:
build: ./app
networks:
# you may set custom IP addresses
front:
ipv4_address: 172.19.238.15
ipv6_address: "3001:4984:5989::10"
- back
db:
image: postgres
networks:
- back
networks:
front:
# use the bridge driver, but enable IPv6
driver: bridge
driver_opts:
com.docker.network.enable_ipv6: "true"
ipam:
driver: default
config:
- subnet: 172.19.238.0/24
gateway: 172.19.238.1
- subnet: "3001:4984:5989::/64"
gateway: "3001:4984:5989::1"
back:
# use a custom driver, with no options
driver: custom-driver-1
Pre-Existing Networks
Docker Compose can be used with pre-existing networks; you just need to use the external option.
version: '2'
networks:
default:
external:
name: existing-network-1
In this case, Docker Compose never creates the default network; instead connecting the app’s containers to the existing-network-1 network.
Final Thoughts
So that was all about networking in Docker compose. Now you know how to create a network using docker compose yaml file, how to use custom network or use pre-existing network. Go ahead and setup docker networking using docker compose.