Как создать Dockerfile для приложения Python
В этой статье вы узнаете, как создать файл Python Dockerfile. Мы расскажем достаточно, чтобы вы смогли начать свой собственный проект. Этот файл Dockerfile в настоящее время используется в двух моих любимых проектах. Один касается получения обложек книг из внешнего сервиса, а другой создает превью для моего блога.
Итак, мы рассмотрим Dockerfile строка за строкой и извлечем уроки из этого. Не волнуйтесь, предварительные знания вам не понадобятся. Я уверен, что к концу этой статьи вы сможете сделать это самостоятельно. В нынешней среде разработки программного обеспечения знание Docker является обязательным.
Слишком много проектов по науке о данных терпят неудачу просто из-за производственных проблем. Деловые люди часто недооценивают все, что связано с разработкой программного обеспечения. Вместо того, чтобы снова и снова доказывать концепцию, больше внимания следует уделять созданию ценного программного обеспечения. Прочитав эту статью, вы узнаете очень важную часть цикла разработки программного обеспечения. Эта статья посвящена используемому программному обеспечению.
Создать приложение
Итак, я предполагаю, что на этом этапе вы создали базовое приложение. Если вы этого не сделали, лучше всего реализовать базовый запрос GET с помощью FastAPI. Хороший пример можно найти в этом уроке. Это хорошее упражнение, так почему бы не попробовать его самому?
Поскольку наличие приложения имеет решающее значение для остальной части статьи, включен пример исходного кода основного приложения:
На этом этапе вы должны иметь возможность запустить приложение с помощью только следующей команды:
python "main.py"
С этого момента я подробно объясню каждую строку Dockerfile в следующем разделе. Если вам кажется, что вы чего-то не понимаете, не бойтесь спрашивать в комментариях ниже!
Создать Dockerfile
Первая строка файла Dockerfile, который мы собираемся создать, посвящена нашему языку. Поскольку мир все больше и больше знакомится с Python 3, неудивительно, что я выбрал одну из последних версий Python. Если вас интересуют другие доступные базовые образы Docker для Python, эта страница — ваш друг.
Две следующие строки часто игнорируются, когда люди пишут или говорят о Docker. Тем не менее, на мой взгляд, они очень важны. Следующие строки гарантируют, что все, что вы делаете внутри контейнера, выполняется обычным пользователем. Вы ведь не используете sudo для каждой команды в Linux, верно? Эти строки не позволят вам испортить внутреннюю структуру образа Docker и избежать проблем с привилегиями в дальнейшем.
Следующие две строки добавляют группу user , пользователя с именем user и домашний каталог в каталоге /home/user :
RUN useradd -ms /bin/bash user USER user
Поскольку мы ленивы, как хорошие разработчики, мы не хотим добавлять домашний каталог к каждой команде, которую собираемся выполнить. Поэтому вместо этого мы используем следующую строку в нашем Dockerfile. Это гарантирует, что все, что мы делаем, мы делаем внутри домашнего каталога:
Вне среды контейнера Docker рекомендуется работать с виртуальной средой. Я дам вам представление о том, как выглядит файл requirements.txt :
mockito~=1.2.2 requests~=2.24.0 Pillow~=7.2.0 pylint~=2.6.0 fastapi~=0.61.1 uvicorn~=0.11.8
Виртуальная среда очень полезна, когда вы работаете над несколькими проектами. Работая таким образом, вы предотвращаете переход на более раннюю или более раннюю версию пакетов, которые вы используете где-либо еще, которые могут нарушить работу вашего приложения, которое работало вчера вечером. Вы не хотите, чтобы это произошло, и руководитель вашей группы тоже не хочет этого слышать.
Итак, в этой строке мы копируем все необходимые библиотеки с вашего хост-компьютера в контейнер Docker:
С помощью этого файла мы можем установить все необходимые библиотеки для нашего приложения. После этого нам больше не понадобится этот файл в контейнере Docker, так что не будем его там хранить.
Примечание. Вы можете подумать об этом, но я не считаю полезным создавать здесь второй уровень Docker.
RUN pip install -r requirements.txt && rm requirements.txt
Хорошо, а как насчет источника? Что ж, пришло время исходников. Мы скопируем это прямо сейчас.
Мне сложно угадать, куда вы поместили свои тестовые файлы, но вы не хотите, чтобы они были в вашем контейнере Docker. Помните об этом, если хотите оптимизировать свой контейнер. Для простоты эта часть опущена.
Вторая последняя строка предназначена для документации. Поскольку мы запускаем приложение на порту 10000, мы используем инструкцию expose , чтобы прояснить это. Таким образом, мы также знаем в производственной среде, какие порты доступны.
Последняя строка касается запуска приложения. Поскольку все о том, как запустить приложение, содержится в main.py , это довольно типично для других приложений. Таким образом, нам не придется так часто открывать Dockerfile.
ENTRYPOINT [ "python", "main.py"]
Вот и все — весь Dockerfile всего в несколько строк.
Итак, давайте создадим изображение с классным тегом, чтобы мы могли поделиться им с нашими коллегами:
docker image build . -t "awesome_tag" . Successfully built 41612ca5ccfd Successfully tagged awesome_tag:latest
И теперь нам остается только раскрутить контейнер!
И это буквально все, что нужно для запуска одного из ваших приложений Python в Docker. На этом этапе вы сможете сделать это самостоятельно для любого проекта.
Заключение
В этой статье мы увидели, как создать приложение Python и запустить его в контейнере Docker. Создать Dockerfile для небольшого приложения, такого как то, которое мы создали с помощью FastAPI, очень просто, поэтому я всегда рекомендую начинать с контейнеров как можно раньше.
Используя Docker, тестирование новых версий приложения становится намного проще, так как вы можете легко настроить его практически в любой среде — с установленным Docker. Если у вас остались вопросы, задавайте их в комментариях. Я буду более чем рад ответить на все вопросы.
Packaging your software
Docker builds images by reading the instructions from a Dockerfile. This is a text file containing instructions that adhere to a specific format needed to assemble your application into a container image and for which you can find its specification reference in the Dockerfile reference.
Here are the most common types of instructions:
Dockerfiles are crucial inputs for image builds and can facilitate automated, multi-layer image builds based on your unique configurations. Dockerfiles can start simple and grow with your needs and support images that require complex instructions. For all the possible instructions, see the Dockerfile reference.
The default filename to use for a Dockerfile is Dockerfile , without a file extension. Using the default name allows you to run the docker build command without having to specify additional command flags.
Some projects may need distinct Dockerfiles for specific purposes. A common convention is to name these .Dockerfile . Such Dockerfiles can then be used through the —file (or -f shorthand) option on the docker build command. Refer to the “Specify a Dockerfile” section in the docker build reference to learn about the —file option.
Note
We recommend using the default ( Dockerfile ) for your project’s primary Dockerfile.
Docker images consist of read-only layers, each resulting from an instruction in the Dockerfile. Layers are stacked sequentially and each one is a delta representing the changes applied to the previous layer.
Example
Here’s a simple Dockerfile example to get you started with building images. We’ll take a simple “Hello World” Python Flask application, and bundle it into a Docker image that can test locally or deploy anywhere!
Let’s say we have a hello.py file with the following content:
from flask import Flask app = Flask(__name__) @app.route("/") def hello(): return "Hello World!"
Don’t worry about understanding the full example if you’re not familiar with Python, it’s just a simple web server that will contain a single page that says “Hello World”.
Note
If you test the example, make sure to copy over the indentation as well! For more information about this sample Flask application, check the Flask Quickstart page.
Here’s the Dockerfile that will be used to create an image for our application:
# syntax=docker/dockerfile:1 FROM ubuntu:22.04 # install app dependencies RUN apt-get update && apt-get install -y python3 python3-pip RUN pip install flask==2.1.* # install app COPY hello.py / # final configuration ENV FLASK_APP=hello EXPOSE 8000 CMD flask run --host 0.0.0.0 --port 8000
The first line to add to a Dockerfile is a # syntax parser directive. While optional, this directive instructs the Docker builder what syntax to use when parsing the Dockerfile, and allows older Docker versions with BuildKit enabled to use a specific Dockerfile frontend before starting the build. Parser directives must appear before any other comment, whitespace, or Dockerfile instruction in your Dockerfile, and should be the first line in Dockerfiles.
Note
We recommend using docker/dockerfile:1 , which always points to the latest release of the version 1 syntax. BuildKit automatically checks for updates of the syntax before building, making sure you are using the most current version.
Next we define the first instruction:
Here the FROM instruction sets our base image to the 22.04 release of Ubuntu. All following instructions are executed on this base image, in this case, an Ubuntu environment. The notation ubuntu:22.04 , follows the name:tag standard for naming docker images. When you build your image you use this notation to name your images and use it to specify any existing Docker image. There are many public images you can leverage in your projects. Explore Docker Hub to find out.
# install app dependencies RUN apt-get update && apt-get install -y python3 python3-pip
This RUN instruction executes a shell command in the build context.
In this example, our context is a full Ubuntu operating system, so we have access to its package manager, apt. The provided commands update our package lists and then, after that succeeds, installs python3 and pip , the package manager for Python.
Also note # install app dependencies line. This is a comment. Comments in Dockerfiles begin with the # symbol. As your Dockerfile evolves, comments can be instrumental to document how your dockerfile works for any future readers and editors of the file.
Note
Starting your Dockerfile by a # like regular comments is treated as a directive when you are using BuildKit (default), otherwise it is ignored.
This second RUN instruction requires that we’ve installed pip in the layer before. After applying the previous directive, we can use the pip command to install the flask web framework. This is the framework we’ve used to write our basic “Hello World” application from above, so to run it in Docker, we’ll need to make sure it’s installed.
Now we use the COPY instruction to copy our hello.py file from the local build context into the root directory of our image. After being executed, we’ll end up with a file called /hello.py inside the image.
This ENV instruction sets a Linux environment variable we’ll need later. This is a flask-specific variable, that configures the command later used to run our hello.py application. Without this, flask wouldn’t know where to find our application to be able to run it.
This EXPOSE instruction marks that our final image has a service listening on port 8000 . This isn’t required, but it is a good practice, as users and tools can use this to understand what your image does.
CMD flask run --host 0.0.0.0 --port 8000
Finally, CMD instruction sets the command that is run when the user starts a container based on this image. In this case we’ll start the flask development server listening on all addresses on port 8000 .
Testing
To test our Dockerfile, we’ll first build it using the docker build command:
$ docker build -t test:latest .
Here -t test:latest option specifies the name (required) and tag (optional) of the image we’re building. . specifies the build context as the current directory. In this example, this is where build expects to find the Dockerfile and the local files the Dockerfile needs to access, in this case your Python application.
So, in accordance with the build command issued and how build context works, your Dockerfile and python app need to be in the same directory.
Now run your newly built image:
$ docker run -p 8000:8000 test:latest
From your computer, open a browser and navigate to http://localhost:8000
Note
You can also build and run using Play with Docker that provides you with a temporary Docker instance in the cloud.
Other resources
If you are interested in examples in other languages, such as Go, check out our language-specific guides in the Guides section.