У меня недавно был похожий случай. Поскольку «ENTRYPOINT» содержит команду, которая будет выполняться при каждом запуске контейнера, решение будет включать в себя некоторые logi c в точке входа . sh сценарий, чтобы избежать применения обновлений (в вашем случае миграция и загрузка данных), если эффекты этих операций уже присутствуют в базе данных.
Например:
#!/bin/bash
set -e
#Function that goes to verify if effects of migration and load data are present on database
function checkEffects() {
IS_UPDATED=0
#Check effects and set to 1 IS_UPDATED if effects are not present
}
checkEffects
if [[ $IS_UPDATED == 0 ]]
then
echo "Database already initialized. Nothing to do"
else
echo "Database is clean. Initializing it"
python manage.py migrate maps
python manage.py loaddata maps/fixtures/country_data.yaml
python manage.py loaddata maps/fixtures/seed_data.yaml
fi
exec "$@"
Однако сценарий более сложный , потому что проверить эффекты, которые позволяют решить, продолжать или нет обновления, может быть довольно сложно, если они включают в себя несколько данных и данных. Более того, это становится очень сложным, если вы думаете об обновлении контейнеров с течением времени.
Пример: Сегодня вы работаете с локальным Dockerfile для своей службы web , но я думаю, что в процессе работы вы начнете создавать версии этой службы для загрузки это в Docker реестре. Поэтому, когда вы загрузите свой первый выпуск (например, 1.0.0 версия ), вы укажите следующее в вашем docker -compose.yml:
web:
restart: always
image: <DOCKER_REGISTRY_HOST>:<DOCKER_REGISTRY_PORT>/web:1.0.0
ports: # to access the container from outside
- "8000:8000"
Затем вы выпустите версию 1.2.0 * контейнера службы web , когда будете вносить другие изменения в схему, например, загружать другие данные в точку входа. sh:
#1.0.0 updates
python manage.py migrate maps
python manage.py loaddata maps/fixtures/country_data.yaml
python manage.py loaddata maps/fixtures/seed_data.yaml
#1.2.0 updates
python manage.py loaddata maps/fixtures/other_seed_data.yaml
Здесь у вас будет 2 сценария ios ( давайте пока проигнорируем необходимость проверять эффекты на сценарии ):
1- Вы впервые развертываете свои сервисы с web: 1.2.0 : начиная с чистой базы данных, вы должны быть уверены, что все обновления выполнены (оба 1.1.0 и 1.2.0 ).
Решение этого случая простое, поскольку вы можете просто выполнить все обновления.
2 - вы обновляете веб-контейнер до 1.2.0 вкл. существующая среда, в которой 1.0.0 работала : поскольку ваша база данных была инициализирована с обновлениями от 1.0.0, вы должны быть уверены, что only 1.2.0 обновления выполняются
Здесь сложно, потому что вы должны иметь возможность проверить, какая версия базы данных применяется, чтобы пропустить обновления 1.0.0. Это означает, что вы должны хранить веб-версию где-нибудь в базе данных, например
Согласно всем этим обсуждениям, поэтому я думаю, что лучшее решение - это работать непосредственно над сценариями, которые идут для создания схемы и заполнения данные, чтобы сделать эти инструкции идемпотентными, обращая внимание на обновления.
Некоторые примеры:
1- Создайте таблицу
Вместо создания таблицы следующим образом:
CREATE TABLE country
используйте , если не существует , чтобы избежать таблица уже существует ошибка:
CREATE TABLE IF NOT EXISTS country
2- Вставьте данные по умолчанию
Вместо этого вставьте данные без указания первичного ключа:
INSERT INTO maps.country (name) VALUES ("USA");
Включите первичный ключ , чтобы избежать дубликатов :
INSERT INTO maps.country (id,name) VALUES (1,"USA");