【问题标题】:Docker compose postgresql service - can't create user and database during build?Docker compose postgresql 服务 - 在构建期间无法创建用户和数据库?
【发布时间】:2017-05-05 18:07:51
【问题描述】:

我已经为此浪费了一整天的时间,并且说我对本应简单的任务的不必要的复杂性没有留下深刻的印象 - 这是一种严重的轻描淡写。

好的,我已经明白了,我正在使用 docker-machine、docker-compose、postgresql 和 redis 构建一个 django 应用程序 - 关注 this tutorial。

我已经设法让基本教程开始工作 - 但它不适合我的需要,因为我需要为我的应用程序创建一个用户和一个数据库 - 而不是同时使用“postgres”。

我已将@dnephin 的答案用于similar question,并将我的代码修改如下:

我在新目录./database/中创建了一个新的Dockerfile:

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 在我通过 psql 导入 SQL 固定装置文件的位置:

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 解决这个问题 - 但没有找到。

我该如何解决这个问题?

【问题讨论】:

  • 我认为你应该使用“postgres”用户而不是 root 来启动你的脚本。您可以使用USER 关键字指定用户。
  • @papey 当我在我的 ./database/DockerFile 中指定 USER postgres 时(就在导入 SQL 语句文件之前)。我在运行docker-compose build 时收到以下错误输出:安装:无法更改“/etc/postgresql/9.6”的所有者和权限:没有此类文件或目录安装:无法创建目录“/etc/postgresql/9.6”:权限拒绝错误:无法创建配置目录;您可能需要以 root 权限运行此程序
  • 我认为这里有多个问题:1)标准docker容器内没有init,使用/etc/init.d可能会失败。 2)您的 psql 命令由 root 执行,默认 postgres 配置避免 root 用户连接。
  • @papey 感谢您提供帮助。但是仅仅猜测问题可能是什么没有帮助。关于您的建议:1)。如果您查看我发布的控制台输出,通过 init.d 启动 postgres 服务没有问题 2)。如果我使用 USER 指令将用户从 root 更改为 postgresql,问题不会消失。

标签: postgresql docker docker-compose psql


【解决方案1】:

卷在构建时不可用。您可以在脚本中创建/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

【讨论】:

  • 感谢您的建议,但当我按照您的指示操作时,出现以下错误:install: cannot change owner and permissions of ‘/etc/postgresql/9.6’: No such file or directory install: cannot create directory ‘/etc/postgresql/9.6’: Permission denied Error: could not create configuration directory; you might need to run this program with root privileges ERROR: Service 'postgres' failed to build: The command '/bin/sh -c /fixtures/setup.sh' returned a non-zero code: 1
  • 您的脚本中还有pg_createcluster 9.6 main --start 和/etc/init.d/postgresql start,对吧?它可以在我的机器上运行.. 我会更新答案 - 等一下
  • 对不起 - 也许我现在明白了这个问题。我认为 postgres 9.6 的卷在构建时不可用。卷在构建时根本不可用 - 当您启动容器时它们会被绑定。您必须在 entrypoint.sh 中执行此脚本。将更新答案
  • 感谢更新的答案 - 至少,这消除了我之前遇到的错误。 但是,我想登录数据库并确保对象(在我的 create_fixtures.sql 中指定)已创建。当我运行docker-compose up -d 时,我得到了容器的名称(为此,我们只对 postgres 容器感兴趣):Creating container mywebapp_postgres_1。然后我尝试使用命令docker run --rm -ti mywebapp_postgres_1 bash 登录,我得到错误:Unable to find image 'mywebapp_postgres_1:latest' locally ???
  • 只需使用:docker-compose exec postgres psql -U webuser mydatabase
【解决方案2】:

官方的 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

如果您需要特定的 db 用户或数据库,您还可以使用环境变量自定义您的 postgresql 容器。

在此处查看“环境变量”部分:https://hub.docker.com/_/postgres/

【讨论】:

  • 我不明白这句话:所以如果你用你的init sql脚本将你的目录挂载到容器路径'/docker-entrypoint-initdb.d/'它应该运行 - 你能澄清一下吗? - 最好举个例子? 目前,我正在将我的 init 文件复制到入口点目录COPY init.sql /docker-entrypoint-initdb.d/10-init.sql,但在我构建映像之后,并登录到数据库,我在初始化文件中指定的数据库对象都没有被创建。
  • @HomunculusReticulli 我修改了我的帖子
【解决方案3】:

试试这个 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"

【讨论】:

  • 这是我尝试您建议的修改时的控制台输出:install: cannot change owner and permissions of ‘/etc/postgresql/9.6’: No such file or directory install: cannot create directory ‘/etc/postgresql/9.6’: Permission denied Error: could not create configuration directory; you might need to run this program with root privileges ERROR: Service 'postgres' failed to build: The command '/bin/sh -c /fixtures/setup.sh' returned a non-zero code: 1
【解决方案4】:

在运行 psql 时尝试显式用户:

psql -U postgres -f create_fixtures.sql

【讨论】:

  • 您尝试过您推荐的 - 还是只是“猜测”?这是我尝试您推荐的结果时的结果:install: cannot change owner and permissions of ‘/etc/postgresql/9.6’: No such file or directory install: cannot create directory ‘/etc/postgresql/9.6’: Permission denied Error: could not create configuration directory; you might need to run this program with root privileges ERROR: Service 'postgres' failed to build: The command '/bin/sh -c /fixtures/setup.sh' returned a non-zero code: 1
  • 您报告的错误是因为 psql 命令中省略了-U role,在这种情况下 psql 尝试与 OS 用户连接。您可以编辑 ./database/setup.sh 添加我所说的内容,但请记住,您需要确保该用户对 ./database/create_fixtures.sql 的适当权限。
  • 不,我告诉过你我输入了命令,完全如你指定 - 即通过在 bash 脚本中明确指定用户。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-13
  • 1970-01-01
  • 1970-01-01
  • 2022-12-04
  • 1970-01-01
  • 2019-10-28
  • 2018-08-13
相关资源
最近更新 更多