Connect two Docker containers having their own Docker Compose files
The provider container creates a Docker network that can be used by a consumer container.
I wanted to create a network between a database Docker container and an application Docker container, both having their own Docker Compose files. And I also wanted to make sure doing it right before implementing this in the actual docker-compose files. Test first baby ...
I also did this some time ago but had to look into this again because Docker Compose now has a name option in networks section. I am writing this post to document how I did it, hope you find it useful as well.
Two containers and commands for testing
In this setup I am using two containers:
- container#1: the database container
- container#2: the application container
A nice tool to play with containers and networking is the Busybox image. It's small and contains a lot of networking commands.
Database container
The database container (the provider) should contain a deamon that is listening to incoming connections. In the application container (the consumer) we run a program that calls the deamon in the database container.
For listening (an actual database deamon is listening) I first tried the obvious netcat command, for example when listening to port 1234:
nc -l -p 1234
But it appeared that netcat terminated when the connection got closed (by telnet) and this terminated the container. Netcat also has a '-k' persistent option but that did not work, it is a known problem. There appears to be a better version called ncat but that is not available in the Busybox image.
That's why I use the httpd command:
httpd -f -v -p 1234
Summary, in the database container we use httpd as the listening service.
Application container
Unfortunately curl is not available in the Busybox image and the wget command in Busybox does not support ports other than 80. That is why I use telnet in the application container to connect to the httpd server.
Finally, I use netstat to check the listening ports in the containers.
The two docker-compose files
The database docker-compose file, db.yml
In the database container we create the network 'postgres12_network'.
# db.yml
version: '3.7'
services:
postgres12:
image: busybox
container_name: postgres12_container
command: /bin/httpd -f -v -p 1234
networks:
- default
networks:
default:
name: postgres12_network
The application docker-compose file, app.yml
In the application container we consume the network 'postgres12_network'.
# app.yml
version: '3.7'
services:
app:
image: busybox
container_name: app_container
command: sleep infinity
networks:
- default
- postgres
networks:
postgres:
external:
name: postgres12_network
Testing the database container
Be prepared, we use a lot of terminal windows here.
Open a terminal window, and start the database container:
docker-compose -f db.yml up
To check if the container is up, open another terminal window and type:
docker ps
Result:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4ab28dc6d47b busybox "/bin/httpd -f -v -p…" 19 minutes ago Up 19 minutes postgres12_container
To check if the Docker network is created, type:
docker network ls
Result:
NETWORK ID NAME DRIVER SCOPE
539decc283dd postgres12_network bridge local
In a third terminal window we enter the database container, using exec, and start a shell (sh) session:
docker-compose -f db.yml exec postgres12 /bin/sh
Check if the httpd deamon is listening to port 1234:
netstat -l -t
Result:
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 localhost:41825 0.0.0.0:* LISTEN
tcp 0 0 :::1234 :::* LISTEN
Now connect to the httpd deamon:
telnet postgres12 1234
Result:
Connected to postgres12
In telnet, hit <ENTER> or type something else and hit <ENTER>.
Result:
HTTP/1.1 408 Request Timeout
Date: Wed, 26 May 2021 11:42:22 GMT
Connection: close
Content-type: text/html
<HTML><HEAD><TITLE>408 Request Timeout</TITLE></HEAD>
<BODY><H1>408 Request Timeout</H1>
No request appeared within 60 seconds
</BODY></HTML>
Connection closed by foreign host
It may look bad but it is in fact looking good, we got a response from the httpd deamon!
In the first terminal window there should be a message like:
postgres12_container | [::ffff:192.168.48.2]:33264: response:400
If you try telnet with a different port, the message will be:
telnet: can't connect to remote host (192.168.48.2): Connection refused
So far so good, let's move on to the application container.
Testing the application container
Open a terminal window, and start the application container:
docker-compose -f app.yml up
In another terminal window check if the container is up, type:
docker ps
Result:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9df4c69b8772 busybox "sleep infinity" 58 seconds ago Up 57 seconds app_container
4ab28dc6d47b busybox "/bin/httpd -f -v -p…" 42 minutes ago Up 42 minutes postgres12_container
Both containers are up and running now.
In another terminal window we enter the application container, using exec, and start a shell (sh) session:
docker-compose -f app.yml exec app /bin/sh
Check if we can connect to the httpd deamon in the database container:
telnet postgres12 1234
Result:
Connected to postgres12
That's good, everything working as expected.
Summary
It is funny (NOT) that the question + answers on how to connect two Docker containers has a huge amount of votes on Stack Overflow, see links below. I think the documentation on the Docker website improved a lot but it needs more (trivial) examples. The 'name' option in the networks section makes it more easy to define networks and read what is going on in a docker-compose file.
Finally, Busybox is a small image but also very limited. It would be nice if more networking commands were added.
Links / credits
BusyBox - The Swiss Army Knife of Embedded Linux
https://www.busybox.net/downloads/BusyBox.html
Communication between multiple docker-compose projects
https://stackoverflow.com/questions/38088279/communication-between-multiple-docker-compose-projects/38089080#38089080
netcat - keep listening for connection in Debian
https://superuser.com/questions/1008348/netcat-keep-listening-for-connection-in-debian
Networking in Compose
https://docs.docker.com/compose/networking/
Read more
Docker Docker-compose
Recent
- Hiding database UUID primary keys of your web application
- Don't Repeat Yourself (DRY) with Jinja2
- SQLAlchemy, PostgreSQL, maximum number of rows per user
- Show the values in SQLAlchemy dynamic filters
- Secure data transfer with Public Key encryption and pyNaCl
- rqlite: a high-availability and distributed SQLite alternative
Most viewed
- Using Python's pyOpenSSL to verify SSL certificates downloaded from a host
- Using UUIDs instead of Integer Autoincrement Primary Keys with SQLAlchemy and MariaDb
- Connect to a service on a Docker host from a Docker container
- Using PyInstaller and Cython to create a Python executable
- SQLAlchemy: Using Cascade Deletes to delete related objects
- Flask RESTful API request parameter validation with Marshmallow schemas