Передать Django SECRET_KEY в переменной среды Dockerized gunicorn - PullRequest
0 голосов
/ 30 ноября 2018

Некоторый фон

Недавно у меня возникла проблема, когда мое приложение Django использовало файл базовых настроек, несмотря на то, что для DJANGO_SETTINGS_MODULE был установлен другой файл.Оказалось, что проблема заключалась в том, что gunicorn не наследовал переменную среды, и решение было добавить -e DJANGO_SETTINGS_MODULE=sasite.settings.production в мою запись Dockerfile CMD, где я вызываю gunicorn.

Проблема

У меня проблемы с тем, как мне следует обрабатывать SECRET_KEY в моем приложении.Я устанавливаю его в переменной окружения, хотя ранее он хранился в файле JSON, но это казалось менее безопасным (поправьте меня, если я ошибаюсь, пожалуйста).

Другая часть проблемы заключается в том, что при использовании gunicorn он не наследует переменные среды, которые обычно устанавливаются в контейнере.Как я уже говорил выше, я столкнулся с этой проблемой с DJANGO_SETTINGS_MODULE.Я полагаю, что у gunicorn также будет проблема с SECRET_KEY.Как это обойти?

Мой текущий подход

Я установил SECRET_KEY в переменной окружения и загрузил его в файл настроек django.Я устанавливаю значение в файле "app-env", который содержит export SECRET_KEY=<secretkey>, Dockerfile содержит RUN source app-env, чтобы установить переменную среды в контейнере.

Последующие вопросы

Было бы лучше установить переменную среды SECRET_KEY с помощью команды Dockerfile ENV вместо поиска файла?Является ли приемлемой практика жестко кодировать секретный ключ в Dockerfile, как этот (кажется, что это не для меня)?

Существует ли "лучший метод" для обработки секретных ключей в Dockerized-приложениях?

Я всегда могу вернуться к JSON, если он окажется таким же безопасным, как переменные среды.Но все равно было бы неплохо выяснить, как люди решают проблему SECRET_KEY и gunicorn с переменными окружения.

Код

Вот файл Docker:

FROM python:3.6
LABEL maintainer x@x.com

ARG requirements=requirements/production.txt
ENV DJANGO_SETTINGS_MODULE=sasite.settings.production_test

WORKDIR /app

COPY manage.py /app/
COPY requirements/ /app/requirements/ 

RUN pip install -r $requirements

COPY config config
COPY sasite sasite
COPY templates templates
COPY logs logs
COPY scripts scripts

RUN source app-env

EXPOSE 8001

CMD ["/usr/local/bin/gunicorn", "--config", "config/gunicorn.conf", "--log-config", "config/logging.conf", "-e", "DJANGO_SETTINGS_MODULE=sasite.settings.production_test", "-w", "4", "-b", "0.0.0.0:8001", "sasite.wsgi:application"]

1 Ответ

0 голосов
/ 01 декабря 2018

Я начну с того, почему он не работает как есть, а затем обсудим варианты, которые необходимо продвинуть вперед:

В процессе сборки контейнера выполняется одна инструкция RUN в качестве егособственный автономный контейнер.Только изменения в файловой системе слоя записи этого контейнера фиксируются для последующих слоев.Это означает, что ваша команда source app-env запускается и завершается, и, вероятно, не вносит изменений на диск, что делает эту строку RUN запретной.

Docker позволяет вам задавать переменные среды во время сборки, используя инструкцию ENV, котораявы сделали с переменной DJANGO_SETTINGS_MODULE.Я не обязательно согласен с тем, что здесь должен быть указан SECRET_KEY, хотя, возможно, было бы неплохо поместить значение, необходимое для разработки, в Dockerfile.


Поскольку переменная SECRET_KEY может отличаться для разных сред(постановка и производство), тогда может иметь смысл установить эту переменную во время выполнения.Например:

docker run -d -e SECRET_KEY=supersecretkey mydjangoproject

Параметр -e является коротким для --env.Кроме того, есть --env-file, и вы можете передать файл переменных и значений.Если вы не используете docker cli напрямую, тогда ваш докер-клиент должен также иметь возможность указать их там (например, docker-compose позволяет вам указать оба из них в yaml)


В этом конкретном случае, поскольку у вас есть внутри контейнера, который знает, какие переменные необходимы, вы можете вызвать это во время выполнения.Есть два способа сделать это.Во-первых, измените CMD следующим образом:

CMD source app-env && /usr/local/bin/gunicorn --config config/gunicorn.conf --log-config config/logging.conf -e DJANGO_SETTINGS_MODULE=sasite.settings.production_test -w 4 -b 0.0.0.0:8001 sasite.wsgi:application

При этом используется синтаксис оболочки CMD, а не синтаксис exec.Это означает, что весь аргумент CMD будет запущен внутри / bin / sh -c ""

Оболочка будет обрабатывать выполнение source app-env и затем вашу команду gunicorn.

Если вам когда-либо понадобитсячтобы изменить команду во время выполнения, вам нужно не забыть указать source app-env &&, где это необходимо, что подводит меня к другому подходу, а именно к использованию сценария ENTRYPOINT


функции ENTRYPOINT в Dockerпозволяет обрабатывать любые необходимые шаги запуска внутри контейнера при его первом запуске.Рассмотрим следующий сценарий точки входа:

#!/bin/bash
cd /app && source app-env && cd - && exec "$@"

Это явным образом перейдет к месту, где находится app-env, найдет его, вернется к тому, что было oldpwd, и затем выполнит команду.Теперь вы можете переопределить командный и рабочий каталог во время выполнения для этого образа и иметь любые переменные, указанные в файле app-env, чтобы быть активными.Чтобы использовать этот сценарий, вам нужно добавить его где-нибудь в образе и убедиться, что он исполняемый, а затем указать его в Dockerfile с помощью директивы ENTRYPOINT:

ADD entrypoint.sh /entrypoint.sh
RUN chmod a+x /entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]

С помощью стратегии точки входа вы можете оставитьваш CMD без изменений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...