Сборка / развертывание Docker с использованием Bash-скрипта

#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 ошибок… При этом, естественно, ваше решение было вынужденным, чтобы я мог правильно автоматизировать сборки. Глядя сейчас, это то, что я всегда должен был делать, спасибо!