GitHub – feerposser/basic-docker-network-tutorial: Basic Docker Network between container using Python Flask and Mongodb
Mục Lục
Basic Docker network for developers
This is a explanation with examples of
docker network
for developers. Hope you enjoy (:
When we talk about different docker services connecting each other, it is implicit that we’re using networks. Depending on what you’re creating, maybe there are no reasons to worry about creating and managing networks because sometimes Docker runs everything for us in the background and everything works fine.
But sometimes we also need to create something different or outside of the box and you’re going to need to understand what is going on inside your Docker container/services.
What you’re going to find (and not to find) in this tutorial
- A basic
Python + Flask
app that connects to aMongoDB
database -
docker run
command line to create and connect containers - How to create and check basic networks in docker
- Understand how
docker
usesnetworks
to connect differentcontainers/services
- How can you find what is wrong with your services connection issues
- Use
Docker Compose
and understand what is going on under the covers - Learn how to use advanced
docker networks
- Learn how to configure
Docker Compose
- Get it all the basics for running containers and services on docker
What is a network in Docker?
First things first, Docker use networks for what? Well, the answer is simple: for the same reason that any PC or virtual machine also use them to share and consume third parties resources.
Every computer machine that needs to connect with some outside world feature will need a network interface for doing that. The same will happen with Docker. When we start a container, Docker will automatically connect it on the netowrk system.
It’ll be nice see that in action, right?
So let’s get started.
1. Image creation
In this example we’re going to create an image with a Python Flask application that returns “It works” on accessing localhost/test and connects in a database and return data in localhost/. To use this, first we need to create the image. If you already know how to build and start a container, go to the 3 step.
In the /tutorial folder, type the command below:
docker build . -t tutorial-image
This going to create an image using the Dockerfile in that folder. This file includes just two important elements:
- the installation of all dependencies inside the requirements.txt file that includes
Flask
andflask-mongoengine
packages - running the app.py when it finishes
After running the command, we can check if the image was created by typing docker images
:
2. Running the image
After build the image, next step consist in running the container and testing him.
To run the image, we can type the command below:
docker run --name tutorial-container -p 80:5000 -d tutorial-image
After running the command above, we can check this out by typing the docker ps
and searching for the “tutorial-container” in the list.
If the status is up and running, this means that we’re able to access the flask
application on the following address: http://localhost/test
and see the API result telling that “It works!”.
Here is what the command is actually doing:
- –name able us to set a name to the container, as can be verified in the
docker ps
result. If we skip this, Docker will set a name randomly for us. - -p flag is very important to make the application works. If we jump over this, nothing will work by accessing localhost/test. -p means that we’re connecting the 80 port of the host to the 5000 port of the container. Do yout remember that the Flask uses 5000 port by default? Whitout this flag we’re not able to reach the application running inside the container.
- -d flag is just to run the container in background mode, so we can keep using the terminal to run some other commands.
- Last but not least, the “tutorial-image” is just the image that we wanna run.
3 Where is the network?
After running a container, where is the network default functionality applyed by Docker?
By default, Docker have three default network modes: bridge, host and none. We can see this by typing docker network ls
:
Those are some of the default Docker network drivers. Bridge, the first one, as his name suggests, is used by containers that need to communicate. This is the default network driver of any container when we don’t specify a driver. Also, this is the most commom drive that we’re going to use for simple services aplications and architectures.
Host is a driver that allows the container bind to the host network. If we used this driver, that means the container would beacome just like any other machine inside the network host.
Finally, the none driver means that really there is none network enable on the running container.
In the Docker documentation there are also the overlay, ipvlan and macvlan drivers. But in this article we’re going to use bridge only. If you want more examples of those other drivers, check out the conclusion topic after reading (:
As we saw, bridge is the default driver of any non specified network container. So, our tutorial-container must be using this driver. We can see whether this is true by accessing the network or the container inspector.
Typing docker network inspect bridge
it will show us the bridge driver configuration. And in some point there is an object called “Containers” that contains all the containers using this driver.
And the docker container inspect tutorial-container
also will show us the inspector where in some point it’ll be and object called “Networks” that list the networks used by the tutorial-container.
Now we know that all the containers use this driver by default. That means we can connect them through this network, right?
So in the next step we going to create a database container which ‘tutorial-container’ can access.
3.1 Connecting containers in a network
In this step we’re going to create a database container which can be accessed by the ‘tutorial-container’.
First things first, let’s access the `localhost/` address and see what happens.
If you try it, you’ll get an 500 error.
This is happening because when we try to reach the localhost root address, the Flask
application try to connect in a Mongodb
database and retrieve all the data inside it. You can verify this by openning and reading the comments whithin the app.py file in the tutorial folder.
To solve this problem, let’s try to create a Mongo container.
First things first, let’s take a look on the MongoDB Docker image documentation. To create a container using Mongo we can run the “mongo” official image and set the environment variables to match with the ones in the app.py file. If you don’t know what are the environment variables, take a look on my previus post by clicking here.
docker run -e MONGO_INITDB_ROOT_USERNAME=admin -e MONGO_INITDB_ROOT_PASSWORD=admin -d --name tutorial-mongo-container mongo
If you don’t have the mongo image on your local cache, Docker will download it on Docker Hub and run the container with name “tutorial-mongo-container” or any other name that you want. You can check this out by typing docker images
and docker ps
to check the mongo image followed by the running container.
And as you can imagine, while the container has been created, Docker set him to the bridge network driver.
We can run the same command used before to get a list of containers using bridge driver: docker network inspect bridge
. And in the containers list we can found the mongodb container.
The same will happen if we run “docker container inspect tutorial-mongo-container”. Bridge will be there in the network settings.
Now, when we access the localhost
, maybe a empty list of data will be sort in the screem, right?
The answer is: no. The same Internal Server Error will appear.
This is happening because we need to connect both containers in a same network.
3.2 Creating a network
In this section we’ll create a bridge network and connect both containers on it.
To do this, first let’s stop the containers and after the network creation we can start them using the container network flag.
docker stop tutorial-mongo-container tutorial-container
To create a new Docker bridge network, just type the command below:
docker network create tutorial-network
Docker uses the bridge driver as default to create containers and also to create networks. Running docker network ls
you be able to see the network in the list:
Now, when we run the containers we must use the –network flag to specify the network that we just created.
docker run -e MONGO_INITDB_ROOT_USERNAME=admin -e MONGO_INITDB_ROOT_PASSWORD=admin -d --name tutorial-mongo-container --network tutorial-network mongo
docker run --name tutorial-container -p 80:5000 -d --network tutorial-network tutorial-image
To certify that both containers are in the same network, we can inspect the tutrial-network by typing
docker network inspect tutorial-network
And when we access the localhost
, we expect to see a empty list of data. But this will not happn. The same Internal Server Error will appear. But Why?
The answer is simple. In the app.py file, on the mongodb configuration, the “host” attribute need to be set with the database ip address or domain.
But when we’re using Docker in this situation, we do not need to get the ip address and set it manually. We can just use the container name as the domain because Docker implements an internal DNS (Domain Name Service) that can handdle everything for us. Cool isn’t it?
The tutorial-image generated with the app.py are using “mongo” as the domain name of the database. To be able to connect in our mongo container we can fix in two ways:
- Stop the tutorial-container, delete its image, update the app.py file to use the name of our container, build the image again and run the container.
- Just stop the mongo container and start it again using “mongo” as the container name.
As the second solution is simpler for this example, I’ll choose this one.
- docker stop tutorial-mongo-container
- docker run -e MONGO_INITDB_ROOT_USERNAME=admin -e MONGO_INITDB_ROOT_PASSWORD=admin -d –network tutorial-network –name mongo mongo
Now our application container is successfully reaching the database container and retrieve all its data (in this case there is no one, but you get the idea).
4 Conclusion
We saw some basics from Docker Network. Now, if you want to get some more complex or other network definitions, you can take a look in this tutorial from NetworkChuck. I not gonna lie. Crazy amazing complex stuff on that video. Most part of the time you don’t need to configure all those things if you’re a developer and not a professional devops.
And if you want to read a little more about Docker networks, get a look in this post of Docker’s blog to understand more from what happn behind the scenes.
Cheers (: