#bash #docker #docker-compose
#bash #docker #docker-compose
Вопрос:
У меня есть сценарий развертывания, который я пытаюсь использовать для своего сервера на компакт-диске, но я сталкиваюсь с проблемами при написании сценария bash для выполнения некоторых необходимых шагов, таких как запуск npm и команды миграции.
Как бы я мог попасть в контейнер bash из этого скрипта, выполнить приведенные ниже команды, а затем выйти, чтобы завершить внесение изменений?
Вот сценарий, который я пытаюсь автоматизировать:
cd /Project
docker-compose -f docker-compose.prod.yml down
git pull
docker-compose -f docker-compose.prod.yml build
# all good until here because it opens bash and does not allow more commands to run
docker-compose -f docker-compose.prod.yml run --rm web bash
npm install # should be run inside of web bash
python manage.py migrate_all # should be run inside of web bash
exit # should be run inside of web bash
# back out of web bash
docker-compose -f docker-compose.prod.yml up -d
Комментарии:
1. Вы можете достаточно легко запустить bash в контейнер (
exec -it
), но тогда вам потребуется иметь оболочку bash в контейнере, из которой вы могли бы продолжать запускать скрипты. Почему вы просто не выполняете установку из файла Dockerfile?2. Вы вообще этого не делаете. Запустите
npm install
в своем Dockerfile, чтобы образ содержал правильное дерево библиотек. (И если выdocker-compose.yml
монтируете тома поверх исходного дерева образа, удалите это.) Вы можетеdocker-compose run
создать отдельный контейнер для выполнения миграции. Вы можете отложить запускdocker-compose down
доdocker-compose build
завершения.
Ответ №1:
Обычно образ Docker является автономным и знает, как запустить себя без какого-либо вмешательства пользователя. За некоторыми ограниченными исключениями вам никогда не понадобятся docker-compose run
интерактивные оболочки для выполнения настройки после развертывания, и docker exec
их следует зарезервировать для экстренной отладки.
В этом скрипте вы делаете две вещи.
Первым делом необходимо установить пакеты узлов. Они должны быть инкапсулированы в ваш образ; ваш Dockerfile почти всегда будет выглядеть примерно так
FROM node
WORKDIR /app
COPY package*.json .
RUN npm ci # <--- this line
COPY . .
CMD ["node", "index.js"]
Поскольку зависимости находятся в вашем образе, вам не нужно переустанавливать их при запуске образа. И наоборот, если вы измените свой package.json
файл, повторный запуск docker-compose build
приведет к повторному запуску npm install
шага, и вы получите чистое дерево пакетов.
(Существует несколько распространенных настроек, которые помещают node_modules
каталог в анонимный том и перезаписывают код образа с помощью привязки. Если вы обновите свой образ, он получит старый node_modules
каталог из анонимного тома и проигнорирует обновления образа. Удалите их volumes:
и используйте код, встроенный в образ.)
Миграции базы данных немного сложнее, поскольку вы не можете запускать их на этапе сборки образа. Для этого есть два хороших подхода. Один из них заключается в том, чтобы всегда запускать миграции контейнера при запуске. Вы можете использовать сценарий точки входа, например:
#!/bin/sh
python manage.py migrate_all
exec "$@"
Сделайте этот скрипт исполняемым и сделайте его изображением ENTRYPOINT
, оставив CMD
команду для фактического запуска приложения. При каждом запуске контейнера он будет запускать миграции, а затем запускать основную команду контейнера, какой бы она ни была.
Этот подход не обязательно хорошо работает, если у вас есть несколько реплик контейнера (особенно в кластерной среде, такой как Docker Swarm или Kubernetes) или если вам когда-нибудь понадобится понизить рейтинг. В этих случаях может иметь смысл вручную запускать миграции вручную. Вы можете сделать это отдельно от основного жизненного цикла контейнера с помощью
docker-compose run web
python manage.py migrate_all
Наконец, с точки зрения жизненного цикла, который вы описываете, образы Docker неизменяемы: это означает, что безопасно перестраивать новые образы, пока работают старые. Описанный вами подход к последовательности обновления с минимальным временем простоя может выглядеть следующим образом:
git pull
# Build new images (includes `npm install`)
docker-compose build
# Run migrations (if required)
docker-compose run web python manage.py migrate_all
# Restart all containers
docker-compose up --force-recreate
Комментарии:
1. Интересно, что, поскольку я использую webpack, запуск
npm run build
изменил мой файл webpack-stats.json, поэтому, несмотря на то, что контейнер был собран и заменен, до завершения сборки было 500 ошибок… При этом, естественно, ваше решение было вынужденным, чтобы я мог правильно автоматизировать сборки. Глядя сейчас, это то, что я всегда должен был делать, спасибо!