I am new to docker. Managed to create a script which gets info from online source and populates an SQL DB. All works well within docker container.
However, I need to make this to run for example every minute.
So I amended my working Dockerfile and added the following:
Dockerfile:
RUN apt-get install -y cron
COPY cronms /etc/cron.d/cronms
RUN chmod 0644 /etc/cron.d/cronms
RUN crontab /etc/cron.d/cronms
RUN touch /var/log/cron.log
CMD cron && tail -f /var/log/cron.log
#CMD [ "python3", "./my_script.py" ] -- command before cron
my cronms file:
*/1 * * * * /usr/bin/python3 /my_script.py
Image builds without errors however when running it data is not being downloaded.
What I am missing please?
Thanks
Your crontab file has incorrect syntax. From the cron man page:
The system crontab (/etc/crontab) and the packages crontabs (/etc/cron.d/*) use the same format, except that the username for the command is specified after the time and date fields and before the command.
So your cronms file should look like:
*/1 * * * * root /usr/bin/python3 /my_script.py
I assume the Dockerfile in your question is truncated, but it's worth noting that for this to work you may need to explicitly install python3 as well as cron, depending on which base image you're using.
If I build an image using this Dockerfile:
FROM ubuntu:20.04
RUN apt-get update
RUN apt-get install -y cron python3
COPY cronms /etc/cron.d/cronms
RUN chmod 0644 /etc/cron.d/cronms
RUN crontab /etc/cron.d/cronms
RUN touch /var/log/cron.log
COPY my_script.py /my_script.py
CMD cron && tail -f /var/log/cron.log
And this cronms:
*/1 * * * * root /usr/bin/python3 /my_script.py
And this my_script.py:
#!/usr/bin/python3
import time
with open("/tmp/datafile", "a") as fd:
fd.write(time.ctime())
fd.write("\n")
Then I can confirm that everything works as expected: the script is
executed once a minute.
Note that nothing is written to /var/log/cron.log, however,
because cron logs to syslog, not to a file. To see output from
cron, you would need to arrange to run a syslog daemon, or use a
different cron daemon (for example, the busybox crond command can
log to a file or stderr).
Related
I'm trying to run a script in a Docker container with cron. It looks like the script isn't being run at all at first. crontab -l shows the task. service cron reload doesn't fix the issue. If I do crontab -e, add a space and save the file, it suddenly works. So I can rule out permission issues etc.
FROM node:17
RUN apt-get update && apt-get install -y cron
COPY scripts /app/scripts
COPY package.json /app/package.json
RUN chmod -R +x /app/scripts
WORKDIR /app
RUN touch /var/log/cron.log
RUN npm install
RUN echo "* * * * * /usr/local/bin/node /app/scripts/test.js >> /var/log/cron.log 2>&1" >> /var/spool/cron/crontabs/root
CMD ["cron","-f"]
Adding RUN crontab -u root /var/spool/cron/crontabs/root after creating the file seems to have fixed it.
I'm using the current time to develop myself a little bit and I decided to invest some time in Docker Containers.
I created myself some small learning excercises where I am working on now.
I have an Issue with my Cronjobs. It should be a cronjob which is running every minute. Runtime of the completed scripts will be something around 40-50 seconds. Therefore I decided not to start a container every minute, I want to keep the container running and run the cronjobs inside the container.
My Issue: Cronjob is not starting.
#Dockerfile
FROM ubuntu
RUN apt-get update
RUN apt-get -yq install cron
COPY scripts/cmd.txt /home/cmd.sh
RUN chmod 744 /home/cmd.sh
COPY scripts/cron.txt /etc/cron.d/test-cron
RUN chmod 644 /etc/cron.d/test-cron
RUN crontab /etc/crontab.d/test-cron
RUN touch /var/log/cron.log
CMD cron && tail -f /var/log/cron.log
# scripts/cmd.txt
echo "test aus CMD" >> /var/log/cron.log
# scripts/cron.txt
* * * * * root /home/cmd.sh >> /var/log/cron.log 2>&1
* * * * * root echo "Hello world" >> /var/log/cron.log 2>&1
From my understanding the /var/log/cron.log should get some content over time but nothing happens. I'm pretty sure that's me who caused this error but I'm not finding it.
Anybody an Idea what I did wrong?
Thanks and kind regards
Holger
There are a few typos in your files.
#Dockerfile
FROM ubuntu
RUN apt-get update
RUN apt-get -yq install cron
COPY scripts/cmd.txt /home/cmd.sh
RUN chmod 744 /home/cmd.sh
COPY scripts/cron.txt /etc/cron.d/test-cron
RUN chmod 644 /etc/cron.d/test-cron
RUN crontab /etc/crontab.d/test-cron # Here it is, just replace `crontab.d` by `cron.d`
RUN touch /var/log/cron.log
CMD cron && tail -f /var/log/cron.log
# scripts/cron.txt
* * * * * root /home/cmd.sh >> /var/log/cron.log 2>&1 # Remove the `root` command from this line...
* * * * * root echo "Hello world" >> /var/log/cron.log 2>&1 # ...and also from that one
I am using docker and OS is Ubuntu.
If i use crontab -e and place data in there then cron runs fine.
* * * * * /var/www/daily.sh
But if remove the container then that crontab is also gone. I want to somehow place crontab in some file like crontabs.sh then mount that inside container so that if i create container then my cron is still there.
I don't know at what location i need to mount that so that cron runs normally. something like
/myhost/code/crontabs.sh: /etc/crons.daily
As mentioned in this answer, you can copy your file, adding to your Dockerfile:
FROM ubuntu:latest
MAINTAINER docker#ekito.fr
# Add crontab file in the cron directory
COPY crontab /etc/cron.d/crons.daily
# Give execution rights on the cron job
RUN chmod 0644 /etc/cron.d/hello-cron
# Create the log file to be able to run tail
RUN touch /var/log/cron.log
# Run the command on container startup
CMD cron && tail -f /var/log/cron.log
(Source: example "Run a cron job with Docker" (by Julien Boulay)
That way, your image will always include the right cron definition.
You can initialize the content of 'crontab', the local file you are copying to your image, with cronsandbox.com.
In your case: 0 23 * * *
If you don't want to make a new image at each change, you remove the COPY line, and mount that file at runtime:
docker run -v crontab:/etc/cron.d/hello-cron -n mycontainer myimage
That way, the local file crontab is mounted as in the container as /etc/cron.d/hello-cron (or any other name you want).
Whenever you change it, stop and restart your container.
Hello Everyone I just about have my entire app dockerized except my cron jobs here is my dockerFile
FROM nodesource/precise
# Update install os dep
RUN apt-get update && apt-get install -y apt-utils cron
RUN apt-get -y install pwgen python-setuptools curl git unzip vim
# Add code
RUN mkdir /var/sites
ADD /api /var/sites/api
ADD /services /var/sites/services
RUN cd /var/sites/services && npm install
RUN cd /var/sites/api && npm install
# Add crontab file in the cron directory
ADD crontab /etc/cron.d/hello-cron
# Give execution rights on the cron job
RUN chmod 0644 /etc/cron.d/hello-cron
# Create the log file to be able to run tail
RUN touch /var/log/cron.log
# Run the command on container startup
CMD cron && tail -f /var/log/cron.log
my cron file
* * * * * root echo "Hello world" >> /var/log/cron.log 2>&1
* * * * * cd /var/sites/services/ldapSync && node index.js >> 2>&1
# An empty line is required at the end of this file for a valid cron file.
if I remove the node cron job just leave the hello world it works fine but when I have the node cron in there it doesn't appear to do anything. If I go into the container and do crontab -e and add it manually it works fine.
Any ideas what I'm doing wrong?
Thanks
In second line of your cron file you are missing username in the format
So instead of
* * * * * cd /var/sites/services/ldapSync && node index.js >> 2>&1
you should have
* * * * * root cd /var/sites/services/ldapSync && node index.js >> 2>&1
For more info see this
Have a look at redmatter/cron image. It took me a while to get crond to behave.
There is an example in the test sub folder on github.
You can also refer to my answer here.
I have made a Docker image, from a Dockerfile, and I want a cronjob executed periodically when a container based on this image is running. My Dockerfile is this (the relevant parts):
FROM l3iggs/archlinux:latest
COPY source /srv/visitor
WORKDIR /srv/visitor
RUN pacman -Syyu --needed --noconfirm \
&& pacman -S --needed --noconfirm make gcc cronie python2 nodejs phantomjs \
&& printf "*/2 * * * * node /srv/visitor/visitor.js \n" >> cronJobs \
&& crontab cronJobs \
&& rm cronJobs \
&& npm install -g node-gyp \
&& PYTHON=/usr/sbin/python2 && export PYTHON \
&& npm install
EXPOSE 80
CMD ["/bin/sh", "-c"]
After creation of the image I run a container and verify that indeed the cronjob has been added:
crontab -l
*/2 * * * * node /srv/visitor/visitor.js
Now, the problem is that the cronjob is never executed. I have, of course, tested that "node /srv/visitor/visitor.js" executes properly when run manually from the console.
Any ideas?
One option is to use the host's crontab in the following way:
0 5 * * * docker exec mysql mysqldump --databases myDatabase -u myUsername -pmyPassword > /backups/myDatabase.sql
The above will periodically take a daily backup of a MySQL database.
If you need to chain complicated commands you can also use this format:
0 5 * * * docker exec mysql sh -c 'mkdir -p /backups/`date +\%d` && for DB in myDB1 myDB2 myDB3; do mysqldump --databases $DB -u myUser -pmyPassword > /backups/`date +\%d`/$DB.sql; done'
The above takes a 30 day rolling backup of multiple databases and does a bash for loop in a single line rather than writing and calling a shell script to do the same. So it's pretty flexible.
Or you could also put complicated scripts inside the docker container and run them like so:
0 5 * * * docker exec mysql /dailyCron.sh
It's a little tricky to answer this definitively, as I don't have time to test, but you have various options open to you:
You could use the Phusion base image, which comes with an init system and cron installed. It is based on Ubuntu and is comparatively heavyweight (at least compared to archlinux) https://registry.hub.docker.com/u/phusion/baseimage/
If you're happy to have everything started from cron jobs, you could just start cron from your CMD and keep it in the foreground (cron -f).
You can use lightweight process manager to start cron and whatever other processes you need (Phusion use runit, Docker seem to recommend supervisor).
You could write your own CMD or ENTRYPOINT script that starts cron and your process. The only issue with this is that you will need to be careful to handle signals properly or you may end up with zombie processes.
In your case, if your just playing around, I'd go with the last option, if it's anything more serious, I'd go with a process manager.
If you're running your Docker container with --net=host, see this thread:
https://github.com/docker/docker/issues/5899
I had the same issue, and my cron tasks started running when I included --pid=host in the docker run command line arguments.