Docker: Custom networks
Guillaume Briday
3 minutes
This article is a follow-up to the presentation I gave on Docker: Understanding and Implementing Docker. I received some relevant feedback and wanted to revisit points that I believe are important.
Networks
I didn't specify this earlier, but Docker has a default network. It's called bridge
, and if you don't change the configuration, all containers will be associated with this network. What does this mean for us? If you don't need to isolate your containers, they will all be able to communicate with each other on this network without requiring links
, for instance. To achieve this, you can use either the container's IP address or the name assigned to a container via the --name
option.
You can list your networks using the following command:
$ docker network ls
Dependencies between containers
Links
are not only used for this purpose. Beyond creating private networks between containers to transmit sensitive information, they allow you to define a launch order and dependencies between your containers. Additionally, they enable you to create aliases for your container names.
For example, if your container is named mysql
, but another service needs it to be called database
, you can create an alias with the syntax --link mysql:database
. If the second argument is the same as the first, it becomes optional. Thus, in your database configuration, you can directly set the host
as database
instead of using the container's IP address or mysql
.
For dependencies, if you're using docker-compose up -d
, the question doesn’t arise because all containers are launched without conditions.
However, if you need to launch a container that depends on another (for example, a PHP container that runs tests and requires a MySQL container), with the docker-compose run
or docker-compose exec
commands, Docker won't know that the PHP container depends on the MySQL container to function. It will only launch the container you requested, causing your tests to fail.
Links
ensure that dependent containers are also launched.
If no links
are used, no other containers are launched. However, docker-compose
creates a custom network to avoid using the default one, maintaining isolation between your projects.
$ docker-compose run --rm blog-server ./vendor/bin/phpunit
Creating network "laravelblog_default" with the default driver
PHPUnit 6.4.4 by Sebastian Bergmann and contributors.
...
If links
are used, all dependent containers are also launched:
$ docker-compose run --rm blog-server ./vendor/bin/phpunit
Creating laravelblog_redis_1 ...
Starting laravelblog_mysql_1 ...
Starting laravelblog_mysql-test_1 ... done
Creating laravelblog_redis_1 ... done
PHPUnit 6.4.4 by Sebastian Bergmann and contributors.
...
Since custom networks became available, it's no longer recommended to use links
, which have been deprecated. If you need to isolate containers, it's better to use a dedicated custom network and manage dependencies with depends_on
.
A simplified version of our old docker-compose.yml
would look like this:
services:
blog-server:
- links:
+ depends_on:
- mysql
- mysql-test
- redis
Custom Networks
As we've seen, you can define custom networks. These need to be specified in two places: at the same level as services to create them (called top-level networks
) and within the services themselves to use them (service-level networks
). Even though the networks
section is defined after the services
section in your docker-compose.yml
, they are created first.
To define a network with docker-compose
:
services:
blog-server:
depends_on:
- mysql
networks:
backend:
driver: bridge
In this example, we’ve created a network named backend
with the bridge
driver, which is the default driver in Docker. You can find all available options in the official documentation. I won’t go over all of them, as it’s more important to understand how it works; the rest depends on your needs.
A service can join one or more networks:
services:
blog-server:
depends_on:
- mysql
networks:
- backend
- frontend
networks:
backend:
driver: bridge
frontend:
driver: bridge
The names of networks created with docker-compose
will follow the pattern [projectname]_[networkname]
. In our case, it would be laravelblog_backend
. You can inspect a container with the command:
$ docker inspect <container_id>
You can also create networks with Docker:
$ docker network create --driver bridge <network_name>
And to join a network when launching a container:
$ docker run --name blog-server -v $(pwd):/application --network <network_name> -d laravel-blog
In the network section, you’ll notice two networks, each with distinct IPs for the same container depending on the network.
If you don’t need to create a custom network for specific cases, it's recommended to use the default network, as docker-compose
handles it for you.
I've updated my docker-compose.yml
for the laravel-blog project if you’d like to see the complete example.
Thank you!