如何在Docker容器內運行Cron作業?

1. 概述

作為系統管理員,我們總會遇到調度任務的需要。我們可以通過在 Linux 系統中cron服務來實現這一點。此外,我們可以在容器系統中cron

現在,本教程將闡明在 Docker 容器cron在第一種方法中,我們將cron服務嵌入到 docker 鏡像中,而另一種方法將說明如何在容器中安裝調度服務。

2. Cron 服務——使用Dockerfile方法

Dockerfile構建鏡像是創建容器鏡像最簡單的方法之一。那麼,我們該怎麼做呢?基本上, 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指令有助於將任何 shell 命令作為當前層之上的新圖像層執行並提交結果。 RUN更新apt存儲庫並在映像中cron它還在crontab cron調度。

最後,我們將使用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準備就緒,我們就可以使用docker build命令構建鏡像。點 (.) 指示 Docker 引擎從當前路徑Dockerfile 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或者,我們可以使用docker run命令啟動容器。隨後, docker run -it ”選項有助於通過 bash 提示符進入容器。

下圖顯示了cron在容器中get_date.sh腳本:

$ docker run -it 8cee091ca87d /bin/bash
 [email protected]:/#
 [email protected]:/# date
 Mon Nov 15 14:30:21 UTC 2021

 [email protected]:/# ls -ltrh ~/date.out
 ls: cannot access '/root/date.out': No such file or directory

 [email protected]:/# ls -ltrh /root/get_date.sh
 -rw-r--r-- 1 root root 18 Nov 15 14:20 /root/get_date.sh

 [email protected]:/# crontab -l
 * * * * * bash /root/get_date.sh

 [email protected]:/# ls -ltrh ~/date.out
 -rw-r--r-- 1 root root 29 Nov 15 14:31 /root/date.out

 [email protected]:/# cat /root/date.out
 Mon Nov 15 14:31:01 UTC 2021

3. Cron 服務——實時容器方法

或者,我們可以在 Docker 容器中cron cron作業。那麼,作案手法是什麼?

讓我們使用docker run命令快速運行一個ubuntu通常,容器是輕量級操作系統,不會包含cron服務作為其默認包。

因此,我們需要**進入容器的交互式 shell 並使用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:/#
 root:/# which cron
 root:/# apt update -y
 Get:1 http://archive.ubuntu.com/ubuntu focal InRelease [265 kB]
 ...
 ... output truncated ...
 ...
 All packages are up to date.
 root:/# apt upgrade -y
 ...
 ... output truncated ...
 ...
 root:/# 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.
 [email protected]:/# which cron
 /usr/sbin/cron

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

我們可以使用get_date.sh docker cp命令將 get_date.sh 從主機複製到容器中。 crontab -e使用vi編輯器編輯cron下面的cron配置每分鐘運行一次腳本。此外,輸出指示腳本執行的時間戳:

root:/# export EDITOR=vi
 [email protected]:/# crontab -e
 * * * * * bash /root/get_date.sh

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

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

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

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

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

4 結論

總而言之,我們已經探索了cron作業的具體細節。使用Dockerfile的方法是將cron服務和任務cron調度配置自動執行腳本。

儘管cron可以在正在運行的容器中安裝和配置,但它只是一個運行時構造,除非我們使用docker commit構造映像。

此外,根據我們的使用情況,這兩種選擇都有其優勢。