簡體   English   中英

如何在創建時加載 postgres docker 圖像中的數據

[英]How to load data in postgres docker image on creation

我有以下 Dockerfile

FROM postgres:9.6.18
ENV POSTGRES_PASSWORD postgres
ENV POSTGRES_DB import
COPY docker/admin-db/*.sql /docker-entrypoint-initdb.d/

這工作正常,但每次我構建並啟動我的集群(docker-compose,結合 api 容器)時,加載所有 sql 文件(它包含測試數據)需要大約 2 分鍾。 這不是很敏捷,所以我想在創建圖像時加載數據,而不是在啟動容器時加載數據。 由於數據庫圖像不會經常更改,因此在圖像創建期間加載數據,大部分時間將從緩存層中獲取。

如何在創建鏡像時啟動容器,這樣每次運行docker-build都不需要在容器啟動時加載數據?

我已經廣泛閱讀了這個主題; 發現絕大多數建議也涉及使用 Docker 卷。 但是,我也堅信一定有辦法。 我想出了解決方案,效果很好。

  • 創建一個名為init-scripts的目錄,並將初始化 SQL 放在那里。
  • 將下面的build-bootstrapped-postgres-docker-image.sh腳本粘貼到上述目錄旁邊的 build-bootstrapped-postgres-docker-image.sh 中。
  • 如果需要,更改POSTGRES_DBPOSTGRES_PASSWORD
  • 使腳本可執行。
  • 執行: ./build-bootstrapped-postgres-docker-image.sh postgres:12.9-alpine your-db 1.0

這將使用postgres:12.9-alpine構建一個預先填充的 Postgres Image your-db:1.0


#!/bin/bash

# set -o xtrace

PG_IMAGE_NAME=$1
IMG_NAME=$2
IMG_TAG=$3
IMG_FQN="$IMG_NAME:$IMG_TAG"

CONTAINER_NAME="$IMG_NAME-$IMG_TAG-container"

echo 'killing any existing container that is running w same name'
docker kill $CONTAINER_NAME

echo 'running postgres container and bootstrapping schema/data... please wait.'
docker container run \
  --rm \
  --interactive \
  --tty \
  --detach \
  --volume ${PWD}/data:/var/lib/postgresql/data \
  --volume ${PWD}/init-scripts:/docker-entrypoint-initdb.d \
  --name $CONTAINER_NAME \
  --entrypoint /bin/bash \
  --env POSTGRES_DB=database \
  --env POSTGRES_PASSWORD=password \
  --env PGDATA=data \
$PG_IMAGE_NAME

docker container exec -d $CONTAINER_NAME sh -c 'docker-entrypoint.sh postgres >> bootstrap.log 2>&1'

echo 'waiting for container...this may take a while'
grep -q 'IPv4' <(docker exec $CONTAINER_NAME tail -f /bootstrap.log)

# echo 'removing the initialization SQL files'
docker container exec $CONTAINER_NAME rm -rf /docker-entrypoint-initdb.d/*

echo 'stopping pg'
docker container exec -u postgres $CONTAINER_NAME pg_ctl stop -D /data

# commit it.
echo 'committing the container to a new image'

docker container commit \
--change='CMD postgres' \
--change='ENTRYPOINT ["docker-entrypoint.sh"]' \
--change='USER postgres' \
$CONTAINER_NAME $IMG_FQN

# cleanup!
docker kill $CONTAINER_NAME

echo "successfully built $IMG_FQN"

現在你可以運行容器了:

docker run your-db:1.0

如果您想要一個有點手動的簡單解決方案,那么您將:

  1. 以應用測試數據的正常方式啟動 postgres 容器。
  2. 退出它。 並運行docker commit將容器保存為新圖像。
  3. 使用該圖像作為測試的基礎。

在 docker 構建時應用測試腳本的完全自動化的解決方案將必須了解如何啟動 postgres。 在這里,您可以像這樣調查問題:

# Create a postgres container.
docker create postgres:9.6 --name postgres
# Copy the entrypoint script out.
docker cp postgres:/usr/local/bin/docker-entrypoint.sh docker-entrypoint.sh

現在,修改后的 docker-entrypoint.sh 腳本可以用作

RUN apply-sql-scripts.sh

在您的 Dockerfile 中。 它看起來可能很復雜。

在構建時使用卷而不是將數據復制到 /docker-entrypoint-initdb.d/ 使用卷,第一次啟動容器時,它將加載所有數據。 之后,它將僅重用已加載的數據(這似乎是您所需要的)。 只要您不刪除該卷,您的數據將在您重新啟動時始終存在。

這是一個示例:

  pgdb:
    image: postgres
    restart: always
    container_name: pgdb
    env_file: ./postgres/docker-compose.env
    volumes:
      - ./postgres/postgresDB:/var/lib/postgresql/data
      - ./postgres/postgresInit:/docker-entrypoint-initdb.d
    ports:
      - "5432:5432"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM