Missing environment variables on running python cronjob in Docker

Viewed 1244

I'm running a python script inside a docker container using crontab. Also, I set some environment variables (as database host, password, etc.) in .env file in the project's directory. If I run the script manually inside the container (python3 main.py) everything is working properly. But when the script is run by crontab the environment variables are not found (None). I have the following setup:

Dockerfile

FROM ubuntu:latest

RUN apt-get update -y
RUN apt-get -y install cron
RUN apt-get install -y python3-pip python-dev

WORKDIR /home/me/theservice
COPY . .

RUN chmod 0644 theservice-cron
RUN touch /var/log/theservice-cron.log

RUN chmod +x run.sh

ENTRYPOINT ./run.sh

run.sh

#!/bin/bash

crontab theservice-cron
cron -f

docker-compose.yml

version: '3.7'
services:
  theservice:
    build: .
    env_file:
      - ./.env

theservice-cron

HOME=/home/me/theservice

* * * * * python3 /home/me/theservice/main.py >> /var/log/theservice-cron.log 2>&1
#* * * * * cd /home/me/theservice && python3 main.py >> /var/log/theservice-cron.log 2>&1

I assumed that the cronjob is running in another directory and there the environment variables set in /home/me/theservice/.env are not accessible. So I tried to add HOME=/home/me/theservice line in the theservice-cron file or just to execute /home/me/theservice before running the script but it didn't help.

In the python script, I use os to access environment variables

import os 

print(os.environ['db_host'])

How I can fix this problem?

2 Answers

For those fighting to get ENV variables from docker-compose into docker, simply have a shell script run at ENTRYPOINT in your Dockerfile, with

printenv > /etc/environment

again, the naming of "/etc/environment" is CRUCIAL !

And then in your crontab, have it call a shell script:

* * * * * bash -c "sh /var/www/html/cron_php.sh"

The scripts simply does :

#!/bin/bash
cd /var/www/html
php whatever.php

You will now have the docker-compose environment variables in your php cron application. It took me a full day to figure this out. Hope i save someone's trouble now !

UPDATE:

In Azure Docker (Web app) the mechanism doesn't seem to work. A small tweak is needed:

  • In the Dockerfile, in the ENTRYPOINT sh script, write a file (and CHMOD to execution rights chmod 770 ) /etc/environments.sh using this command:

    eval $(printenv | awk -F= '{print "export " $1"=""""$2""" }' >> /etc/environments.sh)

Then, in your crontab shell where you execute php, do this:

#!/bin/bash 
. /etc/environments.sh 
php whatever.php

Notice the "." instead of source. Even though the Docker container is Linux using bash, source did not do the trick, the . did work.

Note: In my local Windows Docker the first solution, using /etc/envrionment worked fine. I was baffled to find out that on Azure the second fix was needed.

Related