By now, you may have realized that running cron jobs in a docker container is not straight-forward. Here is how I managed to get cron jobs to work in my example container from a previous tutorial.
First, we are going to create a startup script to be executed rather than packing more into the CMD of our dockerfile. This keeps things more "tidy".
vim startup.sh
This is my startup script, but you can alter it as you like.
# Start the cron service in the background. Unfortunately upstart doesnt work yet.
cron -f &
# Run the apache process in the foreground, tying up this so docker doesnt ruturn.
/usr/sbin/apache2 -D FOREGROUND
cron -f &
# Run the apache process in the foreground, tying up this so docker doesnt ruturn.
/usr/sbin/apache2 -D FOREGROUND
The cron -f & command results in us manually running the cron service and placing it in the background. The cron service won't work on its own due to Docker issues with Upstart. We need to run it in the background so that we can start other processes.
It is important that a process never stops runs in the foreground. This is because the docker executable exits as soon as the foreground process is finished, resulting in any changes in state being lost (e.g. any writes to files/internal database etc). In this example, I am running the cron in the background and the apache service in the foreground, but I could have done this the other way round, making sure to call the background processes before the final foreground one.
Now create a file with all your cron jobs in it. I call it crons.conf, but you can name it whatever you want, as long as you update the future tutorial steps accordingly.
vim crons.conf
My example crontab file:
* * * * * echo "echo 'crontab ran<br />';" >> /var/www/my_website/public_html/index.php
We now need to update our Dockerfile build script so that the container image will have the cron package, an updated crontab from the cron file, and call the startup script we created when started. I am showing the entire script in case people haven't read the previous tutorial that this extends from.
FROM ubuntu:12.04
MAINTAINER [Docker username here]
# Install the relevant packages
RUN apt-get update && apt-get install apache2 libapache2-mod-php5 -y
# Enable the php mod we just installed
RUN a2enmod php5
# Add our websites files to the default apache directory (/var/www)
ADD my_website /var/www/my_website
# Update our apache sites available with the config we created
ADD apache-config.conf /etc/apache2/sites-enabled/000-default
# expose port 8080 so that our webserver can respond to requests.
EXPOSE 8080
# Manually set the apache environment variables in order to get apache to work immediately.
ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_LOG_DIR /var/log/apache2
# Install the cron service
RUN apt-get install cron -y
# Add our crontab file
ADD crons.conf /var/www/my_website/crons.conf
# Use the crontab file.
RUN crontab /var/www/my_website/crons.conf
# Add our startup script to the container. This script should be executed upon starting the container.
ADD startup.sh /var/www/startup.sh
# Execute the containers startup script which will start many processes/services
CMD ["/bin/bash", "/var/www/startup.sh"]
Now we need to build the image from the updated Dockerfile. Make sure to make a note of the "Successfully built [Image ID]" line as we will need the Image ID in the next step.
docker build .
Run the image
docker run -p 80:80 [Image ID here] &
I have used the & to run the process in the background, but you don't have to.
That's it! If you want to go inside the container to check if your Cron jobs are taking effect, I recommend you Connect to the LXC container.
THANK YOU! I was struggling trying to get cron to work with Supervisor (which seems to be what most try to do to solve this). After HOURS of trying to get cron to do anything through Supervisor, I finally found this post. Life saver. Also, no Supervisor means less container complexity. Always up for that.
ReplyDeleteGreat article! You saved my time a lot.
ReplyDeleteThanks, always glad to know if I have helped others. I spend a large % of my time working on docker based projects. If there are any other tutorials on docker that you think would be useful, let me know. (I am going to roll one out soon about building/running docker inside docker).
Delete