具有以下 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
,你有镜像名称后面的任何内容都被视为要运行的命令,并替换 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
,或使用 发送原始 ICMP 数据包ping
。如果文件在源代码管理中被检查并设置了可执行位,则您不需要
RUN chmod +x
它们。您可以COPY
一次性将多个文件放入一个目录中。由于/usr/local/bin
是默认的$PATH
,您不需要更改WORKDIR
或使用路径来运行脚本。将这些更改放在一起,你将得到最终的 Dockerfile