Adding dependencies
We’re going to run Python via Docker and a configuration file. That way, any developer can replicate our code regardless of whether they have Python installed on their machine and they will be able to run the associated services with just one command.
First, we will create a Python file called hello.py
with the following content:
print(“Wow, I have run in a Docker container!”)
The code is ready. We can continue.
The goal will be to configure Docker to run the file. Sounds easy, doesn’t it? Here we go!
We’ll create a file called Dockerfile
with the following code:
# Image
FROM python:3.10
# Display the Python output through the terminal
ENV PYTHONUNBUFFERED: 1
# Set work directory
WORKDIR /usr/src/app
# Add Python dependencies
## Update pip
RUN pip install --upgrade pip
## Copy requirements
COPY requirements.txt ./requirements.txt
## Install requirements
RUN pip3 install -r requirements.txt
This file is used to create a Docker image, or template, with instructions that will be cached. Since they are precached, their launch will be almost instantaneous. Let’s check out what’s going on in the code:
- With
FROM python:3.10
, we are using another existing image as a base. We are extending the work already done. But... where is it? Docker has a repository full of images, or templates, called Docker Hub (https://hub.docker.com/), a place where developers selflessly upload their work. There is an official image calledpython
and we mark it with a tag to use version 3.10. If you have worked with Docker before, you might be wondering why we are not using the Alpine version, the famous operating system that saves so much space in servers around the world. For two reasons: Python is slower (https://pythonspeed.com/articles/alpine-docker-python/) and it doesn’t have the ability to compile dependencies. The Slim version also exacerbates the last problem and is recommended only for production versions that are short of space. ENV PYTHONUNBUFFERED: 1
shows us the Python messages, for example, when we useprint()
. If it was not added, they would go directly to the Docker log.- By adding
WORKDIR /usr/src/app
, we define the path in which the commands will be executed inside the Docker container, not inside our operating system. This is equivalent to changing the directory withcd
. - We will also take the opportunity to install the Python dependencies that we will be adding in the future inside
requirements.txt
. We update pip withRUN pip install --upgrade pip
, copy the list of dependencies from the folder to the image withCOPY requirements.txt ./requirements. Txt
, and finally, run pip to install everything withRUN pip3 install -r requirements.txt
. - At the root of the project, we create another file called
docker-compose.yaml
with the following content:version: '3.8' services: python: build: context: ./ dockerfile: ./Dockerfile entrypoint: python3 hello.py volumes: - .:/usr/src/app/
This is the orchestrator, a file where we define each service and its configurations. In this case, we are only going to have a service called python
. With build
, we tell Docker to use the image that we just defined in the Dockerfile
. With entrypoint
, we indicate what it should do when the service is launched: python3 hello.py
. Finally, in volumes
, we tell it to mount the root directory, represented by a single dot, with /usr/src/app/
, which is an internal directory of the image. This way, the service will have access to all the files in the folder.
- Next, we create an empty file called
requirements.txt
. We will not add a single line, though the file must be present.
We’re ready to go! Open the terminal, go to the working folder, and tell docker-compose
to pull up the services:
cd [your folder] docker-compose up
Docker will gradually perform several tasks: it will download the base python
image, build its own image by executing the instructions we have defined, and raise the python
service. It will print 2 lines per console, as in the following:
python_1 | Wow, I have run in a Docker container! python_1 exited with code 0
We’ve executed the Python file! Victory!
With the recent ability to run Python using Docker, it’s time to integrate it into an IDE to make it easier to run without using the terminal.