惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

F
Fortinet All Blogs
Attack and Defense Labs
Attack and Defense Labs
V2EX - 技术
V2EX - 技术
O
OpenAI News
S
Secure Thoughts
H
Heimdal Security Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Schneier on Security
Schneier on Security
H
Hacker News: Front Page
S
Security Affairs
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Vercel News
Vercel News
Microsoft Security Blog
Microsoft Security Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
P
Proofpoint News Feed
The Register - Security
The Register - Security
GbyAI
GbyAI
Cloudbric
Cloudbric
MongoDB | Blog
MongoDB | Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
K
Kaspersky official blog
Forbes - Security
Forbes - Security
Y
Y Combinator Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
Scott Helme
Scott Helme
Hacker News - Newest:
Hacker News - Newest: "LLM"
The Cloudflare Blog
Recorded Future
Recorded Future
人人都是产品经理
人人都是产品经理
Cyberwarzone
Cyberwarzone
C
CERT Recently Published Vulnerability Notes
Webroot Blog
Webroot Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
L
LangChain Blog
T
Tor Project blog
Microsoft Azure Blog
Microsoft Azure Blog
博客园_首页
Hacker News: Ask HN
Hacker News: Ask HN
Blog — PlanetScale
Blog — PlanetScale
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
B
Blog RSS Feed
N
News and Events Feed by Topic
阮一峰的网络日志
阮一峰的网络日志
I
Intezer
V
V2EX
T
Tailwind CSS Blog
SecWiki News
SecWiki News
NISL@THU
NISL@THU
C
Check Point Blog

博客园 - Nihaorz

告别闪烁,拥抱流畅:在 Windows Terminal 中完美配置 Cygwin 环境 Nginx 透明代理 + 自动回源存储:访问即缓存,落盘即文件 创建 docker ipvlan,让 docke 容器获取独立ip 电犀牛 R68s iStoreOS 2.5G 网口速率优化 解决 openwrt ssh 命令行终端 home、end 键不可用问题 一键添加视频封面脚本 ffmpeg 转码参数 docker save 远程 ssh 主机直接 load,不产生本地文件 AutoHotKey 脚本 - win10 自动连接无线显示器 SSH 登录/退出实时监控脚本 OpenClaw 安装部署,配置 deepseek curl 断点续传下载 debian iso 镜像下载地址 linux 安装 zerotier,加入网络 基于 Fail2ban 的 SSH 入侵自动反制方案 ssh 配置密钥登录,关闭密码登录 memc - 基于 shell 的交互式清理内存脚本 基于 Fail2ban 的 OpenWRT SSH 入侵自动反制方案 Linux Screen 命令速查 linux 磁盘挂载示例
使用 ofelia 在 docker 容器中执行计划任务
Nihaorz · 2026-03-02 · via 博客园 - Nihaorz

我需要在执行某些计划任务,由于一些不可名状的原因,我不想在宿主机上写 cron,不然全天下都知道我在干什么了,那么我就脱裤子放个屁 —— 在 docker 容器内部悄咪咪的执行

具体场景是我启动了一个 nginx 的 docker 容器,我需要每2个小时执行一次授权检测,授权检测实际上就是在 nginx 容器内部执行一个检测脚本,脚本具体工作事项就不具体介绍了

原本这个事情直接在宿主虚拟机上搞定是最直接的,但是直接在宿主上跑一个计划任务那不是谁都知道了(就是防止一下甲方问东问西),那这里我们就需要用到 ofelia,让 ofelia 来帮我干这个活

摘抄一份 deepseek 查到的 ofelia 介绍

Ofelia 非常灵活,提供了四种不同的任务(Job)类型以适应不同场景:

job-exec:在 指定的、正在运行 的容器中执行命令。例如,定期在已有的 nginx 容器里执行日志清理脚本。

job-run:每次任务触发时,都会基于指定的镜像创建一个新容器来执行命令,执行完毕后销毁该容器。这对于运行一次性的、隔离性要求高的任务非常有用。

