Docker 容器 ubuntu 镜像 cron 服务未运行

问题描述 投票:0回答:1

有以下 Dockerfile

FROM ubuntu:20.04
FROM postgres:17.0

##### packages needed that dont come with the image of ubuntu:20.04
RUN apt-get update \
&& apt-get install -y bash \
&& apt-get install -y cron \
&& apt-get install nano
#&& apt-get install -y iputils-ping
#RUN sudo apt install postgresql

COPY backup.sh /usr/local/bin/
COPY setup.sh /usr/local/bin/ 
WORKDIR /usr/local/bin/
RUN chmod +x backup.sh
RUN chmod +x setup.sh
RUN ./setup.sh

# Add the cron job to the crontab
RUN crontab -l | { cat; echo "* * * * * /usr/local/bin/backup.sh 10 'localhost' '5432' 'postgres' 'xxxxx' 'dvdrental' >> /mnt/backups/backup.log 2>&1"; } | crontab -

CMD ["/bin/bash","cron"]

构建容器的命令

sudo docker build --no-cache -t hcorte/backup_container .

运行容器的命令

sudo docker run --name ubuntu -v /mnt/backups/:/mnt/backups/ --add-host host.docker.internal:host-gateway -itd hcorte/backup_container bash

当附加到容器并运行命令时

service cron status
返回

cron 未运行...失败!

但是

CMD ["/bin/bash","cron"]
不是表示启动cron服务吗? 需要在 Dockerfile 中进行哪些更改才能使 cron 服务一开始就启动?

docker cron dockerfile
1个回答
0
投票

TL;DR:将 Dockerfile 的最后一行更改为

CMD ["cron", "-f"]
,并且不要将
bash
放在
docker run
命令的末尾。


一个容器只运行一个进程。 您无法在 Dockerfile 中启动后台服务,并且总的来说像

service
这样的命令不起作用。

在您的

docker run
命令中,您有

docker run ... -itd hcorte/backup_container \
  bash

镜像名称后面的任何内容都会作为运行命令,并替换 Dockerfile

CMD
。 由于容器只运行一个进程,因此 shell 运行而不是您尝试运行的 cron 守护进程,这就是为什么当您在容器内获得调试 shell 时,您找不到 cron 守护进程。

在 Dockerfile

CMD
行中,您通常不需要提及
bash
或其他 shell。 带方括号的语法(JSON 数组)完全运行指定的命令,没有额外的引用或转义;或者你可以只写一个命令,它会隐式地通过
/bin/sh -c
(或当前的
SHELL
)传递。

在您的情况下,您希望主容器进程是 cron 守护进程;容器中不会运行任何其他内容。 这只是一个简单的命令,不需要任何类型的变量扩展,因此 exec 形式(JSON 数组语法)可以正常工作。 对于 Debian cron

-f
选项使其在前台运行(至少还有一个具有不同选项的其他 cron 实现)。

如果您对容器执行

docker exec
操作,
service
仍然不会显示 cron 守护进程正在运行。 不过,如果您已经安装了
ps
,那么它的进程 ID 将为 1。


您还应该考虑在 Dockerfile 中清理更多内容。

一张图像只有一个父图像。 有两条

FROM
线可创建多阶段构建;它不会导致
ubuntu
postgres
图像被组合。 我会删除第一行
FROM

除了 cron 守护进程之外,不需要使用 APT 安装的工具。 基于 Debian 的镜像已经包含 GNU bash(并且您不使用它的任何功能);您通常不需要使用

nano
编辑容器内的文件,或使用
ping
发送原始 ICMP 数据包。

如果文件被检入源代码管理并设置了可执行位,则不需要

RUN chmod +x
它们。 您可以一次性将多个文件
COPY
放入一个目录中。 由于
/usr/local/bin
是默认的
$PATH
,因此您无需更改
WORKDIR
或使用路径来运行脚本。

将这些更改放在一起,您将获得最终的 Dockerfile

FROM postgres:17.0

RUN apt-get update \
 && DEBIAN_FRONTEND=noninteractive apt-get install -y cron

COPY backup.sh setup.sh /usr/local/bin/
RUN setup.sh

RUN crontab -l | { cat; echo "* * * * * /usr/local/bin/backup.sh 10 'localhost' '5432' 'postgres' 'xxxxx' 'dvdrental' >> /mnt/backups/backup.log 2>&1"; } | crontab -

CMD ["cron", "-l"]
© www.soinside.com 2019 - 2024. All rights reserved.