How to create a network of containers that can communicate with each other interchangably?

Hi! I’m incredibly new to docker, but I genuinely have no idea where to even get started. This is my dilemma:
I have containers A, B, C, and D. A and B are both servers while C and D are clients. I need to be able to connect and communicate Server A with Clent C, or Client D when C is turned off.

Additionally, I need to be able to connect Server B with Client C and D.

A and B use phpmyadmin with MariaDB, while C and D have apache and php to run websites. I tried linking two containers using this tutorial and it works, but now I need to be able to have the above scenario.

Link mentioned: How to Run MariaDB & phpMyAdmin in 3 steps using Docker | by Miguel Doctor Yuste | Medium

I would really, really appreciate any form of help I can get, especially with it being explained in laymans terms.

1 Like

Welcome to the world of Docker!

You need to use user-defined networks for connecting and communicating between containers.

To create a user-defined network and add the containers to it, you can use the docker network create command to create the network, and the docker network connect command to connect a container to the network.

Here is an example of how you can create a network named “my-network” and add Server A, Server B, Client C and D to it:

docker network create my-network
docker run --name mariadb --network my-network -e MYSQL_ROOT_PASSWORD=password -d mariadb
docker run --name server-a --network my-network -p 8080:80 -d phpmyadmin/phpmyadmin
docker run --name server-b --network my-network -p 8081:80 -d phpmyadmin/phpmyadmin
docker run --name client-c --network my-network -d httpd
docker run --name client-d --network my-network -d httpd

This command will create a network called “my-network”, and then runs the container for each service and connect them to the “my-network”.

With the above command, all containers that are part of the “my-network” will be able to communicate with each other using the container’s name as hostname.

You can also use docker network connect command to connect a running container to a network.

docker network connect my-network server-a
docker network connect my-network server-b

Hope it helps.

2 Likes

Hi! Thank you so much for the explanation, it really helped my understanding! I do have another question though, If I want to only use Server A and Client C(not D), is there a method in which to do so, with Client C still being in the network.

Eg. I’d like to display a running website in localhost port 80 on client C, with Server A as the database(like mariadb.) And when Client C is shut off, It will display Client D instead while still being connected to Server A. I hope this query was understandable…? I’m still not entirely sure of the terminology myself;; Or is this query actually the answer in the last paragraph you provided?

Sorry, I have another question! Is this entire network situation possible to be in vscode to run in a dockerfiler or docker-compose.yml? How should I go about it if that’s possible? This is mainly because there are php files I’d like to run in localhost with docker…
I’m genuinely so sorry for the noob questions, I’m utterly clueless when it comes to docker :sob:

I tried doing the instructions you mentioned above, but localhost refused to connect…?

Yes, you can accomplish that by using the same user-defined network and connecting only the necessary containers to it. For example, you can create a network named “my-network” as before, and then run and connect only Server A and Client C to it, like this:

docker network create my-network
docker run --name mariadb --network my-network -e MYSQL_ROOT_PASSWORD=password -d mariadb
docker run --name server-a --network my-network -p 8080:80 -d phpmyadmin/phpmyadmin
docker run --name client-c --network my-network -d httpd

With this setup, Server A and Client C will be able to communicate with each other using the container name as hostname.

If you want to display a running website in localhost port 80 on client C, you will need to configure the web server running on the Client C container to serve the website. Also, you need to configure the web server running on the client C container to connect to the Server A container for the database.

When you want to use Client D instead, you would stop the Client C container and start the Client D container and connect it to the same network. With this approach, the Client D container will be able to communicate with the Server A container and use it as a database.

docker stop client-c
docker run --name client-d --network my-network -d httpd

To connect and communicate Server A with Client C or Client D when C is turned off, you can use Docker Compose to define and run multiple containers as a single service.

First, you’ll need to create a docker-compose.yml file in the root directory of your project. In this file, you’ll define the services for each container (A, B, C, and D), along with their respective configurations and dependencies.

To connect Server A with Client C, you would define the service for Server A and specify that it depends on the service for Client C. Then, you would set the environment variables for Server A to connect to the service for Client C (i.e. the IP address and port of Client C’s service).

To connect Server B with Client C and D, you would similarly define the service for Server B, specify that it depends on the services for both Client C and D, and set the environment variables for Server B to connect to both of those services.

You can use the same method to link with other containers as well.

Here is an example of how you might define the services in your docker-compose.yml file:

version: '3'
services:
  server_a:
    image: mariadb
    depends_on:
      - client_c
    environment:
      - DB_HOST=client_c
  server_b:
    image: mariadb
    depends_on:
      - client_c
      - client_d
    environment:
      - DB_HOST=client_c
      - DB_HOST_2=client_d
  client_c:
    image: httpd:latest
    environment:
      - APACHE_RUN_USER=www-data
      - APACHE_RUN_GROUP=www-data
  client_d:
    image: httpd:latest
    environment:
      - APACHE_RUN_USER=www-data
      - APACHE_RUN_GROUP=www-data

In this example, server_a is dependent on client_c and server_b is dependent on both client_c and client_d. Then you can use docker-compose up command to start all the containers defined in the compose file and it will automatically link the dependent services.

1 Like

Ohh I see! I was doing docker-compose but I didn’t realise I needed to add that sort of dependency for the client container! Thank you so much for answering my queries, I’ll go try it out right now!

I tried out the code and phpmyadmin/mariadb didnt work, it kept giving me the error “Error response from daemon: pull access denied for phpmyadmin/mariadb, repository does not exist or may require ‘docker login’: denied: requested access to the resource is denied” this is my current docker compose now…

version: ‘3’
services:
server-a:
image: phpmyadmin/mariadb:10.3
depends_on:
- client-c
environment:
- DB_HOST=client-c

server-b:
image: phpmyadmin/mariadb:10.3
depends_on:
- client-c
- client-d
environment:
- DB_HOST=client-c
- DB_HOST_2=client-d

client-c:
image: httpd:latest
environment:
- APACHE_RUN_USER=www-data
- APACHE_RUN_GROUP=www-data

client-d:
image: httpd:latest
environment:
- APACHE_RUN_USER=www-data
- APACHE_RUN_GROUP=www-data

I’m already logged into dockerhub and desktop, so im not sure why it keeps giving me this error. It gave me the same error for phpmyadmin/mariadb

I already updated the compose file with just “mariadb” as Docker image. Can you try replacing it with it?
Also, please consider the compose file as an example - server-a, server-b, client-c etc. You might need to modify it to make it work.

Hi! sorry, could I clarify what you mean by modify client-c etc as in names? also, i changed a few things and got this as a result: