To preface, I have been referencing these two articles for help:
My goal is to have a cron job automatically start when I start my docker container. Currently, it doesn't automatically start, but I can manually go into my container and run service cron start
, which starts the job, and it works correctly.
So the problem is: How do I get my cron job to start automatically when my container starts up?
Dockerfile
FROM microsoft/dotnet:latest
RUN apt-get update && apt-get install -y cron
COPY . /app
WORKDIR /app
ADD crontab /etc/cron.d/crontab
RUN chmod 0600 /etc/cron.d/crontab
RUN crontab -u root /etc/cron.d/crontab
RUN touch /var/log/cron.log
RUN ["dotnet", "restore"]
RUN ["dotnet", "build"]
EXPOSE 5000/tcp
CMD cron && tail -f /var/log/cron.log
CMD service cron start
crontab
* * * * * echo "Hello world" >> /var/log/cron.log 2>&1
# Empty space
Though I wasn't able to get cron working in that particular container, I was able to create a standalone docker container specifically for cron, and was successful in getting it to run automatically.
As far as setup for the cron container, I followed the linked article, Run a cron job with Docker - Julien Boulay, and was able to get it working.
As system administrators, we'll invariably encounter the need to schedule tasks. We can achieve this by using cron services in Linux systems. Also, we can enable the cron scheduling services in container systems. Now, this tutorial will elucidate two different ways of enabling cron services in the Docker containers.
You might discover that your job works when run via the command line, but won't run via cron. This may be due to the location you're executing from or the PATH you're using. The use of relative paths is a common cause of cron issues. In cron, the PATH is set by default to /bin:/usr/bin .
The cron reads the crontab (cron tables) for running predefined scripts. By using a specific syntax, you can configure a cron job to schedule scripts or other commands to run automatically.
What I'm doing is have the CMD call cron directly like this:
CMD /usr/sbin/cron -f
Before that I'm adding the crontab to the container and assigning it as the root crontab with the command:
RUN crontab /root/mycrontab
You don't need to call the crontab command on files that are located in /etc/cron.d
, but you do need those files to have the correct syntax. Using your example, instead of this:
* * * * * echo "Hello world" >> /var/log/cron.log 2>&1
You should have this:
* * * * * root echo "Hello world" >> /var/log/cron.log 2>&1
On your crontab file. This only applies to crontab files located within /etc/cron.d
, otherwise your crontab file syntax is correct and you use the crontab
command to load it.
Starting from your example, I think you should modify your files like this:
Dockerfile
FROM microsoft/dotnet:latest
RUN apt-get update && apt-get install -y cron
COPY . /app
WORKDIR /app
ADD crontab /etc/cron.d/crontab
RUN chmod 0600 /etc/cron.d/crontab
RUN touch /var/log/cron.log
RUN ["dotnet", "restore"]
RUN ["dotnet", "build"]
EXPOSE 5000/tcp
CMD /usr/sbin/cron -f
crontab
* * * * * root echo "Hello world" >> /var/log/cron.log 2>&1
Another alternative would be:
Dockerfile
FROM microsoft/dotnet:latest
RUN apt-get update && apt-get install -y cron
COPY . /app
WORKDIR /app
ADD crontab /root/
RUN crontab /root/crontab
RUN touch /var/log/cron.log
RUN ["dotnet", "restore"]
RUN ["dotnet", "build"]
EXPOSE 5000/tcp
CMD /usr/sbin/cron -f
crontab
* * * * * echo "Hello world" >> /var/log/cron.log 2>&1
We had a problem with php-fpm and docker where our cronjob tasks were not be executed. There were two problems we solved:
crontab
file into the docker container by using COPY config/custom-cron /etc/cron.d/custom-cron
. The problem is, that our line endings were in windows format. This did break our crontab file, because this line endings are not converted while copy that file into the container.CMD ["cron", "-f"]
which did block the main php-fpm
process. This results in a 502 Bad gateway
error when calling our web application.Finaly we made it work by editing the crontab file manually while building the docker image instead of copy-pasting and using supervisord to have multiple tasks running inside docker. This should work on all supported operating systems.
FROM php:7.1.16-fpm
RUN apt-get update && apt-get install -y cron supervisor
# Configure cron
RUN crontab -l | { cat; echo "* * * * * echo 'Hello world' >> /var/log/cron-test.log 2>&1"; } | crontab -
# Configure supervisor
COPY config/supervisord.conf /etc/supervisor/supervisord.conf
[supervisord]
logfile = /dev/null
loglevel = info
pidfile = /var/run/supervisord.pid
nodaemon = true
[program:php-fpm]
command = php-fpm
autostart = true
autorestart = true
stdout_logfile = /dev/stdout
stdout_logfile_maxbytes = 0
stderr_logfile = /dev/stderr
stderr_logfile_maxbytes = 0
[program:cron]
command = cron -f
autostart = true
autorestart = true
stdout_logfile = /dev/stdout
stdout_logfile_maxbytes = 0
stderr_logfile = /dev/stderr
stderr_logfile_maxbytes = 0
There is a bug in Debian based distributions which will cause cronjobs to fail because docker uses layered filesystem and cron doesn't start and says NUMBER OF HARD LINKS > 1 (/etc/crontab)
.
The fix is simple, add touch /etc/crontab /etc/cron.*/*
to the entrypoint of your container.
I have made a blog post explaining how to setup cron in a Docker container here : https://esc.sh/blog/cron-jobs-in-docker/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With