Перейти к основному содержимому

Как запустить Cron задание внутри Docker контейнера?

· 6 мин. чтения

1. Обзор

Как системные администраторы, мы неизменно сталкиваемся с необходимостью планирования задач. Мы можем добиться этого, используя службы cron в системах Linux. Кроме того, мы можем включить службы планирования cron в контейнерных системах.

Теперь в этом руководстве будут рассмотрены два разных способа включения служб cron в контейнерах Docker. В первом подходе мы встроим службы cron в образ Docker с помощью Dockerfile, тогда как в другом методе будет показано, как установить службы планирования в контейнере.

2. Службы Cron — использование подхода Dockerfile

Создание образов с помощью Dockerfile — один из самых простых способов создания образов контейнеров. Итак, как мы это делаем? По сути, Dockerfile — это простой текстовый файл, содержащий набор инструкций по созданию образа. Нам нужно передать задачу планирования, детали cron и вызвать службы cron из Dockerfile .

2.1. Написание Dockerfile

Давайте быстро рассмотрим пример:

$ tree
.
├── Dockerfile
└── get_date.sh
0 directories, 2 files

Как правило, первая строка Dockerfile начинается с команды FROM , которая берет запрошенный образ из настроенного реестра. В нашем случае реестр по умолчанию настроен как DockerHub . Затем идет MAINTAINER , который является метаданными для сбора информации об авторе. Инструкция ADD копирует сценарий get_date.sh из пути сборки образа хост-компьютера в путь назначения образа.

После копирования сценария в образ сборки инструкция RUN дает права на выполнение. Более того, инструкция RUN помогает выполнить любую команду оболочки в качестве нового слоя изображения поверх текущего слоя и фиксирует результаты. RUN обновляет репозиторий apt и устанавливает в образ последние службы cron . Он также выполняет планирование cron в crontab .

Наконец, мы запустим службы cron с помощью инструкции CMD :

$ cat Dockerfile

# Dockerfile to create image with cron services
FROM ubuntu:latest
MAINTAINER foreach.com

# Add the script to the Docker Image
ADD get_date.sh /root/get_date.sh

# Give execution rights on the cron scripts
RUN chmod 0644 /root/get_date.sh

#Install Cron
RUN apt-get update
RUN apt-get -y install cron

# Add the cron job
RUN crontab -l | { cat; echo "* * * * * bash /root/get_date.sh"; } | crontab -

# Run the command on container startup
CMD cron

2.2. Сборка и запуск образа Cron

Как только Dockerfile будет готов, мы можем собрать образ с помощью команды docker build . Точка (.) указывает Docker Engine взять Dockerfile из текущего пути. Команда сборки создает слои Docker для каждой инструкции, заданной в Dockerfile , для формирования окончательного образа сборки . Типичный результат сборки показан ниже:

$ docker build .
Sending build context to Docker daemon 3.072kB
Step 1/8 : FROM ubuntu:latest
---> ba6acccedd29
Step 2/8 : MAINTAINER foreach.com
---> Using cache
---> e6b3946b2382
Step 3/8 : ADD get_date.sh /root/get_date.sh
---> 4976f058d428
Step 4/8 : RUN chmod 0644 /root/get_date.sh
---> Running in 423a4e9adbab
Removing intermediate container 423a4e9adbab
---> 76d972a082ba
Step 5/8 : RUN apt-get update
---> Running in badc0d84f6ff
Get:1 http://security.ubuntu.com/ubuntu focal-security InRelease [114 kB]
...
... output truncated ...
...
Removing intermediate container badc0d84f6ff
---> edb8a19b891c
Step 6/8 : RUN apt-get -y install cron
---> Running in efd9b8a67d98
Reading package lists...
Building dependency tree...
...
... output truncated ...
...
Done.
invoke-rc.d: could not determine current runlevel
invoke-rc.d: policy-rc.d denied execution of start.
Removing intermediate container efd9b8a67d98
---> 2b80000d32a1
Step 7/8 : RUN crontab -l | { cat; echo "* * * * * bash /root/get_date.sh"; } | crontab -
---> Running in 1bdd3e0cc877
no crontab for root
Removing intermediate container 1bdd3e0cc877
---> aa7c82aa7c11
Step 8/8 : CMD cron
---> Running in cf2d44873b36
Removing intermediate container cf2d44873b36
---> 8cee091ca87d
Successfully built 8cee091ca87d

