以 Docker 快速建立 PostgreSQL 開發環境

當使用 .NET Core 之後,server 就不見的要使用 Microsoft 技術,可自由選擇 Linux 受歡迎的 service,如 Nginx、Redis、PostgreSQL … 等。

以 PostgreSQL 而言,透過 Docker,我們可以很輕鬆的在 Windows 或 macOS 建立 .NET Core + PostgreSQL 開發環境,且重點是 Linux 版的 PostgreSQL 的。

Version


macOS High Sierra 10.13.4
Docker for Mac 18.03-ce-mac65 (24312)
.NET Core 2.1
PostgreSQL 10.3
DataGrip 2018.1.4

建立 Docker Compose


docker-compose.yml

1
version: "3"

services:
  netcore:
    image: microsoft/dotnet
    container_name: MyNETCore
    volumes:
      - ${NETCORE_HOST_DIR}:/code/
    tty: true
    networks: 
      - netcore-dev
    depends_on:
      - postgres

  postgres:
    image: postgres
    container_name: MyPostgres
    volumes:
      - ${POSTGRES_HOST_DIR}/data:/var/lib/postgresql/data
    expose:
      - "5432"
    ports:
      - "${POSTGRES_PORT}:5432"
    environment:
      - POSTGRES_DB=${POSTGRES_DB}
      - POSTGRES_USER=${POSTGRES_USER}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
    networks:
      - netcore-dev

networks:
  netcore-dev:

第 1 行

1
version: "3"

versiondocker-compose.yml 的第一層 tag,用來設定 docker-compose.yml 格式的版本。

因為 docker-compose.yml 的格式版本與 Docker 版本息息相關,若你要使用新版的 Docker 所提供的功能,在 docker-compose.yml 的版本就必須下的更細,如 3.3,在此只使用了 docker-compose.yml 基本功能而已,使用 3 即可。

第 3 行

1
services:
  netcore:
  postgres:

servicesdocker-compose.yml 的第一層 tag,用來設定有哪些 service 要一起跑。

以本文為例,要同時跑 .NET CorePostgreSQL 兩個 service,因此在 docker-compose.yml 內建立 netcorepostgres 兩個 service。

31 行

1
networks:
  netcore-dev:

networksdocker-compose.yml 的第一層 tag,用來設定 container 間所共用的網路名稱。

以本文為例,我們希望 netcorepostgres 兩個 container 都跑在相同的網路下,彼此都能看到對方,因此特別宣告了 netcore-dev 網路,將來兩個 container 都將共用此網路。

第 4 行

1
netcore:
  image: microsoft/dotnet

設定 netcore service,此名稱可自行建立。

使用 image設定使用 microsoft/dotnet image。

第 6 行

1
container_name: MyNETCore

使用 container_name 設定 netcore service 的 container 名稱為 MyNETCore

第 7 行

1
volumes:
  - ${NETCORE_HOST_DIR}:/code/

使用 volumns 設定 Host OS 與 container 所共享目錄,將來 Host OS 所分享的目錄,相當於 container 內部的 /code 目錄。

由於每個人 Host OS 要分享的目錄都不一樣,因此設定成 NETCORE_HOST_DIR 變數,稍後自行在 .env 設定。

第 9 行

1
tty: true

Docker 為了節省硬體資源,app 執行完就會釋放 container,但處於開發階段,我們需要的是類似 service 跑在背景,隨時可以進入 container 測試 Linux app。

tty: true 將令 Docker 分配一個 TTY (T ele TY pewriter),綁定到 container 的 stdinstdout 上,將來我們才能透過 Bash 對 container 下指令,由於 tty 在背景持續執行,因此 container 就不會被釋放。

10 行

1
networks: 
  - netcore-dev

使用 networks 設定 container 所要使用的網路名稱。

由於之前已經建立了 netcore-dev 網路,現在 netcore container 將使用 netcore-dev 網路。

12 行

1
depends_on:
  - postgres

使用 depends_on 設定 container 的啟動順序。

我們希望 postgres container 先啟動後,netcore container 再啟動,如此 .NET Core 才能使用 PostgresSQL。

15 行

1
postgres:
  image: postgres

設定 postgres service,此名稱可自行建立。

使用 image 設定使用 postgres image。

