有以下 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 服务一开始就启动?
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"]