如何在 Docker 容器内运行 cron 定时任务?

容器内跑 cron:Dockerfile 装 cron、COPY crontab 文件、入口脚本用 cron -f 前台运行;注意 cron 不继承容器环境变量。K8s 场景推荐改用 CronJob。本文给出完整 Dockerfile 示例。

最佳实践
如何在 Docker 容器内运行 cron 定时任务?封面

基本步骤:镜像里装 cron → COPY crontab 文件到 /etc/cron.d/ → 入口脚本里 cron 启动守护进程(注意环境变量问题:cron 不继承 docker run -e 传入的变量,需导出到 /etc/environment)。不过容器里跑 cron 是妥协方案,K8s 环境优先用 CronJob,单机也可用宿主机 cron 调 docker exec。

完整 Dockerfile 示例

FROM python:3.12-slim

RUN apt-get update && apt-get install -y cron && rm -rf /var/lib/apt/lists/*

WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .

# 拷贝定时任务定义
COPY crontab /etc/cron.d/app-cron
RUN chmod 0644 /etc/cron.d/app-cron && crontab /etc/cron.d/app-cron

COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
CMD ["/entrypoint.sh"]

crontab 文件:

*/10 * * * * . /etc/environment; python /app/jobs/cleanup.py >> /proc/1/fd/1 2>&1

entrypoint.sh:

#!/bin/bash
set -e
printenv > /etc/environment   # 把容器环境变量导出给 cron 用
cron                          # 启动 cron 守护进程
exec python app.py            # 主进程前台运行

三个必踩的坑

  1. 环境变量:cron 不继承容器环境,printenv > /etc/environment + 任务里 source 是标准解法
  2. 任务输出:cron 任务默认输出无处可看,重定向到 /proc/1/fd/1(主进程 stdout),这样 docker logs 和日志采集能拿到
  3. 双进程:cron + 应用 = 一个容器俩进程,违背了单进程原则,supervisor 类问题(挂了谁拉谁)要自己想清楚

任务输出应带上任务名、执行时间和最终结果,并确认在容器日志中可见。用 DataKit接入观测云后,可按实际调度周期配置日志检测及无数据通知,窗口中留出执行与采集延迟。收到无成功记录的通知时,再区分任务未启动、执行失败和采集链路中断。

更推荐的替代方案

方案 适用
K8s CronJob K8s 环境首选,任务独立 Pod,环境变量天然注入
宿主机 cron + docker exec 单机少量任务,容器保持单进程
应用内调度器 APScheduler / node-cron,与应用同进程

常见问题(FAQ)

Q:cron 容器时区不对?
A:镜像默认 UTC,挂载 -v /etc/localtime:/etc/localtime:ro 或镜像里设置 TZ 环境变量并装 tzdata。

Q:任务没执行怎么查?
A:进容器 grep CRON /var/log/syslog(需 rsyslog)或直接看重定向到 stdout 的输出;先手动跑一遍命令确认命令本身没问题。

Q:Alpine 镜像怎么装 cron?
A:Alpine 自带 crond(busybox),crond -f 前台启动即可,crontab 文件放 /etc/crontabs/root。

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台