Как запустить Python-скрипт при старте контейнера Docker

DockerBeginner
Практиковаться сейчас

Введение

Docker – это мощный инструмент для контейнеризации приложений, упрощающий разработку, развертывание и управление программным обеспечением. В этом руководстве мы рассмотрим, как запустить Python-скрипт при запуске контейнера Docker. Этот подход позволяет автоматизировать развертывание вашего приложения и оптимизировать рабочий процесс разработки. К концу этой лабораторной работы вы сможете создать контейнер Docker, который автоматически выполняет ваш Python-скрипт при запуске.

Создание простого Python-скрипта

На этом первом шаге мы создадим простой Python-скрипт, который будет выполняться при запуске нашего контейнера Docker. Этот скрипт выведет сообщение и текущую дату и время.

Начнем с создания новой директории для нашего проекта:

mkdir -p ~/project/python-docker
cd ~/project/python-docker

Теперь давайте создадим простой Python-скрипт под названием app.py с помощью текстового редактора nano:

nano app.py

В редакторе nano добавьте следующий код Python:

import datetime
import time

print("Hello from the Docker container!")
print(f"Current date and time: {datetime.datetime.now()}")

## Keep the container running to demonstrate it's working
print("Container is running...")
while True:
    print("Container still running... Press Ctrl+C to stop.")
    time.sleep(10)

Сохраните файл, нажав Ctrl+O, затем Enter, и выйдите из nano, нажав Ctrl+X.

Этот скрипт:

  1. Выведет приветственное сообщение
  2. Отобразит текущую дату и время
  3. Будет поддерживать работу контейнера с сообщением каждые 10 секунд

Давайте протестируем наш Python-скрипт, чтобы убедиться, что он работает правильно:

python3 app.py

Вы должны увидеть вывод, похожий на:

Hello from the Docker container!
Current date and time: 2023-10-12 14:30:45.123456
Container is running...
Container still running... Press Ctrl+C to stop.

Нажмите Ctrl+C, чтобы остановить скрипт.

Теперь, когда у нас есть рабочий Python-скрипт, мы можем приступить к созданию контейнера Docker, который будет запускать этот скрипт при запуске.

Создание Dockerfile

Теперь, когда наш Python-скрипт готов, давайте создадим Dockerfile, чтобы определить, как должен быть построен наш контейнер Docker.

Dockerfile – это текстовый файл, содержащий все команды, необходимые для сборки Docker-образа. Этот образ будет содержать наш Python-скрипт и все необходимые зависимости.

В той же директории (~/project/python-docker) создайте новый файл с именем Dockerfile:

nano Dockerfile

Добавьте следующее содержимое в Dockerfile:

## Use the official Python image as base
FROM python:3.9-slim

## Set working directory
WORKDIR /app

## Copy the Python script to the container
COPY app.py .

## Command to run when the container starts
CMD ["python", "app.py"]

Сохраните и выйдите из nano, нажав Ctrl+O, затем Enter, а затем Ctrl+X.

Давайте разберемся, что делает каждая строка в Dockerfile:

  1. FROM python:3.9-slim: Это указывает базовый образ для использования. Мы используем официальный образ Python 3.9 с вариантом slim, чтобы сохранить небольшой размер.

  2. WORKDIR /app: Это устанавливает рабочую директорию внутри контейнера в /app.

  3. COPY app.py .: Это копирует наш Python-скрипт с хост-машины в текущую рабочую директорию в контейнере (которая /app).

  4. CMD ["python", "app.py"]: Это указывает команду для запуска при запуске контейнера. В этом случае он запустит наш Python-скрипт.

Теперь давайте соберем наш Docker-образ, используя этот Dockerfile:

docker build -t python-app .

Эта команда собирает Docker-образ из Dockerfile в текущей директории (.) и помечает его именем python-app (-t означает tag).

Вы должны увидеть вывод, похожий на:

Sending build context to Docker daemon  3.072kB
Step 1/4 : FROM python:3.9-slim
 ---> 1bc6a8a2a52f
Step 2/4 : WORKDIR /app
 ---> Using cache
 ---> 2a3b7a28c9e5
Step 3/4 : COPY app.py .
 ---> Using cache
 ---> 9a0b7a1c8c2d
Step 4/4 : CMD ["python", "app.py"]
 ---> Using cache
 ---> 3b0c7a2d9f1e
Successfully built 3b0c7a2d9f1e
Successfully tagged python-app:latest

Вывод может отличаться, но вы должны увидеть сообщения "Successfully built" и "Successfully tagged", если все прошло хорошо.

Теперь вы успешно создали Docker-образ, который содержит ваш Python-скрипт и запустит его при запуске контейнера из этого образа.

Запуск контейнера Docker

