如何在 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 类问题(挂了谁拉谁)要自己想清楚

更推荐的替代方案

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

观测云对照

定时任务必须可监控。 任务输出经 stdout 被 DataKit 采集后,用监控器配置"预期时间窗口内无成功日志即告警",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

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

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

立即开始

选择观测云版本

代码托管平台