Il contenitore docker di Django non rileva la variabile di ambiente ALLOWED_HOSTS nella pipeline CI di GitLab

Aug 19 2020

Sto cercando di creare una pipeline GitLab-CI ma Django non sembra catturare la variabile ALLOWED_HOST passata come variabile di ambiente.

Il progetto stesso è un progetto Django in esecuzione in un contenitore. Django ha bisogno di un ALLOWED_HOSTS e di un valore SECRET_KEY nelle sue impostazioni per funzionare. Sul mio ambiente di sviluppo e sul mio server di produzione, le variabili vengono passate a Django tramite un file env.

Esempio di impostazioni di Django:

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

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

Esempio di file Env:

SECRET_KEY=mydummysecretkey

DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1]

Funziona bene sul mio dev e sulle mie macchine di produzione.

Ma quando provo a eseguirlo nel mio .gitlab-ci.yml, Django non trova la variabile DJANGO_ALLOWED_HOSTS. Ho sempre avuto questo errore:

$ 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

Questo è abbastanza strano perché Django cattura bene la variabile SECRET_KEY. Come puoi vedere nel frammento di codice qui sotto, ho anche fatto un'eco sulla variabile che è ben visualizzata.

Cordiali saluti: Django è in esecuzione in un contenitore Docker e la pipeline CI crea l'immagine (e la invia al registro Gitlab) sul primo lavoro per testarla sul secondo lavoro (e distribuirla sul terzo lavoro).

Ecco il mio .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

Ecco l'output:

$ 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

Risposte

2 Bravo2bad Aug 20 2020 at 06:35

Ho avuto la mia risposta grazie a @Zeitounator

Citerò semplicemente il suo commento per renderlo semplice:

os.environ.getrecupera le variabili di ambiente dal sistema in esecuzione che è il tuo contenitore docker, non dal sistema gitlab-ci sottostante. Gitlab CI vars (come le tue solite shell vars) non vengono inviate automaticamente al tuo contenitore. SECRET_KEYnon emette un avviso perché è semplicemente nullo. DJANGO_ALLOWED_HOSTSfa perché provi a dividerlo. Devi passare quelle variabili env al tuo contenitore, con l'opzione -e docker o tramite un file env che crei sul posto.

Quindi questo funziona sicuramente:

...

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

...

Ho finito con qualcosa del genere:

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