使用初始模式构建 postgres docker 容器

Build postgres docker container with initial schema

我希望构建 docker 代表已存在的公司数据库的文件。同样,我想创建一个 docker 文件,以恢复 psql 转储开始。

我的 psql_dump.sql. 目录中。

FROM postgres
ADD . /init_data
run "createdb" "--template=template0" "my_database"
run  "psql" "-d" "my_database"  --command="create role my_admin superuser"
run  "psql" "my_database" "<" "init_data/psql_dump.sql"

我认为这样做就足够了。我想避免使用 .sh 脚本的解决方案。喜欢 this solution.

我使用 template0,因为 psql 文档说您需要在原始数据库中创建相同的用户,并且您需要在恢复之前使用 template0 创建数据库。

但是,它给我一个错误:

createdb: could not connect to database template1: could not connect to server: No such file or directory
        Is the server running locally and accepting

我也在为整个应用程序使用 docker compose,如果在 docker-compose 中解决这个问题更好,我很乐意使用基本 psql 图像并使用 docker 撰写以执行此操作。

根据官方 PostreSQL Docker 映像的 usage guide,您只需要:

Docker文件

FROM postgres
ENV POSTGRES_DB my_database
COPY psql_dump.sql /docker-entrypoint-initdb.d/

POSTGRES_DB 环境变量将指示容器在第一个 运行 上创建一个 my_database 模式。

并且在容器 /docker-entrypoint-initdb.d/ 中找到的任何 .sql 文件都将被执行。

如果要执行.sh个脚本,也可以在/docker-entrypoint-initdb.d/目录下提供。

如评论中所述,如果您的模式重建速度很快,@Thomasleveil 的回答既好又简单。 但在我的情况下它很慢,我想使用 docker 卷,所以这就是我所做的

  1. 首先使用@Thomasleveil 回答中的docker 图像创建一个带有所有模式初始化的 postgres 容器

Docker 文件:

FROM postgres
WORKDIR /docker-entrypoint-initdb.d
ADD psql_dump.sql /docker-entrypoint-initdb.d
EXPOSE 5432
  1. 然后 运行 它并创建新的本地目录,其中包含从“psql_dump.sql”文件填充后的 postgres 数据:docker cp mypg:/var/lib/postgresql/data ./postgres-data

  2. 将数据复制到临时数据文件夹,并启动一个新的 postgres docker-compose 容器,其卷在新的临时数据文件夹中:

startPostgres.sh:

rm -r ./temp-postgres-data/data
mkdir -p ./temp-postgres-data/data
cp -r ./postgres-data/data ./temp-postgres-data/
docker-compose -p mini-postgres-project up

并且 docker-compose.yml 文件是:

version: '3'
services:
  postgres:
    container_name: mini-postgres
    image: postgres:9.5
    ports:
    - "5432:5432"
    volumes:
      - ./temp-postgres-data/data:/var/lib/postgresql/data

现在您可以在新机器上 运行 步骤 #1 和 #2 或者如果您的 psql_dump.sql 发生变化。每次你想要一个新的干净(但已经初始化)的数据库,你只能从步骤#3 运行 startPostgres.sh。 而且它仍然使用 docker 卷。

@Thomasleveil 的回答将在运行时间 re-create 数据库模式,这对大多数情况都很好。

如果您想在 构建时间 重新创建数据库模式(即,如果您的模式初始化真的很慢),您可以从 Dockerfile 中调用库存 docker_entrypoint.sh

但是,由于 docker_entrypoint.sh 旨在启动 long-running 数据库服务器,因此您必须添加一个额外的脚本以在数据库初始化之后但在启动 long-running 之前退出进程服务器。

Dockerfile(带构建时间数据库初始化)

# STAGE 1 - Equivalent to @Thomasleveil
FROM postgres AS runtime_init
ENV POSTGRES_DB my_database
COPY 1-psql_dump.sql /docker-entrypoint-initdb.d/

# STAGE 2 - Initialize the database during the build
FROM runtime_init AS buildtime_init_builder
RUN echo "exit 0" > /docker-entrypoint-initdb.d/100-exit_before_boot.sh
ENV PGDATA=/pgdata
RUN docker-entrypoint.sh postgres

# STAGE 3 - Copy the initialized db to a new image to reduce size.
FROM postgres AS buildtime_init
ENV PGDATA=/pgdata
COPY --chown=postgres:postgres --from=buildtime_init_builder /pgdata /pgdata

重要提示

  • stock postgres 映像将 运行 初始化脚本 in alphabetical order,因此请确保您的数据库恢复脚本比 exit_before_boot.sh 脚本出现在 Dockerfile 中创建。
    • 上面显示的 1100 前缀证明了这一点。根据您的喜好修改它们。
  • 此映像的 运行ning 实例的数据库更新不会在重新启动后保留,因为存储数据库文件的 PGDATA 路径没有更长的映射到从主机安装的卷。

进一步阅读