使用初始模式构建 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 卷,所以这就是我所做的
- 首先使用@Thomasleveil 回答中的docker 图像创建一个带有所有模式初始化的 postgres 容器
Docker 文件:
FROM postgres
WORKDIR /docker-entrypoint-initdb.d
ADD psql_dump.sql /docker-entrypoint-initdb.d
EXPOSE 5432
然后 运行 它并创建新的本地目录,其中包含从“psql_dump.sql”文件填充后的 postgres 数据:docker cp mypg:/var/lib/postgresql/data ./postgres-data
将数据复制到临时数据文件夹,并启动一个新的 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 中创建。
- 上面显示的
1
和 100
前缀证明了这一点。根据您的喜好修改它们。
- 此映像的 运行ning 实例的数据库更新不会在重新启动后保留,因为存储数据库文件的
PGDATA
路径没有更长的映射到从主机安装的卷。
进一步阅读
- 官方 postgres 图像作者关于 writing your own
custom_entrypoint.sh
的说明。这可以说是解决这个问题的更“官方”的方法,但我个人觉得我的方法更容易理解和实施。
- A demo of this concept for PostgreSQL 9, which uses the
--help
flag to exit the docker-entrypoint.sh
before the long-running server boots. Unfortunately, this no longer works as of December 3, 2019
- 两个讨论(1) (2) of this same question from the official docker postgres repository。
我希望构建 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 卷,所以这就是我所做的
- 首先使用@Thomasleveil 回答中的docker 图像创建一个带有所有模式初始化的 postgres 容器
Docker 文件:
FROM postgres
WORKDIR /docker-entrypoint-initdb.d
ADD psql_dump.sql /docker-entrypoint-initdb.d
EXPOSE 5432
然后 运行 它并创建新的本地目录,其中包含从“psql_dump.sql”文件填充后的 postgres 数据:
docker cp mypg:/var/lib/postgresql/data ./postgres-data
将数据复制到临时数据文件夹,并启动一个新的 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 中创建。- 上面显示的
1
和100
前缀证明了这一点。根据您的喜好修改它们。
- 上面显示的
- 此映像的 运行ning 实例的数据库更新不会在重新启动后保留,因为存储数据库文件的
PGDATA
路径没有更长的映射到从主机安装的卷。
进一步阅读
- 官方 postgres 图像作者关于 writing your own
custom_entrypoint.sh
的说明。这可以说是解决这个问题的更“官方”的方法,但我个人觉得我的方法更容易理解和实施。 - A demo of this concept for PostgreSQL 9, which uses the
--help
flag to exit thedocker-entrypoint.sh
before the long-running server boots. Unfortunately, this no longer works as of December 3, 2019 - 两个讨论(1) (2) of this same question from the official docker postgres repository。