Cron doesn't run cron task in Docker container - linux

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.

Related

Docker: cron within container no errors but still not working

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).

Start cron and another process in single docker container

I have a docker image that will start a foreground httpd process. I also have some tasks that
I'd like to run as cron jobs via crontab.
Ideally I'd like to start httpd as a non root user, however, to also start cron, will require me to be root
FROM ubuntu:latest
RUN apt-get update
&& DEBIAN_FRONTEND=noninteractive apt-get dist-upgrade -yq \
&& apt-get install -y cron httpd
# Do a bunch of other setup.....
USER 1000
#START PROCESSES....
The problem as I see it is that I cannot start cron as root, keep that process running and also start httpd as a foreground process.
Is there some way to have both these processes started in one docker container?
You can configure user used to run command in docker with something like
ENV USER_NAME dev
RUN echo "${USER_NAME} ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/${USER_NAME} && \
chmod 0440 /etc/sudoers.d/${USER_NAME}
ARG host_uid=1001
ARG host_gid=1001
RUN groupadd -g $host_gid $USER_NAME && useradd -g $host_gid -m -s /bin/bash -u $host_uid $USER_NAME
And build your image using
docker build --build-arg "host_uid=$(id -u)" --build-arg "host_gid=$(id -g)" -t <ur img> .
But why you can't run a bash script to execute the process in the background every time?

Docker Container: Cronjobs not starting (definity my error)

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

Docker Node.js Cron

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.

Why doesn't the cron service in Dockerfile run?

While searching for this issue I found that: cron -f should start the service.
So I have:
RUN apt-get install -qq -y git cron
Next I have:
CMD cron -f && crontab -l > pullCron && echo "* * * * * git -C ${HOMEDIR} pull" >> pullCron && crontab pullCron && rm pullCron
My dockerfile deploys without errors but the cron doesn't run. What can I do to start the cron service with an added line?
PS:
I know that the git function in my cron should actually be a hook, but for me (and probably for others) this is about learning how to set crons with Docker :-)
PPS:
Complete Dockerfile (UPDATED):
RUN apt-get update && apt-get upgrade -y
RUN mkdir -p /var/log/supervisor
RUN apt-get install -qq -y nginx git supervisor cron wget
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
RUN wget -O ./supervisord.conf https://raw.githubusercontent.com/..../supervisord.conf
RUN mv ./supervisord.conf /etc/supervisor/conf.d/supervisord.conf
RUN apt-get install software-properties-common -y && apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0x5a16e7281be7a449 && add-apt-repository 'deb http://dl.hhvm.com/ubuntu utopic main' && apt-get update && apt-get install hhvm -y
RUN cd ${HOMEDIR} && git clone ${GITDIR} && mv ./tybalt/* ./ && rm -r ./tybalt && git init
RUN echo "* * * * * 'cd ${HOMEDIR} && /usr/bin/git pull origin master'" >> pullCron && crontab pullCron && rm pullCron
EXPOSE 80
CMD ["/usr/bin/supervisord"]
PPPS:
Supervisord.conf:
[supervisord]
autostart=true
autorestart=true
nodaemon=true
[program:nginx]
command=/usr/sbin/nginx -c /etc/nginx/nginx.conf
[program:cron]
command = cron -f -L 15
autostart=true
autorestart=true
Having started crond with supervisor, your cron jobs should be executed. Here are the troubleshooting steps you can take to make sure cron is running
Is the cron daemon running in the container? Login to the container and run ps a | grep cron to find out. Use docker exec -ti CONTAINERID /bin/bash to login to the container.
Is supervisord running?
In my setup for instance, the following supervisor configuration works without a problem. The image is ubuntu:14.04. I have CMD ["/usr/bin/supervisord"] in the Dockerfile.
[supervisord]
nodaemon=true
[program:crond]
command = /usr/sbin/cron
user = root
autostart = true
Try another simple cron job to findout whether the problem is your cron entry or the cron daemon. Add this when logged in to the container with crontab -e :
* * * * * echo "hi there" >> /tmp/test
Check the container logs for any further information on cron:
docker logs CONTAINERID | grep -i cron
These are just a few troubleshooting tips you can follow.
Cron is not running because only the last CMD overrides the first one (as #xuhdev said). It's documented here : https://docs.docker.com/reference/builder/#cmd.
There can only be one CMD instruction in a Dockerfile. If you list more than one CMD then only the last CMD will take effect.
If you want to have nginx and cron running in the same container, you will need to use some kind of supervisor (like supervisord or others) that will be the pid 1 process of your container and manage the chield processes. I think this project should help : https://github.com/nbraquart/docker-nginx-php5-cron (it seems to do what you're trying to achieve).
Depending on what you're cron is here for, there would be other solution to that — like building a new image for each commit or each tags, etc...
I've used this with CentOS and it works:
CMD service crond start ; tail -f /var/log/cron
The rest of my Dockerfile just yum installs cronie and touches the /var/log/cron file so it will be there when the CMD runs.
On centos 7 this works for me
[program:cron]
command=/usr/sbin/crond -n -s
user = root
autostart = true
stderr_logfile=/var/log/cron.err.log
stdout_logfile=/var/log/cron.log
-n is for foreground
-s is to log to stdout and stderr
In my case, it turns out I needed to run cron start at run time. I can't put it in my Dockerfile nor docker-compose.yml, so I ended up placing in the Makefile I use for deploy.
Something like:
task-name:
# docker-compose down && docker-compose build && docker-compose up -d
docker exec CONTAINERNAME /bin/bash -c cron start

Resources