Gitlab CI продолжает игнорировать sql-файлы в /docker-entrypoint-initdb.d/* в этот проект.
вот docker-compose.yml:
version: '3.6'
services:
testdb:
image: postgres:11
container_name: lbsn-testdb
restart: always
ports:
- "65432:5432"
volumes:
- ./testdb/init:/docker-entrypoint-initdb.d
вот .gitlab-ci.yml:
stages:
- deploy
deploy:
stage: deploy
image: debian:stable-slim
script:
- bash ./deploy.sh
Сценарий развертывания в основном использует rsync для развертывания содержимого репозитория на сервере через SSH:
rsync -rav --chmod=Du+rwx,Dgo-rwx,u+rw,go-rw -e "ssh -l gitlab-ci" --exclude = ".git" --delete ./ "gitlab-ci@$DEPLOY_SERVER:test/"
а затем ssh на сервер, чтобы остановить и перезапустить контейнер:
ssh "gitlab-ci@$DEPLOY_SERVER" "cd test && docker-compose down && docker-compose up --build --detach"
Это все идет хорошо, но когда контейнер запускается, он должен запускать все файлы, которые находятся в /docker-entrypoint-initdb.d/* как мы видим здесь.
Но вместо этого, когда я делаю docker logs -f lbsn-testdb на сервере, я вижу, что это говорит
/usr/local/bin/docker-entrypoint.sh: ignoring /docker-entrypoint-initdb.d/*
и я понятия не имею, почему это происходит. При локальном запуске этого контейнера или даже когда я подключаюсь к этому серверу по ssh, клонирую репо и поднимаю контейнеры вручную, все идет хорошо и анализирует sql-файлы. Только не тогда, когда это делает Gitlab CI.
Любые идеи о том, почему это так?
да, это действительно есть
Вы проверили, есть ли еще тома, запустив docker volume ls? Если да, то попробуйте их удалить (если там, конечно, нет ничего важного — если это так, просто переименуйте сервис в docker-compose.yml). Если это поможет, попробуйте изменить docker-compose down в своем скрипте на docker-compose down -v.
Кроме того, есть ли конкретная причина, по которой вы добавили --build к своей команде? Вы не указали ни одной части сборки в своем docker-compose.yml, так что...
извините, параметр --build был остатком от разбивки этого на минимальный пример. Но это не то, что пошло не так, а что-то действительно глупое, см. мой собственный ответ.
Итак, одно замечание: расширение вашего файла должно быть .sql, а не каким-либо другим, например .ddl. Посмотрите ссылку @bellackn, отправленную, чтобы понять, почему.





Это оказалось проще, чем я ожидал, и совершенно не связано с Gitlab CI, кроме прав доступа к файлам.
Я передал --chmod=Du+rwx,Dgo-rwx,u+rw,go-rw на rsync, что выглядело действительно безопасным, потому что только пользователь может что-то делать. Признаюсь, что я, вероятно, скопировал его откуда-то из Интернета. Но затем файлы монтируются в контейнер Docker, и там у них тоже есть такие разрешения:
-rw------- 1 1005 1004 314 May 8 15:48 100-create-database.sql
На хосте мой пользователь gitlab-ci владеет этими файлами, они, очевидно, также принадлежат какому-то пользователю с идентификатором 1005 в контейнере, и другим пользователям не даются разрешения, кроме этого.
Внутри контейнера пользователь, который что-то делает, находится postgres, но он не может читать эти файлы. Вместо того, чтобы жаловаться на это, он просто игнорирует их. Это может быть что-то, чтобы создать проблему о…
Теперь, когда я прохожу--chmod=D755,F644 выглядит так:
-rw-r--r-- 1 1005 1004 314 May 8 15:48 100-create-database.sql
и журналы докера говорят
/usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/100-create-database.sql
Слишком легко думать в первую очередь :-/
Я нашел эту тему, обнаружив аналогичную проблему с установкой PostgreSQL с помощью инструмента docker-compose.
Решение в основном такое же. Для предоставленной конфигурации:
version: '3.6'
services:
testdb:
image: postgres:11
container_name: lbsn-testdb
restart: always
ports:
- "65432:5432"
volumes:
- ./testdb/init:/docker-entrypoint-initdb.d
Ваш сценарий развертывания должен установить разрешения 0755 для тома контейнера postgres, например chmod -R 0755 ./testdb в этом случае. Важно сделать видимыми все подкаталоги, поэтому требуется опция chmod -R.
Официальный образ Postgres работает под внутренним пользователем postgres с UID 70. Пользователь вашего приложения на хосте, скорее всего, имеет другой UID, например 1000 или что-то подобное. Это причина того, что скрипт инициализации postgres пропускает этапы установки из-за ошибки прав доступа. Эта проблема возникает уже несколько лет, но все еще существует в последней версии PostgreSQL (в настоящее время 12.1).
Имейте в виду уязвимость системы безопасности, когда все файлы инициализации в системе доступны для чтения. Хорошо использовать переменные среды оболочки для передачи секретов в сценарий инициализации.
Вот пример создания докера:
postgres:
image: postgres:12.1-alpine
container_name: app-postgres
environment:
- POSTGRES_USER
- POSTGRES_PASSWORD
- APP_POSTGRES_DB
- APP_POSTGRES_SCHEMA
- APP_POSTGRES_USER
- APP_POSTGRES_PASSWORD
ports:
- '5432:5432'
volumes:
- $HOME/app/conf/postgres:/docker-entrypoint-initdb.d
- $HOME/data/postgres:/var/lib/postgresql/data
Соответствующий скрипт create-users.sh для создания пользователей может выглядеть так:
#!/bin/bash
set -o nounset
set -o errexit
set -o pipefail
POSTGRES_USER = "${POSTGRES_USER:-postgres}"
POSTGRES_PASSWORD = "${POSTGRES_PASSWORD}"
APP_POSTGRES_DB = "${APP_POSTGRES_DB:-app}"
APP_POSTGRES_SCHEMA = "${APP_POSTGRES_SCHEMA:-app}"
APP_POSTGRES_USER = "${APP_POSTGRES_USER:-appuser}"
APP_POSTGRES_PASSWORD = "${APP_POSTGRES_PASSWORD:-app}"
DATABASE = "${APP_POSTGRES_DB}"
# Create single database.
psql --variable ON_ERROR_STOP=1 --username "${POSTGRES_USER}" --command "CREATE DATABASE ${DATABASE}"
# Create app user.
psql --variable ON_ERROR_STOP=1 --username "${POSTGRES_USER}" --command "CREATE USER ${APP_POSTGRES_USER} SUPERUSER PASSWORD '${APP_POSTGRES_PASSWORD}'"
psql --variable ON_ERROR_STOP=1 --username "${POSTGRES_USER}" --command "GRANT ALL PRIVILEGES ON DATABASE ${DATABASE} TO ${APP_POSTGRES_USER}"
psql --variable ON_ERROR_STOP=1 --username "${POSTGRES_USER}" --dbname "${DATABASE}" --command "CREATE SCHEMA ${APP_POSTGRES_SCHEMA} AUTHORIZATION ${APP_POSTGRES_USER}"
psql --variable ON_ERROR_STOP=1 --username "${POSTGRES_USER}" --command "ALTER USER ${APP_POSTGRES_USER} SET search_path = ${APP_POSTGRES_SCHEMA},public"
Если вы уже запускали службу postgres ранее, файлы инициализации будут игнорироваться при ее перезапуске, поэтому попробуйте использовать --build для повторной сборки образа.
docker-compose up --build -d
и прежде чем снова бежать:
Проверьте существующие тома с помощью
docker volume ls
Затем удалите тот, который вы используете для службы pg, с помощью
docker volume rm {volume_name}
-> Убедитесь, что том не используется контейнером, если да, то удалите и контейнер.
Странно, но вот мой снимок в темноте: Эта линия указывает, что, похоже, нет файла, который можно было бы запустить. Не могли бы вы добавить что-то вроде
docker exec your_db_container ls -l /docker-entrypoint-initdb.d/в свою конфигурацию CI, просто чтобы убедиться, что файл SQL действительно существует?