17 行

1
container_name: MyPostgres

使用 container_name 設定 postgres service 的 container 名稱為 MyPostgres

18 行

1
volumes:
  - ${POSTGRES_HOST_DIR}/data:/var/lib/postgresql/data

使用 volumns 設定 PostgreSQL 所儲存的資料到 Host OS。

我們不希望 PostreSQL 將資料存在 container 內部,如此 PostgreSQL 將來要更新版本時會很麻煩,無法簡單換掉 container 就更新版本,因此特別使用 volumns 指定 Host OS 目錄,如此 PostgreSQL 會將資料存在 Host OS,而不是 container 內

20 行

1
expose:
  - "5432"

PostgreSQL 將以 port 5432 對外溝通。

注意這只是對 netcore-dev 網路以 port 5432,若要讓 Host OS 存取,必須進一步靠 ports 設定

22 行

1
ports:
  - "${POSTGRES_PORT}:5432"

使用 ports 設定 Host OS 與 container 的 port 對應。

由於每個人 Host OS 所希望的 port 不同,因此設定成 POSTGRES_PORT 變數,稍後自行在 .env 設定。

24 行

1
environment:
  - POSTGRES_DB=${POSTGRES_DB}
  - POSTGRES_USER=${POSTGRES_USER}
  - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}

使用 environment 設定 PostgreSQL 所需的環境變數。

  • POSTGRES_DB: 要使用的 database,container 在建立時,會幫我們自動建立
  • POSTGRES_USER:連進 PostgreSQL 的 user
  • POSTGRES_PASSWORD:連進 PostgreSQL 的 password

由於這 3 個變數每個人的需求不同,因此統一使用變數在 .env 設定。

28 行

1
networks:
  - netcore-dev

使用 networks 設定 container 所要使用的網路名稱。

由於之前已經建立了 netcore-dev 網路,現在 postgres container 將使用 netcore-dev 網路,如此 netcorepostgres 都在相同的 netcore-dev 網路下,可以彼此看到對方。

post000

.env

1
2
3
4
5
6
NETCORE_HOST_DIR=~/Code/CSharp
POSTGRES_HOST_DIR=~/Postgres
POSTGRES_DB=eflab
POSTGRES_USER=admin
POSTGRES_PASSWORD=12345
POSTGRES_PORT=5432

所有 Host OS 自行設定的部分,全部放在 .env

  • NETCORE_HOST_DIR : 設定 Host OS 的 .NET Core 專案所在目錄
  • POSTGRES_HOST_DIR : 設定 PostgreSQL 將資料存到 Host OS 的目錄
  • POSTGRES_DB : 設定 PostgreSQL 所使用的資料庫名稱
  • POSTGRES_USER : 設定 PostgreSQL 連線的 user
  • POSTGRES_PASSWORD : 設定 PostgreSQL 連線的 password
  • POSTGRES_PORT : 設定 PostgreSQL 對應到 Host OS 的 port

post001

執行 Docker Compose


1
~/PostgresCore $ docker-compose up -d

進入 docker-compose.yml 所在的目錄,執行 docker-compose up 啟動所有 container。

  • -dd etatch,表示 docker-compose 啟動後將離開 container 的 process,讓 container 在背景執行

post002

連接 PostgreSQL


post003

開啟 DataGrip:

  1. 右側選擇 Database tab
  2. 上放按 + 新增連線
  3. 選擇 Data Source -> ProgreSQL

post004

  1. Name:設定 connection 連線名稱
  2. Database:設定剛剛所建立的 database
  3. User:設定剛剛所建立的 user
  4. Password : 設定剛剛所建立的 password
  5. Test Connection 測試連線是否成功
  6. 顯示 Successful 確認連線成功
  7. OK 建立連線

post005

  1. 顯示剛剛所建立的 database

結束 Docker Compose


1
~/PostgresCore $ docker-compose down

進入 docker-compose.yml 所在的目錄,執行 docker-compose down 結束所有 container。

post006

Conclusion


  • 透過 Docker,我們可以很輕易在本機建立 .NET Core + PostgreSQL 環境,重點是跑的是 Linux 版本的 PostgreSQL,與 production 的 Linux 版本一致。

Sample Code


完整的範例可以在我的 GitHub 上找到