In many application, you'll need more than one container - for two main reasons:
- It's considered a good practice to focus each container on one main task(e.g. run a web server, run a database, ...)
- It's very hard to configure a Container that does more than one main thing (e.g. run a web server AND a database)
Multi-Container apps are quite common, especially if you're working on real applications.
Often, some of these Containers need to communicate though:
- either with each other
- or with the host machine
- or with the world wide web
Communicating with the WWW (i.e. sending Http request or other kinds of requests to other servers) is thankfully very easy.
Consider this JavaScript example - though it'll always work, no matter which technology you're using:
fetch('https://some-api.com/my-data').then(...)
This very basic code snippet tries to send a GET
request to some-api.com/my-data
.
This will work out of the box, no extra configuration is required! The application, running in a Container, will have no problems sending this request.
Communicating with the Host Machine (e.g. because you have a database running on the Host Machine) is also quite simple, though it doesn't work without any changes.
One important note: If you deploy a Container onto a server (i.e. another machine), it's very unlikely that you'll need to communicate with that machine. Communicating to the Host Machine typically is a requirement during development - for example because you're running some development database on your machine.
Again, consider this JS example:
fetch('localhost:3000/demo').then(...)
This code snippet tries to send a GET
request to some web server running on the local host machine (i.e. outside of the Container but not the WWW).
On your local machine, this would work - inside of a Container, it will fail. Because localhost
inside of the Container refers to the Container environment, not to your local host machine which is running the Container / Docker!
But Docker has got you covered!
You just need to change this snippet like this:
fetch('host.docker.internal:3000/demo').then(...)
host.docker.internal
is a special address / identifier which is translated to the IP address of the machine hosting the Container by Docker.
Important: "Translated" does not mean that Docker goes ahead and changes the source code. Instead, it simply detects the outgoing request and is able to resolve the IP address for that request.
Communicating with other Containers is also quite straightforward. You have two main options:
- Manually find out the IP of the other Container (it may change though)
- Use Docker Networks and put the communicating Containers into the same Network
Option 1 is not great since you need to search for the IP on your own and it might change over time.
Option 2 is perfect though. With Docker, you can create Networks via docker network create SOME_NAME
and you can then attach multiple Containers to one and the same Network.
Like this:
docker run -network my-network --name cont1 my-image
docker run -network my-network --name cont2 my-other-image
Both cont1
and cont2
will be in the container names under same Network.
Now, you can simply use the Container names to let them communicate with each other - again, Docker will resolve the IP for you (see above).
fetch('cont1/my-data').then(...)
Here are the commands used in this project
- Connecting mongo (docker) from host machine
Replace mongodb://localhost:27017
by mongodb://host.docker.internal:27017
- Building the project
docker build . -t actionanand/docker_communication:tagName
- Running the container
docker run -d -p 3000:80 --rm --name docker_communication actionanand/docker_communication:tagName
- Running
mongo
image
docker run -d --rm --name mongoCommunication mongo:7.0
- Finding IP of the mongo (running inside docker)
docker container inspect mongoCommunication
or
docker inspect mongoCommunication
- Look for the
IPAddress
property under the objectNetworkSettings
- Just consider,
172.17.0.3
is the IP, then - Replace
mongodb://localhost:27017
bymongodb://172.17.0.3:27017
- Building the project
docker build . -t actionanand/docker_communication:tagName
- Running the container
docker run -d -p 3000:80 --rm --name docker_communication actionanand/docker_communication:tagName
For this, All the containers should be under the same network
- Create a new docker network
docker network create network_name
docker network create mongo-net
- You can view the existing networks by
docker network ls
- You can remove the unused networks by
docker network rm network_name
docker network --help
is for help related to docker network
- Running
mongo
image with volume and docker network
docker run -d --rm -v mongo-com-vol:/data/db --name mongoCommunication --network mongo-net mongo:7.0
-
-v mongo-com-vol:/data/db
is named volume with the namemongo-com-vol
-
You can view the existing volumes by
docker volume ls
-
You can remove the unused volume by
docker volume rm volume_name
-
docker volume --help
is for help related to docker volume -
Change the DB connection in the project as below:
mongodb://<mongo db container name>:27017
mongodb://mongoCommunication:27017
- Building the project
docker build . -t actionanand/docker_communication:tagName
- Running the container with docker network
docker run -d -p 3000:80 --rm --name docker_communication --network mongo-net actionanand/docker_communication:tagName
-
You can open the postman app(or any other similar client) and try the following API end points
-
GET
request forhttp://localhost:3000/movies
-
GET
request forhttp://localhost:3000/people
-
POST
request forhttp://localhost:3000/favorites
with the following body as example{ "name": "A New Hope", "type": "movie", "url": "https://swapi.dev/api/films/1/" }
And make sure to keep the
type
as eithermovie
orcharacter
. If you use anything apart from this, error will be thrown from backend -
GET
request forhttp://localhost:3000/favorites
-
Accessing DB running inside docker from host machine (our local computer with localhost)
- Exposing mongo(docker) port(27017) to host machine's local host
docker run -d --rm -p 20243:27017 -v mongo-local-vol:/data/db --name mongoDbLocal mongo:7.0
- Connect to the following URl using MongoDB Compass, Studio 3T or NoSQL manager free - for multi connection
mongodb://localhost:20243