Поскольку мы предварительно установили службы cron в образ и внедрили задачи в crontab , задание cron автоматически активируется при запуске контейнера. В качестве альтернативы мы можем запустить контейнер с помощью команды запуска docker . Впоследствии опция « -it » запуска docker помогает попасть в контейнер с приглашением bash.

На приведенном ниже рисунке показано выполнение скрипта get_date.sh в контейнере с использованием cron :

$ docker run -it 8cee091ca87d /bin/bash
root@88f5bb1f0a08:/#
root@88f5bb1f0a08:/# date
Mon Nov 15 14:30:21 UTC 2021

root@88f5bb1f0a08:/# ls -ltrh ~/date.out
ls: cannot access '/root/date.out': No such file or directory

root@88f5bb1f0a08:/# ls -ltrh /root/get_date.sh
-rw-r--r-- 1 root root 18 Nov 15 14:20 /root/get_date.sh

root@88f5bb1f0a08:/# crontab -l
* * * * * bash /root/get_date.sh

root@88f5bb1f0a08:/# ls -ltrh ~/date.out
-rw-r--r-- 1 root root 29 Nov 15 14:31 /root/date.out

root@88f5bb1f0a08:/# cat /root/date.out
Mon Nov 15 14:31:01 UTC 2021

3. Службы Cron — подход к работе с контейнерами

Кроме того, мы можем настроить службы cron в контейнерах Docker для запуска заданий cron . Итак, каков порядок действий?

Давайте быстро запустим контейнер ubuntu с помощью команды запуска docker . Обычно контейнеры представляют собой облегченную ОС, которая не включает службы cron в качестве пакета по умолчанию.

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

$ docker run -it ubuntu:latest /bin/bash
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
7b1a6ab2e44d: Pull complete
Digest: sha256:626ffe58f6e7566e00254b638eb7e0f3b11d4da9675088f4781a50ae288f3322
Status: Downloaded newer image for ubuntu:latest
root@77483fc20fc9:/#
root@77483fc20fc9:/# which cron
root@77483fc20fc9:/# apt update -y
Get:1 http://archive.ubuntu.com/ubuntu focal InRelease [265 kB]
...
... output truncated ...
...
All packages are up to date.
root@77483fc20fc9:/# apt upgrade -y
...
... output truncated ...
...
root@77483fc20fc9:/# apt install cron vim -y
Reading package lists... Done
...
... output truncated ...
...
Done.
invoke-rc.d: could not determine current runlevel
invoke-rc.d: policy-rc.d denied execution of start.
root@77483fc20fc9:/# which cron
/usr/sbin/cron

$ docker cp get_data.sh 77483fc20fc9: /root/get_date.sh

Мы можем использовать команду docker cp , чтобы скопировать get_date.sh с хоста в контейнер. crontab -e редактирует задание cron с помощью редактора vi . Приведенная ниже конфигурация cron запускает скрипт каждую минуту. Кроме того, в выводе указывается временная метка выполнения скрипта:

root@77483fc20fc9:/# export EDITOR=vi
root@77483fc20fc9:/# crontab -e
* * * * * bash /root/get_date.sh

root@77483fc20fc9:/# date
Mon Nov 17 11:15:21 UTC 2021

root@77483fc20fc9:/# ls -ltrh ~/date.out
ls: cannot access '/root/date.out': No such file or directory

root@77483fc20fc9:/# ls -ltrh /root/get_date.sh
-rw-r--r-- 1 root root 18 Nov 17 11:09 /root/get_date.sh

root@77483fc20fc9:/# ls -ltrh ~/date.out
-rw-r--r-- 1 root root 29 Nov 17 11:16 /root/date.out

root@77483fc20fc9:/# cat /root/date.out
Mon Nov 17 11:16:01 UTC 2021

4. Вывод

Подводя итог, мы изучили основы запуска заданий cron внутри контейнера Docker. Метод использования Dockerfile встраивает в образ cron - сервисы и задачи , которые автоматически выполняют скрипт в соответствии с конфигурацией cron -расписания.

Хотя cron можно установить и настроить в работающем контейнере, это всего лишь конструкция времени выполнения, если только мы не создадим образ с помощью docker commit .

Кроме того, оба варианта имеют свои преимущества в зависимости от наших условий использования.