Linking containers is one of Docker’s basic concept: It allows for accessing network services a certain container offers without the need of exposing the needed port(s) to the Docker host. The same concept is available in Docker Compose. However, it get’s a bit more complicated when it comes to linking a container not defined in the same compose file (docker-compose.yml).
Linking containers without Docker Compose is easy using the –link parameter:
docker run --name test1 something docker run --name test2 --link test1:test1 something
Here, a container named test1 is started first, afterwards, a second container test2 is started. Container test1 gets linked to test2, so you can access test2 from within test1 just by using test1’s name (test1).
The same thing is possible if you have two services defined within one Docker Compose File:
version: '2' services: test2: image: something depends_on: - test1 links: - test1 test1: image: something
The result is exactly the same as with the docker run command.
But how can you link containers not defined in the same docker compose file?
I have such a scenario: I have multiple docker compose files, one for each domain, each defining tightly related services (such as blog, backend services and database). Then I have one frontend web server accessible from the internet, proxying incoming requests to the various services defined in multiple docker compose files.
Docker Compose offers the “external_links” configuration option which allows you to link containers not defined in the compose file:
version: '2' services: test2: image: something external_links: - domainA_test1_1
Here, “test1” is a service defined in the composition “domainA”. Docker Compose automatically adds a “_1” to the container name (as long as it’s the first and only running instance).
However, things get a bit more complex here. The reason for this is that Docker by default automatically creates a separate network for each docker composition. Every container defined in the same docker compose file gets attached to the same network. The networks can’t access each other if you don’t do something about it.
Option 1: Make your container requiring the link a member of the foreign networks
To do this, you need to add two sections to the docker compose file where you want to define the link: Make the specific container a member of the foreign network and define for the docker compose file itself that these networks are external.
version: '2' services: test2: image: something external_links: - domainA_test1_1 networks: - default - domainA_default networks: domainA_default external: true
As you can see, “domainA_default” is the network that docker automatically has created for the composition “domainA”. Additionally, I’ve attached the service to the default network.
In test2, you can access test1 using it’s default DNS name “domainA_test1_1”.
You can view a list of all docker networks using this command:
docker network ls
Option 2: Set bridge networking mode for all containers you want to link with each other
Option 1 allows for private networks linked with each other. However, you may run into issues if you need to initiate outbound connections from within your linked containers.
Therefore, another option is to enable the bridged networking mode for all the containers you want to link together:
version: '2' services: test2: image: something network_mode: bridge external_links: - domainA_test1_1
version: '2' services: test1: image: something network_mode: bridge
Which option is right for you, depends on your concrete situation. I personally prefer option 1, because it uses private networks instead of bridging the containers to the host network.