Do you need to create your first Docker image to run your Python module in a Docker container? In this tutorial, you will learn how to do that.
Most get a bit scared the first time they need to create their first docker image – it seems so complex. But don’t worry, in this guide, you will learn how to build your python docker image which you can use to run your Python module in a Docker container.
Docker enables developers to easily deploy their applications in containers to run in a specific environment decided by you.
That might be a bit difficult to understand at first.
Take our Python API – we already know, that it does not run with Python 3.8. But we want to be able to deploy it in different places without the trouble of having correct Python, libraries, environment variables, etc. This is what Docker can do for us.
You can package Python 3.10 (in our case) with the correct libraries in a Linux OS.
What about this Linux, you might wonder. I don’t run Linux.
Neither do I – but I can run it in my Docker Daemon.
This is the beauty of it, you can run it on any machine or server with a Docker Daemon.
This actually solves a big problem. Imagine you also had another API running, but it only worked with Python 3.8. Your new one does not work with 3.8.
But each of these APIs is running in each their package with each their environment.
Therefore, you can have it running isolated in their own containers (as they are called) – also, they can call each other endpoints (APIs) and communicate with each other.
You suddenly understand the power of Docker.
There can seem to be a lot of terminology with Docker.
The good news is, you only need to understand the high-level concepts of how it works – the precise concepts can ease communication, but most people understand you if you call a Dockerfile the Docker image.
The terminology used is as follows.
I think we will learn by doing, but in short, you need the following.
Don’t worry too much about understanding all this now. You will learn it in this tutorial.
You can install Docker Desktop and it will automatically install all you need to manage all Docker tools need.
Go to Docker official download and get Docker Desktop for your OS (here).
Follow the installation instructions and you are ready to go.
You can launch Docker Desktop, which will start the Docker Daemon in the background.
The best way to learn is to try it on a real project. To do that, I suggest you clone the following project (here)
If you want to understand the code in the project, I suggest you read this tutorial. Then you can continue to run the Python module in Docker.
If you want to understand the logging read this one.
And if you want to understand the tox testing framework you should read this one.
Here we will explore the Dockerfile in the project.
FROM python:3.10-bullseye
COPY requirements.txt .
RUN pip install -r requirements.txt
RUN mkdir /src
COPY . /src
WORKDIR /src
EXPOSE 8000
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
On the first line, we take the base image, which is the most recent Python 3.10 version, called python:3.10-bullseye.
The base image is like the foundation of what you are running it on. This is a prebuilt image and contains all the standard libraries for the Python 3.10 release.
This makes the next line understandable.
COPY requirements.txt .
This will copy the requirements.txt file to the Docker image.
Notice that we need the requirement.txt to be in the same folder as the Dockerfile where we will build the image.
RUN pip install -r requirements.txt
The next line will run a command: pip install -r requirements.txt.
Remember what that did?
Yes, you are right, it installs all the requirements.
Notice, that the RUN will execute this command inside the Docker image, and hence, the installation is inside the Docker image.
RUN mkdir /src
This will create a folder /src inside the Docker image.
COPY . /src
This will copy all the files to the Docker image.
Now you might wonder about one thing.
This has something to do with how Docker images are created. And, yes, you could do it, but I will tell you why the approach in the Dockerfile might be good.
Docker images are built in layers. And when you re-build an image, it will only build from the layer there have been changes.
Each line in the Dockerfile represents a layer.
Now consider this.
This change does not affect the requirements.txt file. Hence the installation of all the required libraries will not be executed again. It will start from the COPY . /src command.
You see, it will save time the next time you build your image.
WORKDIR /src
This will set the working folder (or directory). This means, when you execute a command, it will run from this folder.
EXPOSE 8000
This will inform Docker that the container will listen to that specified network port.
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
Finally, the CMD is the command.
This can seem a bit confusing. But it takes the list of arguments and runs the command uvicorn with all the arguments.
uvicorn app.main:app –host 0.0.0.0 –port 8000
You might wonder.
Now we have some basic understanding of the Dockerfile, we are ready to build the Docker image.
Before you build your first Docker image, you need to ensure that the Docker Desktop is running.
This is needed to have the Docker daemon running.
Now run the command: docker build -t fruit-api .
Notice the space and dot at the end of the command.
Then it will start making a lot of stuff. You need to wait until it finishes.
[+] Building 16.3s (12/12) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 257B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/python:3.10-bullseye 2.5s
=> [auth] library/python:pull token for registry-1.docker.io 0.0s
=> [1/6] FROM docker.io/library/python:3.10-bullseye@sha256:8846e26238945dc748151dc3e0f4e9a00bfd09ad2884edcc6e739f085ad9db3b 0.8s
=> => resolve docker.io/library/python:3.10-bullseye@sha256:8846e26238945dc748151dc3e0f4e9a00bfd09ad2884edcc6e739f085ad9db3b 0.0s
=> => sha256:cee26ee24819941bed15229baeb8e437866a7864432a6b15d1bfbd5da70cee09 2.22kB / 2.22kB 0.0s
=> => sha256:ace6d68f6bea726cb6f2aa5a02cc799df1902deef9a94b362fc6a23ff8a69efc 3.04MB / 3.04MB 0.4s
=> => sha256:8846e26238945dc748151dc3e0f4e9a00bfd09ad2884edcc6e739f085ad9db3b 1.86kB / 1.86kB 0.0s
=> => sha256:b62e4294564cd2bdf0693cbd786338d15734a6fbee280faa976c23f3ae60f636 8.53kB / 8.53kB 0.0s
=> => extracting sha256:ace6d68f6bea726cb6f2aa5a02cc799df1902deef9a94b362fc6a23ff8a69efc 0.3s
=> [internal] load build context 6.4s
=> => transferring context: 46.05MB 5.3s
=> [2/6] COPY requirements.txt . 0.2s
=> [3/6] RUN pip install -r requirements.txt 6.3s
=> [4/6] RUN mkdir /src 0.2s
=> [5/6] COPY . /src 0.3s
=> [6/6] WORKDIR /src 0.0s
=> exporting to image 0.4s
=> => exporting layers 0.3s
=> => writing image sha256:8842602312874f7a1c289a2f6a47e5b341033ee4a447ed73381c06df1d44421e 0.0s
=> => naming to docker.io/library/fruit-api 0.0s
It tells you to use docker scan. This is beyond the scope of what we will cover and requires you to create a login.
The image is created from the official Python image and the files in your project.
Now, where is the image?
Look in Docker Dashboard (Docker Desktop) and click images and search for the fruit-api.
Now there is your image.
Can you access it?
It is not running. Remember, you need to launch it in a Docker container.
The name (beautiful_diffie) will most likely be different in your case. This is simply a random name.
If you click on it you will see the output.
To call it, you can run make_order.py file.
Then you should see it in the log-in Docker Desktop.
When you want to shut down your Docker container – that is, you don’t want to have the service running on port 8000, what do you do?
If you hover the mouse over you will see the following options.
It has a stop button (and some more).
If you click the stop button, it will stop.
Then you can start it again with the RUN button (the STOP will change to a RUN button).
Right now, you have built your Docker image and you can run it in a Docker container.
If you make changes to the code in PyCharm, those changes will not be reflected if you run the container we have available.
To make changes you need to build a new image and run that image as a container.
Let’s try that.
Make the following change in app/routers/order.py
import logging
from http import HTTPStatus
from typing import Dict
from fastapi import APIRouter
logger = logging.getLogger(__file__)
router = APIRouter(tags=['income'])
@router.post('/order', status_code=HTTPStatus.OK)
async def order_call(order: str) -> Dict[str, str]:
logger.info(f'Incoming order received: {order}')
return {'Order Received': order}
Let’s make this simple change to line 14. Change it to return {‘Order received’: order}
If you start the Docker container, you will see it is the old version running.
To be clear, you can modify make order a bit to print the response.
As you see – it returns the old response we had.
What to do?
Now make an order (run make_order.py)
And it prints our changes
Also, be sure to learn How to Setup MySQL Server in Docker for Your Python Project or check the full roadmap for Python web app developer.
Unlock the Key to Success with Cloud, Docker, Metrics, and Monitoring!
Master cloud computing, Docker, logging, Git & GitHub, metrics, and monitoring to accelerate your path to success as a Python developer.
Get job-ready skills without wasting time figuring it out on your own.
Deploy your Python applications effortlessly to the cloud, building scalable and resilient solutions.
Streamline your development workflow with Docker, eliminating compatibility issues and enabling seamless collaboration.
Optimize performance with metrics and monitoring, delivering exceptional user experiences and standing out to employers.
Don't settle for the ordinary. Stand out, impress employers, and supercharge your Python developer career. Buy this eBook now and unlock the power of the cloud, Docker, metrics, and monitoring.
Build and Deploy an AI App with Python Flask, OpenAI API, and Google Cloud: In…
Python REST APIs with gcloud Serverless In the fast-paced world of application development, building robust…
App Development with Python using Docker Are you an aspiring app developer looking to level…
Why Value-driven Data Science is the Key to Your Success In the world of data…
Harnessing the Power of Project-Based Learning and Python for Machine Learning Mastery In today's data-driven…
Is Python the right choice for Machine Learning? Should you learn Python for Machine Learning?…