Dockerize Python, Flask application

Tram Ho

Money Setup

Remember to check that you have installed Docker and Docker-compose already. If not, then check the end of your previous post to know how to install it.


You clone source code here about offline.

In this article we will only care about docker-python folder after clone . There, I have setup for you a Python application using Flask framework (if any PHP dev can treat it like Laravel of PHP)

If you have Python installed on your computer, you can run the following command to run the project:

Open the browser at localhost: 5000 and you will see the Hello World line

If your device does not have Python, then it is still great. As long as you have Docker and Docker compose installed, everything else, whether or not it doesn’t matter

Build Docker Image

As in the previous article , we first need to create the Dockerfile configuration file and define the environment we want, then we will build the image and run it.

Configure Dockerfile

In the docker-python folder you create the file named Dockerfile , inside has the following content:


  • First line FROM : We start from an Image with Alpint environment and have Python installed with version 3.6. See the list of Image Python where, you check in the official link offline
  • Why choose Alpine but not Ubuntu or Debian, CentOS, …. Then in the previous article in this section, I have analyzed it. Also throughout this series I will always use the Alpine Linux operating system environment
  • Next in the file Dockerfile we have WORKDIR : I will move to the path is / app inside Image, if this path does not exist, it will be automatically created always
  • Next we copy all the files from the folder in the original environment (outside – docker-python folder) and put in the path / app inside Image
  • Next, we install the dependencies, we need to install what we mentioned in the requirements.txt file (this command you can see it looks like npm install in NodeJS)
  • Finally, we use CMD to indicate the default command when a container is initialized from Image: here we will launch the file

Build Docker Image

After fine configuration, the next step is to build Image. You run the following command to build Image offline:

In the previous post I explained to you what the above command did, you can review it.

Quick explanation: The above command will build an image named learning-docker / python with the tag v1 , both the name and the tag we can choose arbitrarily, if we don’t leave the tag, it will automatically be taken as latest . The “dot” at the bottom of the dock indicates that “look for the Dockerfile file in the current directory and build” 😉

After the Image build process is successful, you can check with the command:

Will see the following display:

Python docker

Run Project

After we have successfully built Image, the next step is to run the project and see the results 😉 .

Still in the docker-python folder, you create the docker-compose.yml file, with the following content:

In the previous part of the project, I explained to you the above. If you have not read it, you should take a look 😉 .

Quick explanation:

  • We define a service named app , this service will create a corresponding container when running, the container is created from the image with the name we have chosen.
  • We map port from port 5000 on the root machine (outside) to port 5000 inside the container, because our project is run on port 5000 (Flask default)

It seems like the setup is not different from the previous one with NodeJS 😄 .

To start the project, run the following command:

Then you will see at the terminal displayed as follows

docker compose python flask

Too good, let’s try it out. You open the browser at the address localhost: 5000 okay.

And BOOM 💥

Python docker

Nothing happens 😭😭

Try reviewing the code again:

  • The file is quite simple, nothing formidable
  • There is already a command to run the app in the Dockerfile file
  • The port also has a map in file docker-compose.yml

So where is the problem ??

Obviously if I run directly from the external environment, my root machine (if you have Python installed on the root machine), do not use Docker anymore, then everything is okay … 😖😖

Try reviewing the docs of Flask here , and we have found the truth, we noticed the Externally Visible Server . I will translate for you all:

Therefore, when running our project in a container, only the environment in the container can access the project, our project considers that environment to be localhost , and from the original (external) environment, the query will not be called localhost again.

Note: you pay attention to this because later when dockerize project Nuxt will be similar

So to fix this we do the following.

You modify the file a little as follows:

Above, we only added host = to tell our project to “accept for all access IPs”

It’s okay, let’s rebuild the image then:

After the build is complete, we need to restart the project, run the following command:

And finally open your browser and test it:

Python docker

Great 👏👏

Environment variables (ENV)

The previous article and the one you can see is that the project has been fixed hard 1 port (the previous article is 3000, this article is 5000), so if we want the container to run at a different port, we have to fix the code? ?

At that time, we will think about environment variables , in the dev process and when actually running, using environment variables will help us a lot in minimizing the need to edit code.

Environment variable in Dockerfile

First, we will try using the environment variable declared in Dockerfile to set Port (port) for the project running in the container. (I mean the container will not run at port 5000 anymore)

In the app.js file, we correct the following:

Then in the Dockerfile file we modify the following:

In the docker-compose.yml file, we modified a bit as follows:

You notice above when we map port we only move the right side, the right side is the port of the project running in the container , the left side is the port in the original environment (outside, we can choose arbitrary , and here, port 5000 is the port that users will use to access in the browser)

Next, we proceed to rebuild the image:

And restart the project:

Open the browser at localhost: 5000 (still the same), you will see everything runs normally, but looking through the Terminal, you will see the following:

Python docker

In the image above we see that inside the container, our project has been run at port 5555 already 😉

So if we now want to change the port of the project in the container to 6666, why do we have to rebuild Image?

With environment variables that are easy to change, we have another simple option which is declared in the docker-compose.yml file.

Environment variable in docker-compose

