最近學著使用 PostgreSQL 做些小應用,過程主要利用 Docker 幫忙建立 PostgreSQL 的執行環境,可說是相當方便,本篇就記錄幾則使用 Docker 玩轉 PostgreSQL 的筆記。

Pull PostgreSQL

PostgreSQL 已經是 Official Image ,所以可以直接透過以下指令 Pull Postgres 的 Image :

docker pull postgres

各種版本的 PostgreSQL 可以參閱 docker store - postgres

啟動 PostgreSQL

Pull Image 結束後,可以使用以下指令將 PostgreSQL 在背景執行:

docker run --name mypostgres -e POSTGRES_PASSWORD=mysecretpassword -d postgres

其中 -e POSTGRES_PASSWORD=mysecretpassword 指的是設定環境變數 POSTGRES_PASSWORD , PostgreSQL 在啟動時會讀取環境變數 POSTGRES_PASSWORD 的值,並將之設定為 postgres (PostgreSQL 預設的使用者帳號)的密碼。

Docker 提供的 PostgreSQL Image 同時也提供多個環境變數可供設定,例如 POSTGRES_USER , POSTGRES_PASSWORD 等,詳閱 docker store - postgres

連線至 PostgreSQL

由於 PostgreSQL 正在背景執行,所以可以啟動另一個新的 PostgreSQL 然後將其與正在背景執行的 PostgreSQL 連結在一起(link),並利用新啟動的 PostgreSQL 裡的 psql 指令連線至鄭在背景執行的 PostgreSQL :

docker run -it --rm --link mypostgres:postgres postgres psql -h postgres -U postgres

上述指令會詢問 postgres 的密碼,輸入我們設置環境變數 POSTGRES_PASSWORD 的值即可。

除了上述提到的連結方式之外,其實也可以選擇 expose PostgreSQL 的 5432 port ,直接從 host 利用 psql 指令連線進去即可:

docker run --rm --name mypostgres -e POSTGRES_PASSWORD=mysecretpassword -p 5432:5432 -d postgres

結合 docker-compose.yaml

除了用 docker 指令玩玩 PostgreSQL 之外,開發應用時也經常會利用 docker-compose 連結多個 container ,也由於資料庫相關的應用在開發時會有儲存的需求,不太可能每次都要花費時間重新建立資料,所以就必須掛載 Volumes 來儲存資料庫的資料,避免 container 重啟之後資料就不見了。

Docker 提供的 PostgreSQL Image 可以透過掛載 /var/lib/postgresql/data (預設,可以修改環境變數 PGDATA 來改變) 達到儲存資料的需求。

此外,Docker 的 PostgreSQL Image 也可以透過掛載 /docker-entrypoint-initdb.d 達到擴充的目的,該資料夾內的 *.sql , .sql.gz , *.sh 都會在 PostgreSQL 服務啟動之前執行,所以也很適合作為預先建立資料庫、設定使用者權限、安裝測試資料等等用途,例如官方提供的範例:

#!/bin/bash
set -e

psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
    CREATE USER docker;
    CREATE DATABASE docker;
    GRANT ALL PRIVILEGES ON DATABASE docker TO docker;
EOSQL

如果是針對 PostgreSQL 的設定檔變更的話,則可以掛載 /etc/postgresql/postgresql.conf

設定好掛載上述提及的 3 個 Volumes 的 docker-compose.yaml 範例如下:

   db:
     image: "postgres:10"
     restart: always
     ports:
       - "5432:5432"
     volumes:
       - ./initdb.d:/docker-entrypoint-initdb.d
       - ./pgdata:/var/lib/postgresql/data
       - ./postgres.conf:/etc/postgresql/postgresql.conf

上述範例會將 ./initdb.d , ./pgdata./postgres.conf 分別掛在 PostgreSQL container 裡的 /docker-entrypoint-initdb.d , /var/lib/postgresql/data/etc/postgresql/postgresql.conf

如此一來就能夠隨心所欲的利用 Docker 玩轉 PostgreSQL 了。

References

https://store.docker.com/images/postgres