在构建期间填充Postgres Docker映像(未运行)

时间:2019-03-04 22:09:54

标签: database postgresql docker

我想通过两个任务准备自定义图像(基于官方Postges image):

  1. 下载数据(例如,通过wget获取CSV文件),
  2. 将数据加载到数据库中(创建表,插入)。

我想在构建映像时而不是在运行容器时执行这两个步骤,因为它们每个都花费很多时间,并且我想一次构建映像并快速运行许多容器。

我知道如何在构建映像期间执行步骤1(下载数据),但是我不知道如何在构建映像期间将数据加载到数据库中,而不是运行容器(步骤2)。

示例:

(下载-构建映像期间,加载-运行容器期间)

Dockerfile

FROM postgres:10.7

RUN  apt-get update \
  && apt-get install -y wget \
  && rm -rf /var/lib/apt/lists/* 

COPY download.sh /download.sh
RUN /download.sh

download.sh

#!/bin/bash

cd /docker-entrypoint-initdb.d/
wget https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/northwindextended/northwind.postgre.sql

要下载数据,我自己运行脚本。要加载数据,我使用Postgres官方图片中的“ initialization scripts”实用程序。

建筑图片:

docker build -t mydbimage .

运行图像:

docker run --name mydbcontainer -p 5432:5432 -e POSTGRES_PASSWORD=postgres -d mydbimage 

运行后,您可以看到需要多少加载数据:

docker logs mydbcontainer

此示例数据集很小,但是长时间运行的容器比较笨拙。

1 个答案:

答案 0 :(得分:1)

您可以剖析上游Dockerfile及其docker-entrypoint.sh,只需选择所需的代码片段即可初始化数据库:

FROM postgres:10.7

ENV PGDATA /var/lib/postgresql/datap-in-image
RUN mkdir -p "$PGDATA" && chown -R postgres:postgres "$PGDATA" && chmod 777 "$PGDATA" # this 777 will be replaced by 700 at runtime (allows semi-arbitrary "--user" values)

RUN set -x \
  && apt-get update && apt-get install -y --no-install-recommends ca-certificates wget && rm -rf /var/lib/apt/lists/* \
  && wget https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/northwindextended/northwind.postgre.sql \ 
    -O /docker-entrypoint-initdb.d/northwind.postgre.sql \
  && cp ./docker-entrypoint.sh ./docker-entrypoint-init-only.sh \
  && sed -ri '/exec "\$@"/d' ./docker-entrypoint-init-only.sh \
  && ./docker-entrypoint-init-only.sh postgres \
  && rm ./docker-entrypoint-initdb.d/northwind.postgre.sql ./docker-entrypoint-init-only.sh \
  && apt-get purge -y --auto-remove ca-certificates wget

构建,运行和测试:

docker build -t mydbimage .

# bring up the database
docker run --rm mydbimage --name pgtest

# run this in another terminal to check for the imported data 
docker exec -ti pgtest psql -v ON_ERROR_STOP=1 --username "postgres" --no-password --dbname postgres --command "\d"

注意事项:

  • 通过此设置,没有为数据库设置没有密码。您可以在构建期间添加它,但是它将保留在映像中。您需要采取预防措施,以确保没有人可以访问您的图像。根据您的设置,这可能很难实现,甚至可能无法实现。
  • 第二个问题是对数据库的写入是临时。在构建期间没有卷可以保留导入的数据。这就是将PGDATA更改为未声明为卷的目录的原因。

基本上,这就是为什么在启动容器时而不是在上游存储库中构建时要处理导入的原因。如果您将非机密数据用作只读数据,则在构建过程中导入它仍然很有意义,以节省时间并在容器启动期间更易于处理。