In order to not have to rebuild the image every time we change the port, we will declare an environment variable in docker-compose.yml . Why:

  • The environment variable in the Dockerfile file will be declared when we build the image
  • The environment variable in the docker-compose.yml file will be initialized when the container is initialized , ie when we run docker-compose up . So to change environment variables we just need to download and upload is done 😉

Let’s try it …

In the Dockerfile file, delete the line ENV PORT 5555 .

Then in the file docker-compose.yml we modify the following:

Now we still need to rebuild the image once to get the new updates applied:

Then we restarted the project:

Then F5 re-browse to make sure everything is ok, and look at the terminal:

Python docker

So we can easily change the port of the project in the container when using environment variables. Try changing it to 7777 (remember to download and upload docker-compose) 😉 )

A better way to create environment variables

In the above example, if we want to change PORT to 7777 for example, we have to fix it in 2 places in the docker-compose.yml file, so what if the variable is used in 100 places?

docker-compose support is a simpler, more convenient way to initialize environment variables, which is located in the .env file (just like Laravel 😎 , which means that if we dockerize the Laravel project, we only need 1 common file is .env )

Let’s try it 😃

In the docker-python folder we create the .env file with the following content:


  • variable PORT : indicates the port of the project that runs inside the container
  • variable PUBLIC_PORT : only the port that the “outside world” uses to access the project 😉 (I mean the port we call in the browser)

We modified the docker-compose.yml file as follows:

Then we restarted the project:

Check in the terminal we will see:

Python docker

Great, the project successfully ran at port 8888 in the container. Now check it on the browser.

We open the browser at the address localhost: xxxx (you fill in xxxx see what it is 😉 )

Push Image onto the registry

In the previous article too long I did not add images to the registry and how others can run your project from the image. In this song, we have a place to play 😉

Docker build runs smoothly on our computer and then try to show others how they run 😄

The registry is where we store the Docker image (like a github for saving code, but this is for the Docker image), there are many registry, public and private.

In this series, we will use Gitlab to save the code and save the image on their registry. Gitlab gives us unlimited images in the private registry for each repository (great but also free and private)

Create accounts and repositories on Gitlab

First you need to create an account on (if not already). Then we create a repository named learning-docker for the whole series 😉

Then click the repository we just created, notice the sidebar on the left, hover over Packages , then click Container Registry , this is where we will store the image. 😉

You will see the following display:

Gitlab registry


Now we will practice pushing the registry image of gitlab 😃

First, as in the image above, we need to log into the Gitlab registry first (because this registry is private 😉 ). We run the following command to login:

We will see in the terminal asking for the email and password of the gitlab account, please enter your parameters.

Then the next step as in the image above we need to build the image. But because our image is already local, we don’t need to rebuild it.

“Ok so I can push it to Gitlab right away?” – You can’t eat it right now 😄

When pushing the image onto the gitlab registry we need to name the image according to their standards, the tag can be arbitrary but the name must be correct, in the following format:

In the image above, copy and paste the docker push command to see how you need to name the image

After knowing how to name then we have 2 options:

  1. Rebuild the image as command test 2 in the image above to get an image with the name in the format
  2. Renaming the existing Image is available locally

Here I will choose the number 2 is to change the name so we don’t have to rebuild the image 😉

We run the following command to list the image:

We will see the following:


Next we will run the following command:

Note: the name of the gitlab image above is for you, and if you try to list the image, you will see a new image is a copy of the old image, the old image is still there, You can delete the old image if necessary

Finally, we push the image onto the registry.

After successful upload, we return to the Container Registry page on gitlab and check:

Gitlab registry

You can see that we have an image on the registry with the latest tag (because just now renamed and when pushing I did not say what the tag is, the docker default tag is latest )

Pull Image and run it

It’s time for the truth, I wonder if everything is fine when I bring the image to another device or somewhere ??

Now you will use a different machine, or if you do not have then move to a certain folder to test, if using another machine, remember that it must have Docker and Docker compose installed offline.

We create a test folder called test-docker wherever you want. In it we have the following files:

  • .env to create environment variables
  • docker-compose.yml to launch the project

The file .env we keep the content, but the file docker-compose.yml we modified as follows:

Then we just need to run the following command to launch the project:

Because the image we put is on a private gitlab, only we can retrieve the image, so if you see an authentication error, run the following command to login:

And everything will run as usual 😉 , we will have the same results as in our original machine, no matter what we put the image to run on any machine.


I know this article is causing you eye pain because of the length, because there are many things I want to talk about, but gradually the new concepts will end and we will focus more on practice, eye pain. I hope so it decreases 🤣🤣

Through this article, you have seen how to dockerize a Python application like the previous one for NodeJS, right? 😉 . We still do not need to install Python directly in the (external) native environment, still only docker and docker-compose ❤️

In this article there are 2 important content I want to talk about:

  • How to use environment variables
  • How to upload an image to the registry so that you can download it later and how to download an image to run it

Thank you for watching, if you have any questions please comment below let me know 😉 .

Source code for this article I put here (branch complete-tutorial okay)

See you in the next post ^^

Chia sẻ bài viết ngay

Nguồn bài viết : Viblo