Я начну с того, почему он не работает как есть, а затем обсудим варианты, которые необходимо продвинуть вперед:
В процессе сборки контейнера выполняется одна инструкция 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 без изменений.