job-local:在 运行 Ofelia 本身的主机(或容器)上 直接执行命令。

job-service-run:用于 Docker Swarm 模式,在 Swarm 集群中创建一个一次性服务来执行任务。

下面上代码

docker-compose.yml

services:

  nginx:
    image: owasp/modsecurity-crs:nginx
    container_name: nginx
    hostname: nginx
    volumes:
      - ./server.conf:/etc/nginx/conf.d/server.conf
      - ./html:/usr/share/nginx/html
      - ./rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf:/etc/modsecurity.d/owasp-crs/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf:ro
    environment:
      - TZ=Asia/Shanghai
      - BLOCKING_PARANOIA=2     # 阻断模式的严格等级
      - ANOMALY_INBOUND=4       # 入站异常分数阈值,低于 9 GetCapabilities 就会被拦截
      - ANOMALY_OUTBOUND=4      # 出站异常分数阈值
    ports:
      - "80:80" # modsecurity-nginx 内部由8080端口反向代理到80端口,我们自己的配置文件以80端口启动即可
    user: root
    restart: always

  ofelia:
    image: mcuadros/ofelia:0.3
    container_name: ofelia
    hostname: ofelia
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    environment:
      - TZ=Asia/Shanghai
    user: root
    restart: always

ofelia/config.ini

[job-exec "auth_check"]

# 每秒执行
# schedule = * * * * * *

# 每两个小时执行
schedule = 0 0 */2 * * *

container = nginx
command = sh /script/auth_check.sh

# 可选参数
user = root                    # 指定执行用户
no-overlap = true              # 防止任务重叠执行

script/auth_check.sh

#!/bin/bash

export PATH=$PATH:/usr/local/bin

DEADLINE="2026-03-03 00:00:00"
LOG_FILE="/var/log/auth_check.log"

if [ $(date +%s) -gt $(date -d "$DEADLINE" +%s) ]; then
    echo "$(date '+%Y-%m-%d %H:%M:%S') - 授权已过期" >> $LOG_FILE
    touch /etc/nginx/auth_expired.lock 2>/dev/null
else
    echo "$(date '+%Y-%m-%d %H:%M:%S') - 授权正常" >> $LOG_FILE
    rm /etc/nginx/auth_expired.lock -rf 2>/dev/null
fi

三个文件准备好后执行下面的启动命令(不在启动 compose 时挂载文件,使用 docker cp 则是为了不留痕迹, docker cp 完毕后记得删除 script 和 ofelia 两个目录,深藏功与名)

docker compose up -d
docker cp script nginx:/
docker cp ofelia ofelia:/etc

# ofelia 启动后没有配置文件,拷贝配置文件进去后停止2秒等待下一次重启
sleep 2
docker logs -f ofelia

# 删除 script 和 ofelia 深藏功与名
# rm script ofelia -rf

ofelia 的容器日志应该类似下面这样

open /etc/ofelia/config.ini: no such file or directory
open /etc/ofelia/config.ini: no such file or directory
2026-03-01T19:20:00.793+08:00  scheduler.go:44 ▶ NOTICE New job registered "auth_check" - "sh /script/auth_check.sh" - "0 0 */2 * * *"
2026-03-01T19:20:00.793+08:00  scheduler.go:55 ▶ DEBUG Starting scheduler with 1 jobs

说明任务已经注册成功了,等待下一次任务执行后再查看最新日志即可

针对我的这个任务查看是否执行成功则很简单,运行下面的 docker 命令验证即可

[root@host-10-1-146-42 srv]# docker exec -it nginx cat /var/log/auth_check.log
2026-03-01 20:00:00 - 授权正常

说到底上面这个流程近似于脱裤子放屁,要更隐蔽一点就不要直接使用 ofelia,from ofelia,自己 build 一个镜像,把配置文件换一个路径,把镜像换一个名字掩盖一下

如果还嫌不够彻底,那就自己用 go 或 c++ 写一个程序,硬编码要执行的计划任务