angle-uparrow-clockwisearrow-counterclockwisearrow-down-uparrow-leftatcalendarcard-listchatcheckenvelopefolderhouseinfo-circlepencilpeoplepersonperson-fillperson-plusphoneplusquestion-circlesearchtagtrashx

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.

26 May 2021 Updated 26 May 2021
In Docker
post main image
Image by Pixabay

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/

Leave a comment

Comment anonymously or log in to comment.

Comments

Leave a reply

Reply anonymously or log in to reply.