Теперь, когда мы собрали наш Docker-образ, мы можем запустить контейнер на основе этого образа. Контейнер автоматически выполнит наш Python-скрипт при запуске.

Чтобы запустить контейнер из нашего образа, используйте следующую команду:

docker run --name python-container python-app

Эта команда запускает новый контейнер с именем python-container из образа python-app, который мы создали на предыдущем шаге.

Вы должны увидеть вывод, похожий на:

Hello from the Docker container!
Current date and time: 2023-10-12 15:45:30.123456
Container is running...
Container still running... Press Ctrl+C to stop.
Container still running... Press Ctrl+C to stop.

Контейнер сейчас работает и выполняет наш Python-скрипт. Скрипт предназначен для непрерывной работы, выводя сообщение каждые 10 секунд.

Нажмите Ctrl+C, чтобы остановить просмотр журналов, но обратите внимание, что контейнер все еще работает в фоновом режиме.

Чтобы убедиться, что контейнер работает, используйте следующую команду:

docker ps

Вы должны увидеть свой контейнер в списке запущенных контейнеров:

CONTAINER ID   IMAGE        COMMAND           CREATED         STATUS         PORTS     NAMES
1a2b3c4d5e6f   python-app   "python app.py"   1 minute ago    Up 1 minute              python-container

Чтобы остановить контейнер, используйте следующую команду:

docker stop python-container

Чтобы снова запустить контейнер, используйте:

docker start python-container

И чтобы просмотреть журналы работающего контейнера:

docker logs python-container

Это покажет вывод нашего Python-скрипта. Вы можете нажать Ctrl+C, чтобы выйти из просмотра журналов.

Чтобы удалить контейнер, когда вы закончите, сначала остановите его, если он работает, затем удалите его:

docker stop python-container
docker rm python-container

Теперь вы успешно создали и запустили контейнер Docker, который выполняет Python-скрипт при запуске.

Использование переменных окружения с Python в Docker

Переменные окружения — отличный способ настроить ваше приложение, не изменяя код. На этом шаге мы изменим наш Python-скрипт для использования переменных окружения и обновим наш Dockerfile, чтобы предоставить эти переменные.

Сначала давайте обновим наш Python-скрипт, чтобы он читал переменную окружения:

nano app.py

Измените скрипт, чтобы включить поддержку переменных окружения:

import datetime
import time
import os

## Get the environment variable with a default value if not set
user_name = os.environ.get('USER_NAME', 'Guest')

print(f"Hello, {user_name}, from the Docker container!")
print(f"Current date and time: {datetime.datetime.now()}")

## Keep the container running to demonstrate it's working
print("Container is running...")
while True:
    print("Container still running... Press Ctrl+C to stop.")
    time.sleep(10)

Сохраните и выйдите из nano, нажав Ctrl+O, затем Enter, а затем Ctrl+X.

Теперь давайте обновим наш Dockerfile, чтобы включить переменную окружения:

nano Dockerfile

Обновите Dockerfile, чтобы включить переменную окружения:

## Use the official Python image as base
FROM python:3.9-slim

## Set working directory
WORKDIR /app

## Set environment variable
ENV USER_NAME="Docker User"

## Copy the Python script to the container
COPY app.py .

## Command to run when the container starts
CMD ["python", "app.py"]

Сохраните и выйдите из nano, затем пересоберите Docker-образ:

docker build -t python-app-env .

Теперь запустите контейнер с переменной окружения по умолчанию:

docker run --name python-env-container python-app-env

Вы должны увидеть приветствие с "Docker User" в выводе:

Hello, Docker User, from the Docker container!
Current date and time: 2023-10-12 16:30:45.123456
Container is running...

Нажмите Ctrl+C, чтобы остановить просмотр журналов.

Остановите и удалите контейнер:

docker stop python-env-container
docker rm python-env-container

Вы также можете переопределить переменную окружения при запуске контейнера:

docker run --name python-env-container -e USER_NAME="LabEx Student" python-app-env

На этот раз вы должны увидеть свое пользовательское имя в приветствии:

Hello, LabEx Student, from the Docker container!
Current date and time: 2023-10-12 16:35:15.789012
Container is running...

Нажмите Ctrl+C, чтобы остановить просмотр журналов.

Остановите и удалите контейнер:

docker stop python-env-container
docker rm python-env-container

Использование переменных окружения — распространенная практика в Docker, позволяющая сделать ваши контейнеры более настраиваемыми, не перестраивая образ для небольших изменений.

Использование ENTRYPOINT против CMD в Dockerfile

В Docker есть две инструкции для указания команды, которая должна выполняться при запуске контейнера: CMD и ENTRYPOINT. Они имеют разные цели и поведение, и понимание разницы важно для управления контейнерами.

