Gitlab CI一直忽略this project中/docker-entrypoint-initdb.d/*
中的sql文件。
这是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"
所有这些goes well,但是当容器启动时,应该运行/docker-entrypoint-initdb.d/*
中的所有文件,就像我们看到的here一样。
但是,相反,在服务器上执行docker logs -f lbsn-testdb
时,我可以看到它说明了
/usr/local/bin/docker-entrypoint.sh: ignoring /docker-entrypoint-initdb.d/*
我不知道为什么会这样。当在本地运行此容器时,甚至当我ssh到该服务器时,克隆存储库并手动启动容器,一切都会顺利进行并解析sql文件。只是在Gitlab CI这样做的时候不是。
关于这是为什么的任何想法?
答案 0 :(得分:1)
这比我预期的要容易,致命的是与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用户拥有这些文件,显然,这些文件也由容器中ID为1005的某个用户拥有,并且除此文件外,其他用户均未获得任何权限。
虽然在容器内执行操作的用户是postgres
,但无法读取这些文件。它没有抱怨,而是忽略了它们。这可能会引起有关……的问题
Now that I pass --chmod=D755,F644
看起来像这样:
-rw-r--r-- 1 1005 1004 314 May 8 15:48 100-create-database.sql
和docker日志说
/usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/100-create-database.sql
太容易想到了:-/
答案 1 :(得分:0)
我发现本主题发现使用docker-compose工具安装PostgreSQL时存在类似问题。
解决方案基本相同。对于提供的配置:
version: '3.6'
services:
testdb:
image: postgres:11
container_name: lbsn-testdb
restart: always
ports:
- "65432:5432"
volumes:
- ./testdb/init:/docker-entrypoint-initdb.d
您的部署脚本应为您的postgres容器卷设置0755权限,在这种情况下,例如chmod -R 0755 ./testdb
。使所有子目录可见是很重要的,因此需要chmod -R
选项。
官方Postgres映像在内部Postgres用户下以UID 70运行。主机中的应用程序用户很可能具有不同的UID,例如1000或类似名称。这就是postgres初始化脚本由于权限错误而错过安装步骤的原因。这个问题出现了好几年,但是在最新的PostgreSQL版本中仍然存在(当前是12.1)
在读取系统中所有初始化文件时,请注意安全漏洞。最好使用shell环境变量将机密传递到初始化脚本。
这是一个docker-compose示例:
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"
答案 2 :(得分:0)
如果您之前已经运行过postgres服务,则在重新启动该文件时会忽略其初始化文件,因此请尝试使用--build
重新构建映像
docker-compose up --build -d
,然后再次运行:
使用以下命令检查现有卷
docker volume ls
然后删除用于pg服务的那个
docker volume rm {volume_name}
->确保该容器未使用该卷,如果是,则也将其删除