El contenedor acoplable de Django no detecta la variable de entorno ALLOWED_HOSTS en la canalización GitLab CI

Aug 19 2020

Estoy tratando de construir una canalización de GitLab-CI pero Django no parece captar la variable ALLOWED_HOST pasada como variable de entorno.

El proyecto en sí mismo es un proyecto de Django que se ejecuta en un contenedor. Django necesita un valor ALLOWED_HOSTS y SECRET_KEY en su configuración para poder funcionar. Tanto en mi entorno de desarrollo como en mi servidor de producción, las variables se pasan a Django a través de un archivo env.

Ejemplo de configuración de Django:

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

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

Ejemplo de archivo Env:

SECRET_KEY=mydummysecretkey

DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1]

Esto funciona bien en mi desarrollador y en mis máquinas de producción.

Pero cuando trato de ejecutarlo en mi .gitlab-ci.yml, Django no encuentra la variable DJANGO_ALLOWED_HOSTS. Siempre recibí este 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

Esto es bastante extraño porque Django capta bien la variable SECRET_KEY. Como puede ver en el fragmento de código a continuación, incluso hice un eco en la variable que se muestra bien.

FYI: Django se ejecuta en un contenedor Docker y la canalización de CI crea la imagen (y la envía al registro de Gitlab) en el primer trabajo para probarla en el segundo trabajo (e implementarla en el tercer trabajo).

Aquí está mi .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

Aquí está la salida:

$ 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

Respuestas

2 Bravo2bad Aug 20 2020 at 06:35

Recibí mi respuesta gracias a @Zeitounator

Simplemente citaré su comentario para hacerlo simple:

os.environ.getrecupera las variables de entorno del sistema en ejecución, que es su contenedor docker, no del sistema gitlab-ci subyacente. Gitlab CI vars (como sus vars de shell habituales) no se envían automáticamente a su contenedor. SECRET_KEYno emite una advertencia porque es simplemente nulo. DJANGO_ALLOWED_HOSTSlo hace porque tratas de dividirlo. Debe pasar esas variables env a su contenedor, ya sea con la opción -e docker o a través de un archivo env que cree en el acto.

Entonces esto definitivamente funciona:

...

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

...

Terminé con algo como esto:

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