前言
前陣子因為專案需求,需要把某個 docker 的 PostgreSQL container 資料備份到另一台 docker container 內,因此紀錄一下整體過程
簡例
首先,先拉取 postgresql 14.6 版的 image
docker pull postgres:14.6
docker image | grep postgres # 取得image id
再來準備一份測試的 seed.csv
,等等要匯入 postgresql 中
title,content
Eric,Hello
Madi,Hi
Danny,GoAhead
Kyle,Looks grood
將 postgresql 的 container 跑起來,並 bind mount 掛載剛剛的 csv 檔
docker run -itd --rm --name example -p 5432:5432 -v "$(pwd)"/seed.csv:/seed.csv -e POSTGRES_PASSWORD=postgres <image_id>
接著,跳進去 container 內,把 csv 的內容匯入 postgresql 中
docker exec -it example psql -U postgres -d postgres
/* 要先依照csv的內容建立table */
CREATE TABLE article(title text, content text);
/* 將csv匯入table */
COPY article (title, content) FROM '/seed.csv' WITH (FORMAT CSV, HEADER TRUE);
/* 確認資料是否匯入成功 */
SELECT * FROM article;
title | content
-------+-------------
Eric | Hello
Madi | Hi
Danny | GoAhead
Kyle | Looks grood
(4 rows)
確認資料匯入成功後,再來模擬需求,目標是把剛剛匯入的 posgresql 的資料 dump 出來,匯到另一個 container
Dump postgresql 資料的語法是
pg_dump -U <user> -h <host> -p <port> <DB name> >> /path/to/backup.sql
用 docker 一行指令完成,通常會在檔名上壓一個 timestamp
docker exec -it example pg_dump -U postgres -h localhost -p 5432 postgres >> dump_`date +%Y%m%d"_"%H%M%S`.sql
完成後,會在當前本機路徑生成一個 .sql 檔,這個就是等等要給另一個 container 匯入的資料
啟動另一個名為 example2 的 postgresql container
docker run -itd --rm --name example2 -p 5433:5432 -e POSTGRES_PASSWORD=postgres <image id>
啟動好之後,將剛剛的 .sql 檔匯給這個新 container
需注意 docker exec 不需要加上
-t
因為不是 TTY
cat ./<dumpfile>.sql | docker exec -i example2 psql -U postgres
撈一下資料看看是否匯入成功
docker exec -it example2 psql -U postgres -d postgres -c "SELECT * FROM article"
title | content
-------+-------------
Eric | Hello
Madi | Hi
Danny | GoAhead
Kyle | Looks grood
(4 rows)
資料轉移成功!
除此之外,其實 restore 還有另一種方式,就是使用 psql 的 -f 參數來指定 file
psql -U postgres -h localhost -p 5433 -f <dumpfile>.sql
總結
去蕪存菁,總結就是以下指令:
# Backup
docker exec -it <container1> pg_dump -U postgres -h localhost -p 5432 <db_name> >> dump_`date +%Y%m%d"_"%H%M%S`.sql
# Create Database Before Restoring
docker exec -it <container2> psql -U postgres -c "CREATE DATABASE \"db_name\";"
# Restore - M1
cat ./<dumpfile>.sql | docker exec -i <container2> psql -U postgres -d <db_name>
# Restore - M2
psql -U <user> -h <host> -p <port> -f <dumpfile>.sql
除此之外,也可以用 volumes 的備份方式,可以參考 Docker 官網的文件