Open bkraul opened 5 years ago
The SERVICE_CRON_OPTS
are actually just the arguments passed to the crond
when it's starting (https://linux.die.net/man/8/crond).
The current solution is to either mount the cron.d
folder or build a custom image with the crontab
file copied into the image.
Works for me! Thank you.
Ok so maybe not so fast π’ . I mounted the /etc/cron.d
folder to my host's persisted storage and placed a file there called myfile
with the following content:
* * * * * application echo "Cron is running" > /etc/cron.d/log.txt 2>&1
The file is marked as chmod +x
and is owner by root:root
(Note the empty line at end, as I have read it matters).
supervisorctl
says the crond service is running. This is on webdevops/php-apache:alpine
.
However, the job does not seem to be running (no log.txt file being created/updated and no docker stdout either). What am I missing?
I see a /opt/docker/bin/service.d/cron.d//10-init.sh
that runs on starting the container. It looks for files on /opt/docker/etc/cron
, and it copies them to /etc/cron.d
after making some changes to them (adding an empty line at end and setting permissions to 644). I am a little confused as to what's going on.
OK so, interestingly enough. I changed my image to webdevops/php-apache
(which I assume is the debian/ubuntu variant), and my cron job runs like so:
I am mounting /opt/docker/etc/cron
to my persisted storage, I am putting my file there, now as 20-myjob
with the same content. The file ends up being copied to /etc/cron.d
per my previous post.
I can see the job running on stdout.
Which begs the question, why does the job not run on the alpine
tag?
UPDATE: Went back to mounting /etc/cron.d
after seeing that 10-init.sh
keeps adding a blank line to the files every time the container starts. Job still runs fine on debian/ubuntu variant, but not on alpine.
Any update on why cron.d jobs don't seem to be working on the alpine variant?
Sorry, won't have time before christmas to look into it
No worries. Have a merry Christmas!
Hey man, just touching base with you on this. It would be awesome if cron would work as expected on the alpine tag, as the image is much leaner.
Same problem here. Jobs created via crontab -e
work just fine. But stuff in /etc/cron.d/
is not running.
BTW: Starting the image with SERVICE_CRON_OPTS="-c /etc/cron.d/"
doesn't help either.
Any news on this? Currently I work around this issue with:
crontab -l | cat - <( cat "$CRON_FILE" ) | crontab -
@hhoechtl Is the alpine variant no longer being actively developed? I notice that you likely have most of your images on autobuild, as I see pretty recent image updates, even to the alpine one, which is why I was asking. As you can understand, a lot of us consider your images to be of utmost quality and maintenance, but it is important to know if you are intending to continue maintaining them long term. π
I'm maintaining as many versions as I can, but my focus is clearly on the official PHP7.x images.
Just a small hint (I don't have much time atm): the cron service itself must be enabled using RUN docker-service-enable cron
.
Usually we built our own images based on the webdevops images, which have this command COPY etc/ /opt/docker/etc/
.
etc
βββ cron
βΒ Β βββ crontab
βββ nginx
βΒ Β βββ conf.d
βΒ Β βΒ Β βββ 10-realip.conf
βΒ Β βββ vhost.common.d
βΒ Β βββ 02-upload.conf
βΒ Β βββ 10-general.conf
βΒ Β βββ 20-redirects.conf
I've personally never looked into or used the SERVICE_CRON_OPTS
. Maybe @mblaschke can tell you how this was intended.
The alpine image does have the cron service enabled: https://github.com/webdevops/Dockerfile/blob/5d307c8a5a1a34171dcebfdef0d2df8f8040c8e4/docker/php/alpine-php7/Dockerfile#L96
I'm struggling with this as well. The crond is running, but alpine uses the Busybox crond which probably bahaves different compared to the "real" crond. For starters, it looks for crontabs in /var/spool/cron/crontabs
, not /etc/cron.d
, and this is a symlink to /etc/crontabs
.
If you create file /etc/crontabs/application
and put a normal cron into it (without user):
* * * * * id
You would see that it starts outputting
uid=1000(application) gid=1000(application) groups=1000(application)
Meaning it is running this cron as user application. It has to be named application (or any other valid user), otherwise it won't execute.
I don't know much about alpine but It might be a problem with busybox, as we are having a similar issue (cron not executing) on versions or Nextcloud that are build on top of alpine.
Problem and problem... the thing is that the alpine-image has the same cron.d structure and script as the ubuntu one, but they are running different crond implementations.
The busybox crond doesn't load the /etc/cron.d scripts. I'm not sure if it would be possible to run them either.
volumes:
- ./www/crm:/app:rw
- ./www/crm.cron/:/var/spool/cron/crontabs/:rw
touch file "root" file in ./www/crm.cron/
insert in ./www/crm.cron/root you cron line
@pomazanbohdan Thank you for your explanation. Works like expected, if the permissions are correct on the docker host!
I'm putting here my TYPO3ish everyday crontab line, if somebody else needs it. It's the content of my /var/spool/cron/crontabs/application
file:
* * * * * TYPO3_CONTEXT=Production/Live /usr/local/bin/php /app/releases/current/typo3cms crontab:run > /dev/null 2>&1
Hello, I've been trying for a long time to get the CronJob running properly. I've been through several situations now. Mount the cron files for root and application under / var / spool / cron / crontabs or under / etc / crontabs and also under /opt/docker/bin/service.d/cron.d/ now and then the root cronfile is partially executed but the cronjob under application is never executed. I slowly don't know anymore what is correct and how. Above, @hhoechtl asked if @mblaschke could say how SERVICE_CRON_OPTS is called correctly. I would be happy if you could say your results or how the crons are going right for you. I have: image: webdevops / php-apache: 7.4-alpine running
etc/cron/crontab
0 8 * * * application /usr/local/bin/php /app/bin/console --env=production dosomething
Dockerfile
FROM webdevops/php-apache:7.4-alpine
COPY etc/ /opt/docker/etc/
exec /usr/sbin/crond -f $SERVICE_CRON_OPTS
Therefore this ENV variable is only for applicatoin parameters for cron itself like described here: https://linux.die.net/man/8/cron
Hey guys, I want to come back to that. So I've tried a lot. If I mount the cron file of root and application under /opt/docker/etc/cron then this can also be seen under /etc/cron.d but nothing works.
If I mount this under /var/spool/cron/crontabs/ then it will be executed by user root but not by application.
So my approach was just to mount this and specify the user in the cron file. But the "column" with the user buw the username is interpreted as a command. I see that under Portainer in the logs that he does not find the command application.
I let it go like this now.
All crons run as root, but every 15 minutes I run a cron that changes the directory /tmp/ and everything below /app/ with chown -R 1000: 1000.
Not nice but it works for now. maybe someone can tell me what I have to do or where to mount that with the cron files of root and application with the correct rights etc.
Sorry I have to ask again: I have included my cron files in the composer file like this.
volumes:
- ./configs/php.ini:/opt/docker/etc/php/php.ini:ro
- ./configs/crontabs/:/var/spool/cron/crontabs/:rw`
The 2 crons look like this. application
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
m h dom mon dow user command
- ls -all /tmp >> /tmp/application-cron.log
- ls -all /tmp > /tmp/application-ls-all.txt
- /usr/local/bin/php /app/JTL-PLde-Projekt/includes/cron_inc.php
root
m h dom mon dow user command
- ls -all /tmp >> /tmp/root-cron.log
- ls -all /tmp > /tmp/root-ls-all.txt /2 * /bin/chown -R 1000:1000 /tmp/ /app/`
All crons work except for the one with / usr / local / bin / php and I don't see them in the logs
2021-03-13T00:11:00.410675090Z crond: can't execute '/bin/bash' for user application 2021-03-13T00:11:00.411270338Z crond: can't execute '/bin/bash' for user application`
I comment that /bin/bash from is in the logs
2021-03-13T00:29:00.969616281Z Could not open input file: /app/JTL-PLde-Projekt/includes/cron_inc.php
If I run it as a user application in the console, everything works Does anyone know?
Alpine versions of "webdevops/php-nginx....-alpine" run BusyBox version of cron, you can check with:
crond --help
You can put tasks in the /etc/periodic folders: 15min or daily or hourly or monthly or weekly
OR
you can replace the file at /var/spool/cron/crontabs/root which runs and therefore disables the default periodic schedule folders.
Dockerfile example:
FROM webdevops/php-nginx-dev:7.4-alpine
COPY mycrontask /var/spool/cron/crontabs/root
mycrontask example:
#!/bin/sh
# m h dom mon dow command
* * * * * /usr/local/bin/php /app/bin/console your:symfony:command
note that there is no user parameter and I use absolute paths, thats why I left the symfony command in the example
I've been having a similar issue with struggling to get the cron working.
I found the simplest way to set up my own cron schedule was to edit the /var/spool/cron/crontabs/root
file.
This file is the main cron that runs, I appended my own cron scheduled job to the end (Laravel scheduler).
Add this or similar to your ./Dockerfile
:
RUN echo "* * * * * cd /app && php artisan schedule:run >> /dev/null 2>&1" >> /var/spool/cron/crontabs/root
Entry Breakdown:
RUN
-> Dockerfile command to perform a shell commandecho "
-> Begin output string* * * * *
-> The schedule (every minute of every day)cd /app && php artisan schedule:run
-> My command>> /dev/null 2>&1
-> Discard any terminal output"
-> End output String>> /var/spool/cron/crontabs/root
-> Append the output to the given fileI invested a few hours to find out how exactly the execution of user crontabs works in the Alpine and Debian images. I think I understand it now and can provide a script to help you easily install a working user crontab:
#!/bin/bash
source /etc/os-release
if [ "$ID" == "alpine" ]; then
CRONTAB_BASE="/etc/crontabs"
if [[ -d "/opt/docker/etc/crontabs/" ]]; then
find /opt/docker/etc/crontabs -type f | while read CRONTAB_FILE; do
CRONTAB_FILENAME="$(basename $CRONTAB_FILE)"
if [[ ! -d "$CRONTAB_BASE" ]]; then
mkdir -p $CRONTAB_BASE
fi
echo "-> Deploy $CRONTAB_FILENAME to $CRONTAB_BASE"
cat $CRONTAB_FILE >> /etc/crontabs/$CRONTAB_FILENAME
chown root:root -- "$CRONTAB_BASE/$CRONTAB_FILENAME"
done
fi
elif [ "$ID" == "debian" ]; then
CRONTAB_BASE="/var/spool/cron/crontabs"
if [[ -d "/opt/docker/etc/crontabs/" ]]; then
find /opt/docker/etc/crontabs -type f | while read CRONTAB_FILE; do
CRONTAB_FILENAME="$(basename $CRONTAB_FILE)"
if [[ ! -d "$CRONTAB_BASE" ]]; then
mkdir -p $CRONTAB_BASE
fi
echo "-> Deploy $CRONTAB_FILENAME to $CRONTAB_BASE"
cat $CRONTAB_FILE >> $CRONTAB_BASE/$CRONTAB_FILENAME
chown $CRONTAB_FILENAME:$CRONTAB_FILENAME -- "$CRONTAB_BASE/$CRONTAB_FILENAME"
chmod 0600 "$CRONTAB_BASE/$CRONTAB_FILENAME"
done
fi
else
echo "Distribution $ID not supported by cron fix script!"
fi
Copy this file inside the docker image to /opt/docker/bin/service.d/cron.d
and name it 20-cron-fix.sh
and ensure it is executable. Next copy your crontab (in my case application
for the user application
) to /opt/docker/etc/crontabs
. Depending on the type image you are using (debian or alpine) the script will copy the crontab to the right place and ensure, the permissions are set right.
During my research, I found that in the Alpine image, cron expects the file to be owned by the root user and group and located in /etc/crontabs
. In the Debian image, the file must be located in /var/spool/cron/crontabs
, must belong to the user for whom the file was created and must be read/write only for that user.
I tested it for two days. I think it's a user privilege issue User of the code: root; user of Nginx: nginx; user of php-fpm: application
You can run the root /bin/echo 1> command. > /tmp/test.log Cannot run: /usr/local/bin/php.app/artisan schedule:run > > /dev/null 2> & 1
My solution: // The original cron remains unchanged COPY docker/etc/cron /opt/docker/etc/cron/ // Just add this new paragraph RUN echo " * /usr/local/bin/php /app/artisan schedule:run > > /dev/null 2> &1" > > /var/spool/cron/crontabs/application RUN chown application:crontab /var/spool/cron/crontabs/application RUN chmod 0600 /var/spool/cron/crontabs/application
Tortured for a long timeπ
Commands in your Dockerfile
# Copy crontab file
COPY ./docker/crontabs/application /var/spool/cron/crontabs/application
# Set the correct permission
RUN chmod 0600 /var/spool/cron/crontabs/application
Content in the application
file:
* * * * * cd /var/www/html && /usr/local/bin/php artisan schedule:run >> /dev/null 2>&1
This setup is tailored for the Laravel scheduler. Adjust the command and path according to your configuration.
Here is my solution for CRON not working in webdevops/php-apache:5.6
The problem is, that the script /opt/docker/bin/service.d/cron.d/10-init.sh
is copying the cronjobs from /opt/docker/etc/cron/
to /etc/cron.d/
and doing some other stuff, but is not applying the cronjob at the end.
The solution is to add an extra line before "done":
# Install crontab files
if [[ -d "/opt/docker/etc/cron" ]]; then
mkdir -p /etc/cron.d/
find /opt/docker/etc/cron -type f | while read CRONTAB_FILE; do
# fix permissions
chmod 0644 -- "$CRONTAB_FILE"
# add newline, cron needs this
echo >> "$CRONTAB_FILE"
# Install files
cp -a -- "$CRONTAB_FILE" "/etc/cron.d/$(basename "$CRONTAB_FILE")"
crontab "/etc/cron.d/$(basename "$CRONTAB_FILE")"
done
fi
Then mount the fixed script and the cronjobs
some-project:
image: webdevops/php-apache:5.6
restart: always
volumes:
- type: bind
source: /somedir/cron
target: /opt/docker/etc/cron
consistency: cached
- type: bind
source: /somedir/10-init-fixed.sh
target: /opt/docker/bin/service.d/cron.d/10-init.sh
consistency: cached
would be nice if it would be fixed in future releases.
@damsma wouldn't it make more sense to submit this as a PR? Thank you for making it work but seems it's still a workaround. @htuscher would it make sense to make this change upstream?
Hopefully this is a simple question. How does one properly implement cron jobs using the webdevops images? I am specifically using the webdevops/php-apache:alpine image.
I know the ENV var (
SERVICE_CRON_OPTS
) allows for cron options but I do not see how to properly set up the jobs in the documentation.I am currently mounting the
/etc/cron.d
folder to a persisted volume, but I suspect this is not the best way to go about it...Thank you for your help!