I\'ve recently tried running a cron job from within a linked docker container and run into an issue. My main docker container is linked to a postgres container and its port numb
The environment is set, but not available to the cron job. To fix that, you can do these two simple things
1) Save the env to a file in your ENTRYPOINT or CMD
CMD env > /tmp/.MyApp.env && /bin/MyApp
2) Then read that env into your cron command like this:
0 5 * * * . /tmp/.MyApp.env; /bin/MyApp
You should export your environment variable before you run cronjobs.
Other solutions are fine but they will fail when there are any special characters in your environment variable.
I have found the solution:
eval $(printenv | awk -F= '{print "export " "\""$1"\"""=""\""$2"\"" }' >> /etc/profile)
I ran into this same problem. I have a docker container that runs cron to execute some shell scripts periodically. I too had a hard time finding out why my scripts would run fine when I manually executed them inside the container. I tried all the tricks of creating a shell script that would run first to set the environment, but they never worked for me (most likely I did something wrong). But I continued looking and found this and it does work.
printenv | grep -v "no_proxy" >> /etc/environment
The trick here is the /etc/environment
file. When the container is built that file is empty, I think on purpose. I found a reference to this file in the man pages for cron(8). After looking at all the versions of cron they all elude to an /etc/?
file that you can use to feed environment variables to child processes.
Also, note that I created my docker container to run cron in the foreground, cron -f
. This helped me avoid other tricks with tail
running to keep the container up.
Here is my entrypoint.sh file for reference and my container is a debian:jessie base image.
printenv | grep -v "no_proxy" >> /etc/environment
cron -f
Also, this trick worked even with environment variables that are set during, docker run
commands.
To escape any weird characters that could break your script, and according to reasoning from Mark's answer, add this line to your entrypoint.sh
:
env | sed -r "s/'/\\\'/gm" | sed -r "s/^([^=]+=)(.*)\$/\1'\2'/gm" \ > /etc/environment
This way, if you have any variable like affinity:container==My container's friend
, it will be converted to affinity:container='=My container\'s friend
, and so on.
One can append the system environment variables to the top of a crontab file by using wrapper shell script to run the cron daemon. The following example is from CentOs 7,
In the Dockerfile
COPY my_cron /tmp/my_cron
COPY bin/run-crond.sh run-crond.sh
RUN chmod -v +x /run-crond.sh
CMD ["/run-crond.sh"]
run_cron.sh:
#!/bin/bash
# prepend application environment variables to crontab
env | egrep '^MY_VAR' | cat - /tmp/my_cron > /etc/cron.d/my_cron
# Run cron deamon
# -m off : sending mail is off
# tail makes the output to cron.log viewable with the $(docker logs container_id) command
/usr/sbin/crond -m off && tail -f /var/log/cron.log
This is based on a great blog post somewhere, but I lost the link.
inspired by @Kannan Kumarasamy answer:
for variable_value in $(cat /proc/1/environ | sed 's/\x00/\n/g'); do
export $variable_value
done
I can't state for sure, what process with pid1 is and that its stable during lifetime of OS. but as it is the first process to be run, inside a container i guess we can take it for granted it is a process with desired env vars set. take all of this with pich of salt unless some linux/docker docs proves this is completely ok.