Django's docker container doesn't catch the environment ALLOWED_HOSTS variable in GitLab CI pipeline

Aug 19 2020

I'm trying to build a GitLab-CI pipeline but Django doesn't seems to catch the ALLOWED_HOST variable passed as environment variable.

The project it self is a Django project running in a container. Django needs an ALLOWED_HOSTS and a SECRET_KEY value in its settings in order to work. On my development environment as well as on my production server, the variables are passed to Django via an env-file.

Django settings sample:

SECRET_KEY = os.environ.get('SECRET_KEY')

ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS").split(" ")

Env-file sample:

SECRET_KEY=mydummysecretkey

DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1]

This works fine on my dev and my production machines.

But when I try to run it in my .gitlab-ci.yml, Django doesn't find the DJANGO_ALLOWED_HOSTS variable. I always got this error:

$ docker run --rm $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA py.test ./my_project

ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS").split(" ")
AttributeError: 'NoneType' object has no attribute 'split'
ERROR: Job failed: exit code 1

Django가 SECRET_KEY 변수를 잘 포착하기 때문에 이것은 매우 이상합니다. 아래 코드 스 니펫에서 볼 수 있듯이 잘 표시되는 변수에 대해 에코도 수행했습니다.

참고 : Django는 Docker 컨테이너에서 실행 중이며 CI 파이프 라인은 두 번째 작업에서 테스트 (그리고 세 번째 작업에 배포)하기 위해 첫 번째 작업에서 이미지를 빌드하고 Gitlab 레지스터에 푸시합니다.

내 .gitlab-ci.yml은 다음과 같습니다.

image: docker:stable

services:
  - docker:19.03.0-dind

variables:
  SECRET_KEY: 'mydummysecretkey_gitlab-ci'
  DJANGO_ALLOWED_HOSTS: 'localhost 127.0.0.1 [::1]'

stages:
  - build
  - test

Build and push stage:
  stage: build
  script:
    - docker login --username $CI_REGISTRY_USER --password "$CI_BUILD_TOKEN" $CI_REGISTRY
    - docker pull $CI_REGISTRY_IMAGE:latest || true - docker build --cache-from $CI_REGISTRY_IMAGE:latest -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA ./my_project
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

Test stage:
  stage: test
  script:
    - echo $DJANGO_ALLOWED_HOSTS - docker login --username $CI_REGISTRY_USER --password "$CI_BUILD_TOKEN" $CI_REGISTRY
    - docker pull $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
    - docker run --rm $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA py.test ./my_project  # Fails here !
    - docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA $CI_REGISTRY_IMAGE:latest - docker push $CI_REGISTRY_IMAGE:latest

출력은 다음과 같습니다.

$ echo $DJANGO_ALLOWED_HOSTS
localhost 127.0.0.1 [::1]
$ docker login --username $CI_REGISTRY_USER --password "$CI_BUILD_TOKEN" $CI_REGISTRY
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
$ docker pull $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA ... $ docker run --rm $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA py.test ./my_project
Traceback (most recent call last):
  
...

  File "/usr/src/app/my_project/settings.py", line 32, in <module>
    ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS").split(" ")
AttributeError: 'NoneType' object has no attribute 'split'
ERROR: Job failed: exit code 1

답변

2 Bravo2bad Aug 20 2020 at 06:35

@Zeitounator 덕분에 내 대답을 얻었습니다.

간단하게 설명하기 위해 간단히 인용하겠습니다.

os.environ.get retrieves environment variables from the running system which is your docker container, not from the underlying gitlab-ci system. Gitlab CI vars (as your usual shell vars) are not automagically pushed to your container. SECRET_KEY does not issue a warning because it's simply null. DJANGO_ALLOWED_HOSTS does because you try to split it. You have to pass those env vars to your container, either with the -e docker option or through an env file you create on spot.

So this definitely works:

...

Test stage:
  stage: test
  script:

...

    - docker run --rm -e SECRET_KEY=mydummysecretkey_gitlab-ci -e DJANGO_ALLOWED_HOSTS='localhost 127.0.0.1 [::1]' $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA pytest

...

I ended up with something like this:

docker run --rm -e SECRET_KEY='$SECRET_KEY' -e DJANGO_ALLOWED_HOSTS='$DJANGO_ALLOWED_HOSTS' $CI_COMMIT_SHA pytest