장고 프로젝트를 도커로 배포하며 환경변수가 적용되지 않는 문제를 겪었습니다.
이 상황당시의 배포방식은 docker compose와 docker을 이용하고, 이때 env_file인 web.env를 docker-compose.yml에 명시해주어 파일의 환경변수를 가져와주고, 이를 파이썬에서 os.environ.get()으로 읽어오는 방식이였습니다.
# docker-compose.yml version: "3" services: django: build: . ports: - 80:80 env_file: - web.env volumes: - ./static:/staticfiles command: gunicorn config.wsgi --bind 0.0.0.0:80
# Dockerfile FROM python:3.10 ENV PYTHONUNBUFFERED=0 WORKDIR /web COPY ./requirements.txt /web RUN pip3 install --upgrade pip RUN pip3 install -r requirements.txt COPY . /web RUN python manage.py collectstatic --noinput CMD gunicorn config.wsgi:application --bind 0.0.0.0:80
# settings.py import os SECRET_KEY = os.environ.get("SECRET_KEY", "1234") DEBUG = os.environ.get("DJANGO_DEBUG", "False") == "True" ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS", "*").split(" ")
# web.env DJANGO_DEBUG=False SECRET_KEY=12345 DJANGO_ALLOWED_HOSTS=localhost
위와 같은 상황에서 계속 오류가 발생하고 있었는데, 당시 다음과 같은 문제를 의심해 보았습니다.
- web.env environment file이 제대로 불러와지지 않은 경우, 포맷이 잘못된 경우
- docker 내부에 환경변수가 제대로 들어가지 않은 경우
- python에서 os.environ.get()으로 환경변수를 잘 읽어내지 못하는 경우
당시에 이 3가지를 가정하고 디버깅을 진행했습니다.
.env파일과 도커파일들의 문서를 보며 정확한 서식을 찾아보고, 컨테이너를 빌드해보며, docker-compose와 web.env의 파일의 규칙 문제는 아니라고 확신하고, 계속 문제를 찾아보았습니다.
그러다 우연히 문제를 발견하게 되었습니다.
Step 8/9 : RUN python manage.py collectstatic --noinput ---> Running in 4afbff0af905 Traceback (most recent call last): File "/web/manage.py", line 22, in <module> main() File "/web/manage.py", line 18, in main execute_from_command_line(sys.argv) File "/usr/local/lib/python3.10/site-packages/django/core/management/__init__.py", line 446, in execute_from_command_line utility.execute() File "/usr/local/lib/python3.10/site-packages/django/core/management/__init__.py", line 420, in execute django.setup() File "/usr/local/lib/python3.10/site-packages/django/__init__.py", line 24, in setup apps.populate(settings.INSTALLED_APPS) File "/usr/local/lib/python3.10/site-packages/django/apps/registry.py", line 116, in populate app_config.import_models() File "/usr/local/lib/python3.10/site-packages/django/apps/config.py", line 269, in import_models self.models_module = import_module(models_module_name) File "/usr/local/lib/python3.10/importlib/__init__.py", line 126, in import_module return _bootstrap._gcd_import(name[level:], package, level) File "<frozen importlib._bootstrap>", line 1050, in _gcd_import File "<frozen importlib._bootstrap>", line 1027, in _find_and_load File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked File "<frozen importlib._bootstrap>", line 688, in _load_unlocked File "<frozen importlib._bootstrap_external>", line 883, in exec_module File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed File "/usr/local/lib/python3.10/site-packages/rest_framework_simplejwt/models.py", line 6, in <module> from .settings import api_settings File "/usr/local/lib/python3.10/site-packages/rest_framework_simplejwt/settings.py", line 19, in <module> "SIGNING_KEY": settings.SECRET_KEY, File "/usr/local/lib/python3.10/site-packages/django/conf/__init__.py", line 101, in __getattr__ raise ImproperlyConfigured("The SECRET_KEY setting must not be empty.") django.core.exceptions.ImproperlyConfigured: The SECRET_KEY setting must not be empty. ERROR: Service 'django' failed to build: The command '/bin/sh -c python manage.py collectstatic --noinput' returned a non-zero code: 1
당시 오류 메시지를 보면 다음과 같았는데, 보면 8/9단계인 RUN으로 정적파일을 다루는 부분에서 오류가 난 것을 볼 수 있습니다. 이는 docker-compose.yml에서 넘겨준 환경변수는 최종단계에서는 제대로 전달이 되지만, 빌드단계인 8단계에서는 Docker로 들어가지 않아 collectstatic를 실행할 때는 SECRET_KEY가 지정되지 않아 오류가 나는 것이었습니다.
제대로 오류를 읽어보았다면, 빌드과정에서, 그것도 8단계에서 SECRET_KEY가 없는것의 문제인 것을 금방 알 수 있었을 텐데, 오류 코드를 제대로 읽어보지 않아 많은 시간을 낭비하게 된 경험이었습니다.
이후 해당문제는 django-environ 라이브러리를 사용해 파일에서 바로 환경변수를 읽어오는 방식을 이용하여 해결했습니다.