Понимание ENTRYPOINT и CMD

  • ENTRYPOINT: Определяет исполняемый файл, который будет запущен при запуске контейнера. Его сложнее переопределить во время выполнения.
  • CMD: Предоставляет аргументы по умолчанию для ENTRYPOINT или может указать всю команду, если ENTRYPOINT не используется. Его легко переопределить во время выполнения.

Давайте рассмотрим разницу, создав два разных Dockerfile.

Сначала создайте новый Python-скрипт, который принимает аргументы командной строки:

nano greeting.py

Добавьте следующий код:

import sys

print("Script started!")

if len(sys.argv) > 1:
    print(f"Arguments provided: {sys.argv[1:]}")
    for arg in sys.argv[1:]:
        print(f"- {arg}")
else:
    print("No arguments provided.")

print("Script finished!")

Сохраните и выйдите из nano.

Теперь давайте создадим Dockerfile, который использует CMD:

nano Dockerfile.cmd

Добавьте следующее содержимое:

FROM python:3.9-slim

WORKDIR /app

COPY greeting.py .

CMD ["python", "greeting.py", "default", "arguments"]

Сохраните и выйдите из nano.

Соберите образ:

docker build -t python-cmd -f Dockerfile.cmd .

Теперь создайте другой Dockerfile, который использует ENTRYPOINT:

nano Dockerfile.entrypoint

Добавьте следующее содержимое:

FROM python:3.9-slim

WORKDIR /app

COPY greeting.py .

ENTRYPOINT ["python", "greeting.py"]
CMD ["default", "arguments"]

Сохраните и выйдите из nano.

Соберите образ:

docker build -t python-entrypoint -f Dockerfile.entrypoint .

Тестирование CMD против ENTRYPOINT

Давайте запустим контейнеры из обоих образов и понаблюдаем за различиями.

Сначала запустите контейнер, используя образ CMD без дополнительных аргументов:

docker run --name cmd-container python-cmd

Вывод должен быть похожим на:

Script started!
Arguments provided: ['default', 'arguments']
- default
- arguments
Script finished!

Теперь запустите контейнер с образом CMD, но предоставьте пользовательские аргументы:

docker run --name cmd-container-custom python-cmd hello world

Вывод:

Script started!
No arguments provided.
Script finished!

Обратите внимание, что вся команда была заменена на hello world, которые не передаются в качестве аргументов нашему скрипту.

Теперь давайте запустим контейнер, используя образ ENTRYPOINT без дополнительных аргументов:

docker run --name entrypoint-container python-entrypoint

Вывод:

Script started!
Arguments provided: ['default', 'arguments']
- default
- arguments
Script finished!

Наконец, запустите контейнер с образом ENTRYPOINT и предоставьте пользовательские аргументы:

docker run --name entrypoint-container-custom python-entrypoint hello world

Вывод:

Script started!
Arguments provided: ['hello', 'world']
- hello
- world
Script finished!

На этот раз наши аргументы правильно передаются в Python-скрипт, потому что ENTRYPOINT определяет исполняемый файл, и любые дополнительные аргументы, предоставленные docker run, передаются этому исполняемому файлу.

Лучшие практики

  • Используйте ENTRYPOINT для контейнеров, которые всегда должны запускать определенную команду (например, наш Python-скрипт)
  • Используйте CMD для предоставления аргументов по умолчанию, которые можно легко переопределить
  • Объедините оба, используя ENTRYPOINT для команды и CMD для аргументов по умолчанию

Очистите контейнеры:

docker rm cmd-container cmd-container-custom entrypoint-container entrypoint-container-custom

Теперь вы узнали разницу между CMD и ENTRYPOINT в Docker, что необходимо для управления тем, как ваши Python-скрипты запускаются при запуске контейнера.

Резюме

В этой лабораторной работе вы узнали, как запускать Python-скрипты при запуске контейнера Docker. Вот чего вы достигли:

  1. Создали простой Python-скрипт, который запускается в контейнере Docker
  2. Построили Docker-образ с помощью Dockerfile
  3. Запустили контейнер Docker, который автоматически выполняет Python-скрипт
  4. Использовали переменные окружения для настройки вашего Python-приложения в Docker
  5. Поняли разницу между CMD и ENTRYPOINT в Dockerfiles

Эти навыки являются основополагающими для контейнеризации Python-приложений и автоматизации их развертывания. Теперь вы можете:

  • Упаковывать ваши Python-приложения со всеми их зависимостями
  • Настраивать ваши приложения с помощью переменных окружения
  • Контролировать, как ваши приложения запускаются внутри контейнеров Docker
  • Выбирать подходящий механизм запуска (CMD или ENTRYPOINT) для вашего конкретного случая использования

Обладая этими знаниями, вы можете создавать более сложные приложения Docker, которые автоматически запускают Python-скрипты при запуске, делая процесс развертывания более эффективным и надежным.