我浪费了整整一天的时间,并且说我不会对应该是一项简单的任务的不必要的复杂性留下深刻的印象 - 这将是一种严重的轻描淡写。
好的,从我的胸口开始,我正在使用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
时,构建将通过 psql >> >向 psql 导入SQL fixtures文件进行运动然后 barfs p>
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来解决这个问题 - 但是没有找到。
我该如何解决这个问题?
答案 0 :(得分:4)
在构建时无法使用卷。您可以在脚本中创建/var/lib/postgresql/data
,但VOLUME /var/lib/postgresql/data
图像会覆盖postgres:9.6
。
在您的情况下:只需使用以下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
答案 1 :(得分:1)
官方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/
答案 2 :(得分:0)
尝试使用此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"
答案 3 :(得分:0)
运行psql时尝试显式用户:
psql -U postgres -f create_fixtures.sql