cron容器部署
#说明:
#不能使用cron,不适合在容器运行,包括权限等。
#使用supercronic,版本v0.2.33
#supercronic 官网 https://github.com/aptible/supercronic
#第一次执行
sudo -i
#准备工作copy supercronic 到Dockerfile同级目录
#设置权限
#chown root:root ./supercronic
#第二次执行
#crontab_filename
crontab_filename="crontab"
script_hello_world_filename="hello_world.sh"
#host
#/docker-data/dockerfiles/cron 存放Dockerfile文件
host_dockerfiles_path="/docker-data/dockerfiles/cron"
host_dockerfile_filename=${host_dockerfiles_path}/Dockerfile
host_dockerfiles_path_scripts_path=${host_dockerfiles_path}/scripts
host_dockerfiles_etc_conf_d_path=${host_dockerfiles_path}/etc/cron.d
host_dockerfiles_etc_conf_d_crontab_filename=${host_dockerfiles_path}/etc/cron.d/${crontab_filename}
host_relative_dockerfiles_etc_conf_d_crontab_filename=/etc/cron.d/${crontab_filename}
#/docker-data/cron 存放容器挂载目录
host_data_cron_path="/docker-data/cron"
host_crontab_filename=${host_data_cron_path}/${crontab_filename}
host_scripts_path=${host_data_cron_path}/scripts
host_script_filename=${host_scripts_path}/${script_filename}
host_log_path=${host_data_cron_path}/log
host_script_hello_world_log_filename=${host_log_path}/hello-world.log
#映像
#映像名称
image_name="supercronic:alpine"
#crontab_path
image_cron_d_path=/etc/cron.d
#crontab_filename
image_cron_d_crontab_filename=${image_cron_d_path}/${crontab_filename}
#scripts_path
image_scripts_path="/scripts"
#log_path
image_log_path=/var/log
#hello-world.log
image_hello_world_log_filename=${image_log_path}/hello-world.log
#container
#容器名称
docker_container_name="supercronic"
#创建目录
#host
if [ ! -d ${host_dockerfiles_path} ]; then
mkdir -p ${host_dockerfiles_path}
fi
if [ ! -d ${host_dockerfiles_path_scripts_path} ]; then
mkdir -p ${host_dockerfiles_path_scripts_path}
fi
if [ ! -d ${host_dockerfiles_etc_conf_d_path} ]; then
mkdir -p ${host_dockerfiles_etc_conf_d_path}
fi
if [ ! -d ${host_log_path} ]; then
mkdir -p ${host_log_path}
fi
if [ ! -d ${host_scripts_path} ]; then
mkdir -p ${host_scripts_path}
fi
#crontabl
echo "* * * * * echo hello-world >> ${image_hello_world_log_filename} " > \
${host_dockerfiles_etc_conf_d_crontab_filename}
chmod 644 ${host_dockerfiles_etc_conf_d_crontab_filename}
cp ${host_dockerfiles_etc_conf_d_crontab_filename} ${host_crontab_filename}
#第三次执行
#创建Dockerfile文件
cat > ${host_dockerfile_filename} << eof
# 使用 Alpine 作为基础镜像
FROM alpine:latest
# 安装必要的包,及supercronic
# curl openssl ca-certificates jq 是acmesh需要的
#tzdata 时区相关包
RUN apk add --no-cache curl bash openssl ca-certificates jq tzdata
RUN rm -rf /var/cache/apk/*
#设置时区
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo "Asia/Shanghai" > /etc/timezone
ENV TZ=Asia/Shanghai
#RUN curl -Lo /usr/local/bin/supercronic https://github.com/aptible/supercronic/releases/latest/download/supercronic-linux-amd64
COPY ./supercronic /usr/local/bin/supercronic
RUN chmod +x /usr/local/bin/supercronic
# 创建一个目录用于存放脚本和配置文件
RUN mkdir -p ${image_cron_d_path} ${image_scripts_path}
# 将定时任务配置文件和脚本复制到容器中
COPY ./etc/cron.d/crontab ${image_cron_d_crontab_filename}
#COPY my_script.sh /scripts/my_script.sh
# 设置执行权限
#RUN chmod +x /scripts/my_script.sh
RUN chmod 0644 ${image_cron_d_crontab_filename}
#acme需要的配置
#创建网站ssl相关目录
#RUN mkdir -p /nginx/config/conf.d/ssl
#RUN mkdir -p /nginx/html/ssl
#创建docker映射目录
#RUN mkdir -p /var/run
# 启动 Supercronic 并读取 cron 配置文件
CMD ["/usr/local/bin/supercronic", "${image_cron_d_crontab_filename}"]
eof
#第四次执行
#生成映像,最后一个参数是设置命令执行的当前目录
docker build -t ${image_name} -f ${host_dockerfile_filename} ${host_dockerfiles_path}
#第五次执行
#运行容器
#里面包含了:acme 需要的增加nginx的映射目录 和 docker的映射
docker run -d \
-v ${host_crontab_filename}:${image_cron_d_crontab_filename} \
-v ${host_scripts_path}:${image_scripts_path} \
-v ${host_log_path}:${image_log_path} \
-v /docker-data/nginx/config/conf.d/ssl:/nginx/config/conf.d/ssl \
-v /docker-data/nginx/html/ssl:/nginx/html/ssl \
-v /var/run/docker.sock:/var/run/docker.sock \
--name ${docker_container_name} \
--restart always \
${image_name}
#测试
#查看是否每分钟会多出一个 hello-world 的内容
cat $host_script_hello_world_log_filename
#使用
#修改配置文件,可以注释掉不用的hello-world样例
vim $host_dockerfiles_etc_conf_d_crontab_filename
#重启容器
docker restart $docker_container_name
#查看日志
docker logs $docker_container_name
tree /docker-data/docker-composes/cron/
/docker-data/docker-composes/cron/
├── Dockerfile #见下文
├── etc
│ └── cron.d
│ └── crontab #见下文
├── scripts
└── supercronic #通过scp拷贝到服务器
└── docker-compose.yaml #见下文
tree /docker-data/cron
/docker-data/cron
├── crontab #见下文
├── log
│ └── hello-world.log #空文件即可
└── scripts
#/docker-data/dockerfiles/cron/etc/cron.d/crontab
* * * * * echo hello-world >> /var/log/hello-world.log
#/docker-data/dockerfiles/cron/Dockerfile
# 使用 Alpine 作为基础镜像
FROM alpine:latest
# 安装必要的包,及supercronic
# curl openssl ca-certificates jq 是acmesh需要的
#tzdata 时区相关包
RUN apk add --no-cache curl bash openssl ca-certificates jq tzdata
RUN rm -rf /var/cache/apk/*
#设置时区
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo "Asia/Shanghai" > /etc/timezone
ENV TZ=Asia/Shanghai
#RUN curl -Lo /usr/local/bin/supercronic https://github.com/aptible/supercronic/releases/latest/download/supercronic-linux-amd64
#github.com不好访问,把文件下载下来,直接COPY
COPY ./supercronic /usr/local/bin/supercronic
RUN chmod +x /usr/local/bin/supercronic
# 创建一个目录用于存放脚本和配置文件
RUN mkdir -p /etc/cron.d /scripts
# 将定时任务配置文件和脚本复制到容器中
COPY ./etc/cron.d/crontab /etc/cron.d/crontab
# 设置执行权限
#RUN chmod +x /scripts/my_script.sh
RUN chmod 0644 /etc/cron.d/crontab
#acme需要的配置
#创建网站ssl相关目录
RUN mkdir -p /nginx/config/conf.d/ssl
RUN mkdir -p /nginx/html/ssl
#创建docker映射目录
RUN mkdir -p /var/run
# 启动 Supercronic 并读取 cron 配置文件
CMD ["/usr/local/bin/supercronic", "/etc/cron.d/crontab"]
#/docker-data/docker-compose/cron/docker-compose.yaml
services:
supercronic:
build: .
image: supercronic:alpine # 镜像版本,此jdk版本长期稳定,没有版权问题
container_name: supercronic # 容器名,相当于docker run命令中的--name
restart: unless-stopped # 之前是什么状态,docker重启后,保持之前的状态(如果之前是stop,那docker重启时,也是stop状态)
volumes: # 数据卷挂载路径设置,将本机目录映射到容器目录,相当于docker run命令中的-v
- /docker-data/cron/crontab:/etc/cron.d/crontab
- /docker-data/cron/scripts:/scripts
- /docker-data/cron/log:/var/log/
- /docker-data/nginx/config/conf.d/ssl:/nginx/config/conf.d/ssl
- /docker-data/nginx/html/ssl:/nginx/html/ssl
- /var/run/docker.sock:/var/run/docker.sock
#pwd /docker-data/docker-composes/cron/
docker compose up -d
- 查看docker-ps supercronic 是否没有重启
- 查看docker logs supercronic 是否没有错误日志
- 查看宿主机:/docker-data/cron/log 日志文件是否持续输出hello-world
- 一切正常:注释掉/docker-data/cron/crontab:/etc/cron.d/crontab 计划任务,重启容器:docker restart supercronic
- acme官网:
https://github.com/acmesh-official/acme.sh - acme.sh -h 显示帮助信息
- 映射目录检查:
- 检查容器是否包含映射目录:
docker inspect supercronic"Mounts": [
{
"Type": "bind",
"Source": "/docker-data/cron/log",
"Destination": "/var/log",
"Mode": "rw",
"RW": true,
"Propagation": "rprivate"
},
{
"Type": "bind",
"Source": "/docker-data/nginx/config/conf.d/ssl",
"Destination": "/nginx/config/conf.d/ssl",
"Mode": "rw",
"RW": true,
"Propagation": "rprivate"
},
{
"Type": "bind",
"Source": "/docker-data/nginx/html/ssl",
"Destination": "/nginx/html/ssl",
"Mode": "rw",
"RW": true,
"Propagation": "rprivate"
},
{
"Type": "bind",
"Source": "/var/run/docker.sock",
"Destination": "/var/run/docker.sock",
"Mode": "rw",
"RW": true,
"Propagation": "rprivate"
},
{
"Type": "bind",
"Source": "/docker-data/cron/crontab",
"Destination": "/etc/cron.d/crontab",
"Mode": "rw",
"RW": true,
"Propagation": "rprivate"
},
{
"Type": "bind",
"Source": "/docker-data/cron/scripts",
"Destination": "/scripts",
"Mode": "rw",
"RW": true,
"Propagation": "rprivate"
}
]
- 宿主机文件准备:
/docker-data/cron/scripts/
├── acme
└── acme-sh #此文件夹需要拷贝过来,chown -R root:root acme-sh
└── container-nginx-reload.sh #此文件需要拷贝过来,核对容器中的nginx容器名称
#!/bin/bash
# 定义变量
CONTAINER_NAME="nginx" # 替换为你的容器名称
COMMAND='["nginx", "-s", "reload"]'
# 创建 exec 实例
EXEC_ID=$(curl -s --unix-socket /var/run/docker.sock -X POST \
-H "Content-Type: application/json" \
-d "{
\"AttachStdout\": true,
\"AttachStderr\": true,
\"Cmd\": $COMMAND
}" \
http://localhost/containers/$CONTAINER_NAME/exec | jq -r '.Id')
# 检查是否成功获取 EXEC_ID
if [ -z "$EXEC_ID" ]; then
echo "Failed to create exec instance."
exit 1
fi
# 启动 exec 实例
curl -s --unix-socket /var/run/docker.sock -X POST \
-H "Content-Type: application/json" \
-d '{}' \
http://localhost/exec/$EXEC_ID/start
- 安装acmesh
docker exec -it supercronic bash #进入容器
#以下命令在容器内部执行
accountemai="lidongzhang@rstone.com.cn"
web_site_name="api.rstone.net.cn"
cd /scripts/acme/acme-sh
./acme.sh --install \
--home /scripts/acme/home \
--accountemail ${accountemai} \
--log /scripts/acme/acme.sh.log \
--nocron
- 安装时可能会提示:
It is recommended to install socat first.
We use socat for the standalone server, which is used for standalone mode.
If you don't want to use standalone mode, you may ignore this warning.
#这个提示是建议安装socat,来提供standalone server,
#我们不需要使用这种申请证书,因为我们使用的是nginx
# --home is a customized dir to install acme.sh in. By default, it installs into ~/.acme.sh
# --config-home is a writable folder, acme.sh will write all the files(including cert/keys, configs) there. By default, it's in --home
# --cert-home is a customized dir to save the certs you issue. By default, it's saved in --config-home.
# --accountemail is the email used to register an account to Let's Encrypt, you will receive a renewal notice email here.
# --accountkey is the file saving your account private key. By default, it's saved in --config-home.
# --useragent is the user-agent header value used to send to Let's Encrypt.
# --nocron install acme.sh without cronjob
# --issue Issue a cert.
mkdir -p /nginx/html/ssl/${web_site_name}
cd /scripts/acme/home
#设置联系人邮箱
./acme.sh --register-account -m lidongzhang@rstone.com.cn --home /scripts/acme/home
#更改默认 CA, 否则生成证书的时候会报错
./acme.sh --set-default-ca --server letsencrypt --home /scripts/acme/home
#申请证书
./acme.sh --issue -d ${web_site_name} -w /nginx/html/ssl/${web_site_name} --home /scripts/acme/home
mkdir -p /nginx/config/conf.d/ssl/${web_site_name}
cd /scripts/acme/home
./acme.sh --install-cert -d ${web_site_name} \
--key-file /nginx/config/conf.d/ssl/${web_site_name}/key.pem \
--fullchain-file /nginx/config/conf.d/ssl/${web_site_name}/cert.pem \
--home /scripts/acme/home \
--reloadcmd "/scripts/acme/container-nginx-reload.sh"
- 给网站配置ssl,完善网站的nginx配置文件的https「ssl」部分
- 配置crontab文件
#每天夜间 23:25 分执行, All the certs will be renewed automatically every 60 days.
echo "25 23 * * * /scripts/acme/home/acme.sh --cron --home /scripts/acme/home > /dev/null" >> /etc/cron.d/crontab
docker restart supercronic