Postgresql 如何在构建Docker映像时恢复Postgresdump?

Postgresql 如何在构建Docker映像时恢复Postgresdump?,postgresql,docker,database-backups,Postgresql,Docker,Database Backups,我试图避免在我的工作流程中接触共享的开发人员数据库;为了使这更容易,我希望在磁盘上有Docker映像定义,用于我需要的模式。然而,我在制作Dockerfile时遇到了麻烦,它将创建一个已恢复转储的Postgres图像。我的问题是,在构建Docker映像时,Postgres服务器没有运行 当我在壳中的容器中胡闹时,我尝试手动启动容器,但我不确定正确的方法是什么/docker entrypoint.sh似乎什么都不做,我也不知道如何“正确”启动服务器 所以我需要做的是: 从“博士后”开始 将转储文

我试图避免在我的工作流程中接触共享的开发人员数据库;为了使这更容易,我希望在磁盘上有Docker映像定义,用于我需要的模式。然而,我在制作Dockerfile时遇到了麻烦,它将创建一个已恢复转储的Postgres图像。我的问题是,在构建Docker映像时,Postgres服务器没有运行

当我在壳中的容器中胡闹时,我尝试手动启动容器,但我不确定正确的方法是什么
/docker entrypoint.sh
似乎什么都不做,我也不知道如何“正确”启动服务器

所以我需要做的是:

  • 从“博士后”开始
  • 将转储文件复制到容器中
  • 启动PG服务器
  • 运行
    psql
    恢复转储文件
  • 杀死PG服务器
(我不知道的步骤是斜体,其余的很简单。)

我想避免的是:

  • 在现有容器中手动运行恢复,整个想法是能够在不同数据库之间切换,而无需触摸应用程序配置
  • 保存恢复的映像,我希望能够使用不同的转储轻松地为数据库重建映像。(同时,不可重复的图像构建也让Docker感觉不太好。)

您可以利用卷

postgres
图像有一个可以设置的环境变量:
PGDATA

见文件:

然后,您可以使用所需的确切db数据指向预先创建的卷,并将其作为参数传递给映像。


也可以在此处找到替代解决方案:

通过提供example.pg转储文件,可以使用以下Dockerfile完成此操作:

FROM postgres:9.6.16-alpine

LABEL maintainer="lu@cobrainer.com"
LABEL org="Cobrainer GmbH"

ARG PG_POSTGRES_PWD=postgres
ARG DBUSER=someuser
ARG DBUSER_PWD=P@ssw0rd
ARG DBNAME=sampledb
ARG DB_DUMP_FILE=example.pg

ENV POSTGRES_DB launchpad
ENV POSTGRES_USER postgres
ENV POSTGRES_PASSWORD ${PG_POSTGRES_PWD}
ENV PGDATA /pgdata

COPY wait-for-pg-isready.sh /tmp/wait-for-pg-isready.sh
COPY ${DB_DUMP_FILE} /tmp/pgdump.pg

RUN set -e && \
    nohup bash -c "docker-entrypoint.sh postgres &" && \
    /tmp/wait-for-pg-isready.sh && \
    psql -U postgres -c "CREATE USER ${DBUSER} WITH SUPERUSER CREATEDB CREATEROLE ENCRYPTED PASSWORD '${DBUSER_PWD}';" && \
    psql -U ${DBUSER} -d ${POSTGRES_DB} -c "CREATE DATABASE ${DBNAME} TEMPLATE template0;" && \
    pg_restore -v --no-owner --role=${DBUSER} --exit-on-error -U ${DBUSER} -d ${DBNAME} /tmp/pgdump.pg && \
    psql -U postgres -c "ALTER USER ${DBUSER} WITH NOSUPERUSER;" && \
    rm -rf /tmp/pgdump.pg

HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 \
  CMD pg_isready -U postgres -d launchpad
其中,
等待pg isready.sh
为:

#!/bin/bash
set -e

get_non_lo_ip() {
  local _ip _non_lo_ip _line _nl=$'\n'
  while IFS=$': \t' read -a _line ;do
    [ -z "${_line%inet}" ] &&
        _ip=${_line[${#_line[1]}>4?1:2]} &&
        [ "${_ip#127.0.0.1}" ] && _non_lo_ip=$_ip
    done< <(LANG=C /sbin/ifconfig)
  printf ${1+-v} $1 "%s${_nl:0:$[${#1}>0?0:1]}" $_non_lo_ip
}

get_non_lo_ip NON_LO_IP
until pg_isready -h $NON_LO_IP -U "postgres" -d "launchpad"; do
  >&2 echo "Postgres is not ready - sleeping..."
  sleep 4
done

>&2 echo "Postgres is up - you can execute commands now"
#/bin/bash
set-e
获取_non_lou_ip(){
本地(ip)非(lo)ip(线路)nl=$'\n'
而IFS=$':\t'读取-a\u行;do
[-z“${u行%inet}”]&&
_ip=${{u线[${{u线[1]}>4?1:2]}&&
[“${u ip#127.0.0.1}”]&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
完成<&2 echo“Postgres未准备好-正在睡觉…”
睡眠4
完成
>&2 echo“Postgres已启动-您现在可以执行命令”
对于两个“不确定步骤”:

启动PG服务器

nohup bash-c“docker-entrypoint.sh postgres&”
可以处理它

杀死PG服务器

其实没必要


上述脚本以及更详细的自述文件可在

上找到。我记得我在其他项目上使用过的一种通用方法适用于任何要初始化的系统:

使用Docker Compose dependencies(Docker Compose dependencies)而不是在构建过程中尝试这样做,这样您就可以得到:

  • 您的
    db
    服务启动数据库,而无需任何需要激活数据库的初始化
  • db init
    服务:
    • 依赖于
      db
    • 使用say dockerize等待数据库出现
    • 然后在保持幂等性的同时初始化数据库(例如,使用模式迁移)
    • 和出口
  • 您的应用程序服务现在依赖于
    db init
    而不是
    db

pg_dump不会这样做,因为正如您已经提到的,在生成映像时postgresql没有运行。您可以尝试克隆postgresql数据文件。通常进行备份(不是tar格式)使用pg_basebackup并将整个结构复制到映像中。这样,您将在某个时间点获得一致的快照。在映像启动期间,pg将执行“恢复”从备份期间捕获的存储的WAL文件中获取。但只有当您打算创建纯真实数据快照时,图像中的数据才有用…我将把数据存储在一个卷中,但因为这是为了开发目的,所以实际上并不重要。我真正感兴趣的是能够从docker compose.yml+Dockerfiles+dumpfile转到运行db的步骤尽可能少,并且有尽可能多的适合版本控制的输入文件。是的,使用卷违背了我想要避免的第二件事的精神,也违背了我首先要解决的整个问题:我想在构建过程中创建PG数据文件,而不是单独构建它们。虽然链接的答案看起来很有希望,但看起来对于我的帖子来说,这可能是一个重复,我只是找不到它,因为它使用了不同的措辞。非常有趣的存储库。我很欣赏你的工作。我认为使用多阶段构建可以通过实际/简单地将整个datadir压缩到映像中的一个目录来改进过程,该目录将在运行时恢复