Django check and alternate Docker Compose file: Debug flag not being set?

Question:

I’m trying to prep a Django application for production. I created an alternate docker-compose YML file where I specify DEBUG=0. However when I run the django check for deployment, it says that DEBUG is set to True.

Any thoughts on where I’m going wrong? I thought it was an issue with my use of Docker. But is it perhaps an issue with how I’m using Django?

Here are my steps:

  1. Created my project with docker-compose.yml (see below)
  2. Created docker-compose-prod.yml for production (see below)
  3. Ran the following
$ docker-compose down
$ docker-compose -f docker-compose-prod.yml up -d --build
$ docker-compose exec web python manage.py check --deploy
  1. Output of the check:
    ?: (security.W018) You should not have DEBUG set to True in deployment.

Some of investigatory steps so far:

A. Check the environment variables.

$ docker-compose exec web python
>>> import os
>>> os.environ.get('DEBUG')
'0'

B. Try rebuilding docker image in different ways, e.g. with –no-cache flag

C. Set the DEBUG flag in settings.py in a conditional code block (rather than using os.environ.get). This seemed to work. But I don’t understand why? Code detail below.

Code excerpts

  1. Excerpt from docker-compose.yml
services:
  web:
    ...
    environment:
      - ENVIRONMENT=development
      - SECRET_KEY=randomlongseriesofchars
      - DEBUG=1
  1. Excerpt from docker-compose-prod.yml
services:
  web:
    ...
    environment:
      - ENVIRONMENT=production
      - SECRET_KEY=anotherrandomlongseriesofchars
      - DEBUG=0
  1. Excerpts from settings.py
ENVIRONMENT = os.environ.get('ENVIRONMENT', default='production') 
SECRET_KEY = os.environ.get('SECRET_KEY')
DEBUG = os.environ.get('DEBUG', default=0)  #How is DEBUG being set to True?
...
if ENVIRONMENT == 'production':
    [Various settings for production]
    [Putting DEBUG=0 in this conditional block works]
Asked By: bigwinner

||

Answers:

Environment variables are strings, so result of os.environ.get() is a string.

If code expects variable to be int, boolean, etc – not string – first, it might fail. Or, try converting to desired type, an that might differ from desired result.

I.e., if converting to boolean, only empty string would result in False.

So, possible options are:

  • add logic to first read env vars and then correctly convert or parse them into target arguments.
  • use env helpers, like django-environ, environs which allow to auto-convert env vars to taget type and provide useful utility methods, generally providing something you might have implemented yourself in option 1
  • use different schema to pass arguments – i.e. not by env vars, but by custom settings file (there also exist helpers for that). Someone prefers env vars, someone prefers files, it also might depend on project / team / how you deploy (what is supported by instrument).
Answered By: Oleg Russkin
DEBUG = (os.getenv('DEBUG', '0') == '1')
Answered By: Amax