使用docker-compose在PostgreSQL数据库中创建表

68

我正在使用docker-compose来部署一个多容器的Python Flask Web应用程序。我很难理解如何在构建期间在PostgreSQL数据库中创建表格,以便我不必使用psql手动添加它们。

我的docker-compose.yml文件如下:

web:
  restart: always
  build: ./web
  expose:
    - "8000"
  links:
    - postgres:postgres
  volumes:
    - /usr/src/flask-app/static
  env_file: .env
  command: /usr/local/bin/gunicorn -w 2 -b :8000 app:app

nginx:
  restart: always
  build: ./nginx/
  ports:
    - "80:80"
  volumes:
    - /www/static
  volumes_from:
    - web
  links:
    - web:web

data:
  restart: always
  image: postgres:latest
  volumes:
    - /var/lib/postgresql
  command: "true"

postgres:
  restart: always
  image: postgres:latest
  volumes_from:
    - data
  ports:
    - "5432:5432"

我不想必须输入psql才能输入:

CREATE DATABASE my_database;
CREATE USER this_user WITH PASSWORD 'password';
GRANT ALL PRIVILEGES ON DATABASE "my_database" to this_user;
\i create_tables.sql
我希望您能指导我如何创建表格。

我希望您能指导我如何创建表格。

3个回答

67

对我来说在Dockerfile中使用COPY方法没有起作用。但是我通过在docker-compose.yml中添加以下内容成功运行了我的init.sql文件:

然而,需要注意的是,本次回答仅提供机器翻译,可能存在语言表达不准确或者不符合中文表达习惯的问题,建议仍以官方文档或者人工翻译为准。

    volumes:
        - ./init.sql:/docker-entrypoint-initdb.d/init.sql

init.sql 和我的 docker-compose.yml 文件在同一个目录下。 我从这个代码片段中选择了解决方案。查看这篇文章获取更多信息。


58
我不想输入psql来进行输入,您可以使用容器内置的init机制: COPY init.sql /docker-entrypoint-initdb.d/10-init.sql。 这可以确保在数据库服务器正确启动后执行您的SQL语句。 请查看它们的入口点script。它会做一些准备工作以正确启动psql,并查看以.sh.sql.sql.gz结尾的文件是否存在于/docker-entrypoint-initdb.d/目录中。 文件名中的10-是因为文件按ASCII顺序处理。例如,您可以将其他初始化文件命名为20-create-tables.sql30-seed-tables.sql.gz,并确保它们按您需要的顺序处理。
请注意,调用命令不会指定数据库。如果您正在迁移到docker-compose,并且您现有的.sql文件也没有指定DB,请记住这一点。
尽管在容器的第一次启动时,您的文件将被处理,而不是在build阶段进行处理。由于Docker Compose停止镜像然后恢复它们,几乎没有区别,但是如果对您来说在build阶段初始化DB至关重要,我建议仍然使用内置的init方法,通过从dockerfile中调用/docker-entrypoint.sh,然后在/docker-entrypoint-initdb.d/目录中清理。

3
这在最新版本的Postgres镜像中无法运行 :( - dopatraman

14

我会把表格创建作为构建过程的一部分。在一个名为./database/的新目录中创建一个新的Dockerfile

FROM postgres:latest
COPY . /fixtures
WORKDIR /fixtures
RUN /fixtures/setup.sh

./database/setup.sh的内容可能如下所示:

#!/bin/bash
set -e

/etc/init.d/postgresql start
psql -f create_fixtures.sql    
/etc/init.d/postgresql stop
将您的创建用户、创建数据库、创建表格 SQL(以及任何其他固定数据)放入位于./database/目录下的create_fixtures.sql文件中。
最后,将您的postgres服务更改为使用build
postgres:
    build: ./database/
    ...

注意:有时候在执行 /etc/init.d/postgresql start 命令后,你需要使用 sleep 5(或者更好的是编写一个脚本来轮询并等待postgresql启动完毕)。根据我的经验,无论是init脚本还是psql客户端都可以为你处理这个问题。但我知道mysql不是这种情况,所以我想特别提醒一下。


感谢您的帮助。在构建docker-compose.yml时,我遇到了这个错误:bin/sh: 1: /fixtures/setup.sh: Permission denied Service 'postgres' failed to build: The command '/bin/sh -c /fixtures/setup.sh' returned a non-zero code: 126 - blahblahblah
好的,你也可以在脚本的顶部添加set -x,这样它就会打印出每一步,你就可以找出它失败的地方。 - dnephin
3
我加入了 RUN chmod +x /fixtures/setup.sh 以解决该问题。现在出现警告 No PostgreSQL clusters exist; see "man pg_createcluster" ... (warning). psql: could not connect to server: No such file or directory Is the server running locally and accepting connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"? Service 'postgres' failed to build: The command '/bin/sh -c /fixtures/setup.sh' returned a non-zero code: 2 - blahblahblah
好的,我认为你遇到了我在答案底部描述的情况。 - dnephin
不,这不是数据库目录。fixtures 是一个包含可以加载到数据库中的 .sql 文件的目录。 - dnephin
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接