1. 概要

システム管理者として、私たちは常にタスクをスケジュールする必要に直面します。 これは、Linuxシステムでcronサービスを使用することで実現できます。 また、コンテナシステムでcronスケジューリングサービスを有効にすることもできます。

ここで、このチュートリアルでは、Dockerコンテナでcronサービスを有効にする2つの異なる方法を説明します。 最初のアプローチでは、Dockerfileを使用して cron サービスをDockerイメージ内に埋め込みますが、他の方法では、コンテナーにスケジューリングサービスをインストールする方法を示します。

2. cronサービス– Dockerfileアプローチの使用

Dockerfile を使用してイメージを構築することは、コンテナーイメージを作成する最も簡単な方法の1つです。 では、どうすればよいのでしょうか。 基本的に、 Dockerfile は、イメージを作成するための一連の手順を含む単純なテキストファイルです。 スケジューリングタスクcronの詳細をフィードし、Dockerfileからcronサービスを呼び出す必要があります。

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サービスをイメージにインストールします。 また、crontabcronスケジューリングを実行します。

最後に、CMD命令を使用してcronサービスを開始します。

$ cat Dockerfile

# Dockerfile to create image with cron services
FROM ubuntu:latest
MAINTAINER baeldung.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 の準備ができたら、 dockerbuildコマンドを使用してイメージをビルドできます。 The dot(。)は、現在のパスからDockerfileを取得するようにDockerエンジンに指示します。 buildコマンドは、Dockerfileで指定されたすべての命令に対してdockerレイヤーを作成し、最終的なビルドイメージを形成します 。 典型的なビルド出力を以下に示します。

$ docker build .
Sending build context to Docker daemon  3.072kB
Step 1/8 : FROM ubuntu:latest
---> ba6acccedd29
Step 2/8 : MAINTAINER baeldung.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ジョブが自動的にアクティブ化されます。 または、 dockerrunコマンドを使用してコンテナーを起動することもできます。 続いて、 dockerrunの「-it」オプションは、bashプロンプトでコンテナーに入るのに役立ちます。

次の図は、cronを使用したコンテナでのget_date.shスクリプトの実行を示しています。

$ 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サービスを設定することもできます。 それで、手口は何ですか?

docker run コマンドを使用して、ubuntuコンテナーをすばやく実行してみましょう。 通常、コンテナは軽量のOSであり、デフォルトのパッケージとしてcronサービスは含まれていません。

したがって、コンテナのインタラクティブシェルに入り、aptリポジトリコマンドを使用してcronサービスをインストールする必要があります。

$ 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 は、viエディターを使用してcronジョブを編集します。 以下のcron構成は、スクリプトを1分ごとに実行します。 さらに、出力はスクリプト実行のタイムスタンプを示します。

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. 結論

要約すると、Dockerコンテナー内でcronジョブを実行するための要点を探りました。 Dockerfileを使用するメソッドは、cronサービスとタスクをイメージに埋め込み、cronスケジュール構成に従ってスクリプトを自動的に実行します。

cronは実行中のコンテナーにインストールして構成できますが、docker commit を使用してイメージを構築しない限り、これはランタイム構築にすぎません。

その上、両方の選択肢には、使用状況に応じて利点があります。