Basic Networking in Docker
Jan 15, 2020 · 5 Min Read · 7 Likes · 0 CommentWe already know that Docker is used for containerization. But networking in docker makes it even better tool for deployment. You can make standalone deployments in containers and communicate between them, or make containers act as host, or even assign mac addresses to containers and act them as devices. It does not matter which host machine you are in, you can make dockers communicate in-between them. In this article, we are going to discuss about bridge networking in docker, and in the end will see on how to communicate from container to host or vice versa.
Communication between containers
If you have several standalone applications in different containers and need to communicate between them, then you can use bridge as network driver in docker. Its the default driver, it will be assigned if you don’t specify network driver type. It is used when you deploy standalone applications in different containers and they need communication.
How it works
The docker documentation states:
In terms of Docker, a bridge network uses a software bridge which allows containers connected to the same bridge network to communicate, while providing isolation from containers which are not connected to that bridge network.
Means, the containers connected to bridge network can communicate with each other, but can’t communicate which are outside of that network. It won’t be exposed unless you explicitly do that.
Create bridge network
You can create a bridge network by:
docker network create skynet
Or remove it:
docker network rm skynet
You can also inspect the network using:
docker network inspect skynet
Connect containers to network
After creating the network, now its time to add your containers to that network like this:
docker create --name nz01 \
--network skynet \
--publish 8080:80 \
nginx:latest
Or you can add a running container to network:
docker network connect skynet nz01
Disconnect containers from network
You can use the following command to do that:
docker network disconnect skynet nz01
Examples on how to communicate between containers
It is pretty simple, you need to use the name of a container and port it is exposing. For example, if you want to access nginx container(named nz01
in previous example) from another container, then try like this:
wget nz01:80
Keep in mind that the port number is the port where the application is running inside the container, not the port it has exposed. In docker, port mappings are writtern in <EXPOSED PORT>:<INTERNAL PORT>
, in this example 8080
is accessable from outside world, where nginx is running in port 80
inside the container.
Here is another example, lets say an web application is running in container web
at port 8000 and from nginx
you want to expose it. Then the nginx configuration should look like this:
upstream web {
ip_hash;
server web:8000; // here web is the name of the container or service if you are using docker compose and application is running at port 8000
}
server {
location / {
proxy_pass http://web/;
}
listen 8000;
server_name localhost;
}
Example with ‘Docker Compose’
Docker Compose provides a better way of writing networks. Here is an example:
version: "3"
services:
nginx:
image: nginx:alpine
container_name: nz01
ports:
- "8000:8000"
volumes:
- ./config/nginx:/etc/nginx/conf.d
depends_on:
- web
networks:
- skynet
web:
build:
context: .
dockerfile: compose/django/Dockerfile
container_name: dz01
volumes:
- ./src:/src
expose:
- "8000"
networks:
- skynet
networks:
skynet:
driver: bridge
Here I just provided a networks section in each of the services defining which network to connect. And inside networks section at the bottom, I have defined which driver to use for communication. We could have defined multiple networks if needed.
Communication between host and container
From container to host
Communication from container to host is pretty straight forward. You just need to expose the container in certain port and from host machine access it through localhost:port or 127.0.0.1:8000. For example:
> docker run -p 8000:80 -it web
> wget localhost:8000
From host to container
This communication has been made simple for MacOs and Windows, but not in linux(at the moment of writing). All you need to do is use host.docker.internal
. For example, if you want to use postgres database in django from host machine:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'postgres',
'USER': 'postgres',
'PASSWORD': 'postgres',
'HOST': 'host.docker.internal',
'PORT': 5432,
}
}
But for linux machine, you can add the following lines in docker-entrypoint.sh
(copy pasted from this article):
HOST_DOMAIN="host.docker.internal"
ping -q -c1 $HOST_DOMAIN > /dev/null 2>&1
if [ $? -ne 0 ]; then
HOST_IP=$(ip route | awk 'NR==1 {print $3}')
echo -e "$HOST_IP\t$HOST_DOMAIN" >> /etc/hosts
fi
(main entrypoint)
What its doing is that if host.docker.internal
does not work when pining, it will add the host.docker.internal
as alias of HOST IP and add it in /etc/hosts
.
In conclusion
Although in this article we focused on bridge networking, but there or other types of networking which can be used based on situations. Networking in docker is a breeze compared to doing it manually, and making it a very powerful means of deployment and distribution(along with its awesome platform agnostic services). Thank you for reading, if you have any opinion regarding this article, please share in the comment section below.
Last updated: Jul 13, 2024
I won't spam you. Unsubscribe at any time.