Docker 编写 postgresql 服务 - 无法在构建期间创建用户和数据库?
Docker compose postgresql service - can't create user and database during build?
我已经在这上面浪费了一整天,而且说我对本应是一项简单任务的不必要的复杂性没有印象 - 这是一种严重的轻描淡写。
好的,说完这些,我正在使用 docker-machine、docker-compose、postgresql 和 redis 构建一个 django 应用程序 - 按照 this tutorial.
我已经设法让基本教程开始工作 - 但它不符合我的需要,因为我需要为我的应用程序创建一个用户和一个数据库 - 而不是对两者都使用 'postgres'。
我使用了@dnephin 的回答,并修改了我的代码如下:
我在新目录中创建了一个新的 Dockerfile ./database/
:
FROM postgres:9.6
COPY . /fixtures
WORKDIR /fixtures
RUN /fixtures/setup.sh
./database/setup.sh
内容:
#!/bin/bash
set -e
pg_createcluster 9.6 main --start
/etc/init.d/postgresql start
su - postgres # makes no effing difference ...
psql -f create_fixtures.sql
/etc/init.d/postgresql stop
./database/create_fixtures.sql
内容:
CREATE DATABASE mydatabase WITH ENCODING 'UTF8';
CREATE USER webuser ENCRYPTED PASSWORD 'deadbeefsnaf0' NOSUPERUSER NOCREATEDB NOCREATEROLE;
GRANT ALL PRIVILEGES ON mydatabase TO webuser;
最后我在 docker_compose.yml 中的 postgres 服务被修改为使用 build:
postgres:
build: ./database/
...
当我 运行 docker-compose build
时,构建通过动作然后 barfs 在我导入 SQL 固定装置的地方文件通过 psql:
frothing@themouth:~/path/to/directory$ docker-compose build
redis uses an image, skipping
Building postgres
Step 1/4 : FROM postgres:9.6
---> ff0943ecbb3c
Step 2/4 : COPY . /fixtures
---> fae19dc88da8
Removing intermediate container 84b860aee55c
Step 3/4 : WORKDIR /fixtures
---> aa88438dc69f
Removing intermediate container b801ddc3b374
Step 4/4 : RUN /fixtures/setup.sh
---> Running in ca3e89ec2460
Creating new cluster 9.6/main ...
config /etc/postgresql/9.6/main
data /var/lib/postgresql/9.6/main
locale en_US.utf8
socket /var/run/postgresql
port 5432
Starting PostgreSQL 9.6 database server: main.
psql: FATAL: role "root" does not exist
ERROR: Service 'postgres' failed to build: The command '/bin/sh -c /fixtures/setup.sh' returned a non-zero code: 2
我尝试使用 useless documentation on docker for postgresql service 解决这个问题 - 但没有找到答案。
我该如何解决?
试试这个 setup.sh
#!/bin/bash
set -e
pg_createcluster 9.6 main --start
su postgres sh -c "/etc/init.d/postgresql start && psql -f create_fixtures.sql && /etc/init.d/postgresql stop"
在 运行 psql:
时尝试显式用户
psql -U postgres -f create_fixtures.sql
官方postgresql docker镜像会在容器第一次启动时自动导入脚本。因此,如果您使用 init sql 脚本将目录挂载到容器路径 '/docker-entrypoint-initdb.d/' 它应该是 运行.
例如,如果您有导入脚本 myImport.sql 并且它在主机上的目录 /opt/import 中,您可以将容器启动上的导入目录挂载到您的 postgres 映像到 /docker-entrypoint-initdb.d 和 sql 文件将在初始数据库设置后执行。
docker run -p $toHostParam:5432 -e POSTGRES_PASSWORD="$dbPwd" \
-e POSTGRES_USER="$dbUser" \
-e POSTGRES_DB="$dbName" \
-e PGDATA=/opt/pgdata \
-v ${dataDir}:/opt/pgdata \
# look here
# mount of local import dir
-v /opt/import:/docker-entrypoint-initdb.d \
postgres:9.6
在此处查看 postgesql 图像启动脚本(来自第 126 行):
https://github.com/docker-library/postgres/blob/master/9.6/docker-entrypoint.sh
如果您想要特定的数据库用户或数据库,您还可以使用环境变量自定义您的 postgresql 容器。
看看这里的 'Environment Variables' 部分:https://hub.docker.com/_/postgres/
卷在构建时不可用。您可以在脚本中创建 /var/lib/postgresql/data
,但它会被来自 postgres:9.6
图片的 VOLUME /var/lib/postgresql/data
覆盖。
对于您的情况:只需使用以下 docker 文件:
FROM postgres:9.6
COPY ./create_fixtures.sql /docker-entrypoint-initdb.d/create_fixtures.sql
它们会在容器启动后自动执行。这是一个例子:
$ docker run -d --name mydb -p 33306:3306 yourtag
$ docker exec -ti mydb psql -U postgres
postgres=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
------------+----------+----------+------------+------------+-----------------------
mydatabase | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =Tc/postgres +
| | | | | postgres=CTc/postgres+
| | | | | webuser=CTc/postgres
postgres | postgres | UTF8 | en_US.utf8 | en_US.utf8 |
template0 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres +
| | | | | postgres=CTc/postgres
(4 rows)
过时的答案:
你的脚本应该可以在容器上工作除了在夹具中你必须像这样执行psql:
su postgres -c "psql -f create_fixtures.sql"
su --login postgres
不起作用,因为 postgres 无法打开 bash 或 shell。您可以尝试使用 docker run --rm -ti postgres:9.6 bash
.
抱歉,我必须告诉您 sql 脚本中还有一个错误:GRANT ALL PRIVILEGES ON DATABASE mydatabase TO webuser
- 此处需要关键字 DATABASE
。
这是一个完整的日志,我是如何测试并确认它有效的:
docker run --rm -ti postgres:9.6 bash
root@be03ab1eb704:/# cat > test.sql <<EOF
> CREATE DATABASE mydatabase WITH ENCODING 'UTF8';
> CREATE USER webuser ENCRYPTED PASSWORD 'asdf123' NOSUPERUSER NOCREATEDB NOCREATEROLE;
> GRANT ALL PRIVILEGES ON DATABASE mydatabase TO webuser;
> EOF
root@be03ab1eb704:/# pg_createcluster 9.6 main --start
Creating new PostgreSQL cluster 9.6/main ...
/usr/lib/postgresql/9.6/bin/initdb -D /var/lib/postgresql/9.6/main --auth-local peer --auth-host md5
The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.
The database cluster will be initialized with locale "en_US.utf8".
The default database encoding has accordingly been set to "UTF8".
The default text search configuration will be set to "english".
Data page checksums are disabled.
fixing permissions on existing directory /var/lib/postgresql/9.6/main ... ok
creating subdirectories ... ok
selecting default max_connections ... 100
selecting default shared_buffers ... 128MB
selecting dynamic shared memory implementation ... posix
creating configuration files ... ok
running bootstrap script ... ok
performing post-bootstrap initialization ... ok
syncing data to disk ... ok
Success. You can now start the database server using:
/usr/lib/postgresql/9.6/bin/pg_ctl -D /var/lib/postgresql/9.6/main -l logfile start
Ver Cluster Port Status Owner Data directory Log file
9.6 main 5432 online postgres /var/lib/postgresql/9.6/main /var/log/postgresql/postgresql-9.6-main.log
root@be03ab1eb704:/# /etc/init.d/postgresql start
[ ok ] Starting PostgreSQL 9.6 database server: main.
root@be03ab1eb704:/# su postgres -c "psql -f test.sql"
CREATE DATABASE
CREATE ROLE
GRANT
root@be03ab1eb704:/# /etc/init.d/postgresql stop
[ ok ] Stopping PostgreSQL 9.6 database server: main.
root@be03ab1eb704:/# exit
exit
我已经在这上面浪费了一整天,而且说我对本应是一项简单任务的不必要的复杂性没有印象 - 这是一种严重的轻描淡写。
好的,说完这些,我正在使用 docker-machine、docker-compose、postgresql 和 redis 构建一个 django 应用程序 - 按照 this tutorial.
我已经设法让基本教程开始工作 - 但它不符合我的需要,因为我需要为我的应用程序创建一个用户和一个数据库 - 而不是对两者都使用 'postgres'。
我使用了@dnephin 的回答
我在新目录中创建了一个新的 Dockerfile ./database/
:
FROM postgres:9.6
COPY . /fixtures
WORKDIR /fixtures
RUN /fixtures/setup.sh
./database/setup.sh
内容:
#!/bin/bash
set -e
pg_createcluster 9.6 main --start
/etc/init.d/postgresql start
su - postgres # makes no effing difference ...
psql -f create_fixtures.sql
/etc/init.d/postgresql stop
./database/create_fixtures.sql
内容:
CREATE DATABASE mydatabase WITH ENCODING 'UTF8';
CREATE USER webuser ENCRYPTED PASSWORD 'deadbeefsnaf0' NOSUPERUSER NOCREATEDB NOCREATEROLE;
GRANT ALL PRIVILEGES ON mydatabase TO webuser;
最后我在 docker_compose.yml 中的 postgres 服务被修改为使用 build:
postgres:
build: ./database/
...
当我 运行 docker-compose build
时,构建通过动作然后 barfs 在我导入 SQL 固定装置的地方文件通过 psql:
frothing@themouth:~/path/to/directory$ docker-compose build
redis uses an image, skipping
Building postgres
Step 1/4 : FROM postgres:9.6
---> ff0943ecbb3c
Step 2/4 : COPY . /fixtures
---> fae19dc88da8
Removing intermediate container 84b860aee55c
Step 3/4 : WORKDIR /fixtures
---> aa88438dc69f
Removing intermediate container b801ddc3b374
Step 4/4 : RUN /fixtures/setup.sh
---> Running in ca3e89ec2460
Creating new cluster 9.6/main ...
config /etc/postgresql/9.6/main
data /var/lib/postgresql/9.6/main
locale en_US.utf8
socket /var/run/postgresql
port 5432
Starting PostgreSQL 9.6 database server: main.
psql: FATAL: role "root" does not exist
ERROR: Service 'postgres' failed to build: The command '/bin/sh -c /fixtures/setup.sh' returned a non-zero code: 2
我尝试使用 useless documentation on docker for postgresql service 解决这个问题 - 但没有找到答案。
我该如何解决?
试试这个 setup.sh
#!/bin/bash
set -e
pg_createcluster 9.6 main --start
su postgres sh -c "/etc/init.d/postgresql start && psql -f create_fixtures.sql && /etc/init.d/postgresql stop"
在 运行 psql:
时尝试显式用户psql -U postgres -f create_fixtures.sql
官方postgresql docker镜像会在容器第一次启动时自动导入脚本。因此,如果您使用 init sql 脚本将目录挂载到容器路径 '/docker-entrypoint-initdb.d/' 它应该是 运行.
例如,如果您有导入脚本 myImport.sql 并且它在主机上的目录 /opt/import 中,您可以将容器启动上的导入目录挂载到您的 postgres 映像到 /docker-entrypoint-initdb.d 和 sql 文件将在初始数据库设置后执行。
docker run -p $toHostParam:5432 -e POSTGRES_PASSWORD="$dbPwd" \
-e POSTGRES_USER="$dbUser" \
-e POSTGRES_DB="$dbName" \
-e PGDATA=/opt/pgdata \
-v ${dataDir}:/opt/pgdata \
# look here
# mount of local import dir
-v /opt/import:/docker-entrypoint-initdb.d \
postgres:9.6
在此处查看 postgesql 图像启动脚本(来自第 126 行): https://github.com/docker-library/postgres/blob/master/9.6/docker-entrypoint.sh
如果您想要特定的数据库用户或数据库,您还可以使用环境变量自定义您的 postgresql 容器。
看看这里的 'Environment Variables' 部分:https://hub.docker.com/_/postgres/
卷在构建时不可用。您可以在脚本中创建 /var/lib/postgresql/data
,但它会被来自 postgres:9.6
图片的 VOLUME /var/lib/postgresql/data
覆盖。
对于您的情况:只需使用以下 docker 文件:
FROM postgres:9.6
COPY ./create_fixtures.sql /docker-entrypoint-initdb.d/create_fixtures.sql
它们会在容器启动后自动执行。这是一个例子:
$ docker run -d --name mydb -p 33306:3306 yourtag
$ docker exec -ti mydb psql -U postgres
postgres=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
------------+----------+----------+------------+------------+-----------------------
mydatabase | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =Tc/postgres +
| | | | | postgres=CTc/postgres+
| | | | | webuser=CTc/postgres
postgres | postgres | UTF8 | en_US.utf8 | en_US.utf8 |
template0 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres +
| | | | | postgres=CTc/postgres
(4 rows)
过时的答案:
你的脚本应该可以在容器上工作除了在夹具中你必须像这样执行psql:
su postgres -c "psql -f create_fixtures.sql"
su --login postgres
不起作用,因为 postgres 无法打开 bash 或 shell。您可以尝试使用 docker run --rm -ti postgres:9.6 bash
.
抱歉,我必须告诉您 sql 脚本中还有一个错误:GRANT ALL PRIVILEGES ON DATABASE mydatabase TO webuser
- 此处需要关键字 DATABASE
。
这是一个完整的日志,我是如何测试并确认它有效的:
docker run --rm -ti postgres:9.6 bash
root@be03ab1eb704:/# cat > test.sql <<EOF
> CREATE DATABASE mydatabase WITH ENCODING 'UTF8';
> CREATE USER webuser ENCRYPTED PASSWORD 'asdf123' NOSUPERUSER NOCREATEDB NOCREATEROLE;
> GRANT ALL PRIVILEGES ON DATABASE mydatabase TO webuser;
> EOF
root@be03ab1eb704:/# pg_createcluster 9.6 main --start
Creating new PostgreSQL cluster 9.6/main ...
/usr/lib/postgresql/9.6/bin/initdb -D /var/lib/postgresql/9.6/main --auth-local peer --auth-host md5
The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.
The database cluster will be initialized with locale "en_US.utf8".
The default database encoding has accordingly been set to "UTF8".
The default text search configuration will be set to "english".
Data page checksums are disabled.
fixing permissions on existing directory /var/lib/postgresql/9.6/main ... ok
creating subdirectories ... ok
selecting default max_connections ... 100
selecting default shared_buffers ... 128MB
selecting dynamic shared memory implementation ... posix
creating configuration files ... ok
running bootstrap script ... ok
performing post-bootstrap initialization ... ok
syncing data to disk ... ok
Success. You can now start the database server using:
/usr/lib/postgresql/9.6/bin/pg_ctl -D /var/lib/postgresql/9.6/main -l logfile start
Ver Cluster Port Status Owner Data directory Log file
9.6 main 5432 online postgres /var/lib/postgresql/9.6/main /var/log/postgresql/postgresql-9.6-main.log
root@be03ab1eb704:/# /etc/init.d/postgresql start
[ ok ] Starting PostgreSQL 9.6 database server: main.
root@be03ab1eb704:/# su postgres -c "psql -f test.sql"
CREATE DATABASE
CREATE ROLE
GRANT
root@be03ab1eb704:/# /etc/init.d/postgresql stop
[ ok ] Stopping PostgreSQL 9.6 database server: main.
root@be03ab1eb704:/# exit
exit