我使用 Dockerfile 构建了容器,其中使用 PHP-FPM Alpine Linux 映像。我需要定期在这个容器内运行一个 cron 作业。将应用程序文件复制到该/var/www
目录后,创建一个用户组和用户 www,然后切换到该用户。在入口点脚本中,我使用命令启动 crond crond -fbS -d 8 -L
。然后我将 docker-entrypoint 添加为 PHP-FPM。我正在尝试执行命令
* * * * * php /var/www/artisan schedule:run >> /tmp/mycommand.log 2>> /var/tmp/cronjob.log
作为定时任务。并且有一个startup_script.sh
作为入口点。下面是我的 Dockerfile。
FROM php:7.3-fpm-alpine
RUN mkdir -p /etc/cron.d
WORKDIR /var/www
RUN apk update && apk add \
rsyslog\
openrc \
busybox-suid \
postgresql-dev \
build-base \
freetype-dev \
libjpeg-turbo-dev \
libpng-dev \
libzip-dev \
zip \
jpegoptim optipng pngquant gifsicle \
vim \
unzip \
git \
curl \
busybox-initscripts
RUN docker-php-ext-install pdo_pgsql pdo_mysql mbstring zip exif
pcntl
RUN docker-php-ext-configure gd --with-gd --with-freetype-
dir=/usr/include/ --with-jpeg-dir=/usr/include/ --with-png-
dir=/usr/include/
RUN docker-php-ext-install gd
RUN addgroup -g 8877 -S www && \
adduser -u 8877 -S www -G www
COPY /src/crontab /etc/crontabs/www
COPY /src/cron.allow /etc/cron.d
USER www
COPY --chown=www:www ./src /var/www
CMD ./start_script.sh
EXPOSE 9000
下面是我的start_script.sh
,它将启动 cronjob:
#!/bin/sh
# turn on bash's job control
set -m
# Start the primary process and put it in the background
#php-fpm &
#php artisan schedule:run
echo "TEST" >> /var/tmp/cronjob.log
crond -fbS -d 8 -L /var/tmp/cronjob.log &
docker-php-entrypoint php-fpm
# Start the helper process
#php artisan migrate --force
# the my_helper_process might need to know how to wait on the
# primary process to start before it does its work and returns
#su www
#chown -R www:www /var/www/*
# now we bring the primary process back into the foreground
# and leave it there
fg %1
Docker 容器已完美构建并运行,但当 cron 尝试在 crontab 中执行 cronjob 时,会收到错误“root:permission returned”。以及“该组不允许该操作”。
是否可以以非 root 用户身份运行 cron?我该怎么做?
答案1
有两件事对我有用:
a) /etc/crontabs 中 www 的 crontab 文件必须由 root 所有。然后这个 CMD 运行 cron 和 PHP:
CMD crond -l 0 && php-fpm
缺点是我没有在docker logs
.
b) 使用 Supervisor 在单个容器中运行多个服务,例如 cron、php-fpm(在我的例子中是 NGINX)(这帮助很大):
这是一个supervisord.conf 文件,也可能适合您:
[supervisord]
nodaemon=true
[program:php]
command=php-fpm -F
stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes=0
stderr_logfile=/dev/fd/2
stderr_logfile_maxbytes=0
[program:cron]
command=crond -l 0 -f
stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes=0
stderr_logfile=/dev/fd/2
stderr_logfile_maxbytes=0
Dockerfile 提取:
RUN apk --update upgrade && apk update && apk add supervisor
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
这样做的好处是,主管将负责始终运行的两个服务(或退出的容器),并且我还将在docker logs
.