如何在Docker容器內運行Cron作業?
- Docker
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
構造映像。
此外,根據我們的使用情況,這兩種選擇都有其優勢。