DEV Community

loading...

Cross Container Communication And Networking In Docker

Arsh Sharma
Software engineer particularly interested in distributed systems and building infrastructure tools.
・3 min read

This is the fourth post in my series about Docker. You needn't have gone through the previous one in order to understand this. The only prerequisite is that you have an idea about what Docker containers are. If you don't I suggest you take a look at the second post.

In this post, I'm going to explain to you how you can make the app running in your container communicate with other services (APIs, databases) outside of that particular container. Now when we talk of these services which are running outside of the container we can divide them into three categories:

  1. Running on the World Wide Web. Like a public API (for example, SWAPI)

  2. Running locally on your machine. (for example, a database instance running locally)

  3. Running in another container. (for example, a database instance running in another container)

Let us have a look at each of these cases separately.

Running On The World Wide Web

Guess what? You'll face absolutely no problem here. If the code in your container makes a call to some outside API then it will face no problem and will work perfectly like it would have had you not containerized it :)

Running Locally On Your Machine

If you're running a service, let's say a database locally, and want your containerized app to interact with it then you just have to make one simple change in your code.

The service you'd be running locally would have a URL something like:

localhost:8000/service
Enter fullscreen mode Exit fullscreen mode

for connection. All you have to do in your code to get this to work is to replace localhost with host.docker.internal. So:

'host.docker.internal:8000/service
Enter fullscreen mode Exit fullscreen mode

This works because host.docker.internal is a special address that automatically gets translated to the correct address of the host machine by Docker.

Running In Another Container

This is a little complex than the other two (which shouldn't be a surprise :P ). But I'll try to explain it in as simple terms as possible.

The basic idea is that whenever you want two or more containers to be able to "communicate" with each other you put them in the same "network". A Docker Network is something you'll create before starting either of the containers, using this command:

docker network create dummy_name
Enter fullscreen mode Exit fullscreen mode

This will create a network by the name of dummy_name. Now you will specify this network while starting all the containers you want should be able to communicate with each other.

There is one other small change which you will have to make. You remember how in the second case we replaced the localhost with host.docker.internal? Similarly here we will replace that with the name of the container we want to access.

For example:

docker run -network dummy_name --name appCode image-one
docker run -network dummy_name --name dbInstance image-two
Enter fullscreen mode Exit fullscreen mode

If I plan to do this then we will need to change localhost in the code (from which we built image-one) like this:

dbInstance:8000/service
Enter fullscreen mode Exit fullscreen mode

Docker would automatically now understand this since the two containers are part of the same network. If it's getting a bit complicated let me sum it up:

  1. Create a network
  2. If container A needs to talk to Container B then in the code of container A, replace localhost with Container B's name.
  3. Start the containers with the correct names and do not forget to specify the same network while starting then.

And with this, you're now good to go!

Conclusion

This solves all our problems related to networking while using containers. I hope you now have a pretty good understanding of this and will feel confident enough to use it.

Thanks for reading! :)

If you have any feedback for me or just want to talk feel free to connect with me on Twitter. I'll be more than happy to help you out! :D

Discussion (4)

Collapse
clavinjune profile image
Clavin June

How can I get rid of the port, so I can call the service like this

host.docker.internal/service

instead of this host.docker.internal:8000/service

Collapse
rinkiyakedad profile image
Arsh Sharma Author

I think the example I used might have been a bit unclear. The service you'd be using would have a port for it on the localhost. For example let's say your backend is running at localhost:3000. Then you can use host.docker.internal:3000 in the code present in your container.

What I mean to say is that the serivce would be running at a port on localhost so you would have to necessarily specify the port while using host.docker.internal. The /serivce I used might be a bit confusing cause it is the service it self which is actually running on localhost:8000 and not on localhost:8000/service.

Collapse
clavinjune profile image
Clavin June • Edited

I understood, but what I meant is how can we get rid the port

Thread Thread
rinkiyakedad profile image
Arsh Sharma Author

The default port is 80. If you can get your service to run on that then you would simply be able to use host.docker.internal. Otherwise I don't think so you can get by without specifying the port since your service operates on a specific port itself.