不少開發者在開始一個新項目的時候,一般會使用 JSON,CSV 或者其餘 Flat File 來模擬真實存放在數據庫中的數據。這是由於他們老是在沒有真實的數據庫環境限制和是否須要本身建立模擬數據庫之間左右爲難。既然這樣,爲何不使用 Docker Compose 定義一個能夠在幾秒鐘內建立、銷燬和從新建立的 PostgreSQL 數據庫和監視工具?html
正確建立配置兩個容器的 Docker 命令過於冗長。而使用 Docker Compose,你只須要記住 up
命令和 down
命令!前端
Up
命令將建立指定版本的 PostgreSQL 數據庫和一個 GUI 管理工具。Down
命令會將其關閉並刪除。android
下面所展現的這份 docker-compose.yml
文件定義了一個運行特定版本 PostgreSQL 和 pgAdmin 4(Postgres 最經常使用的管理工具)的 PostgreSQL 容器。該文件的內容值得咱們詳細的探討。ios
version: "3.8"
services:
postgres:
image: postgres:9.6.12-alpine
container_name: some-postgres
volumes:
- "~/Documents/docker_pgsql_init:/docker-entrypoint-initdb.d"
- "~/Documents/docker_pgsql_volume:/var/lib/postgresql/data"
ports:
- 5432:5432
environment:
- POSTGRES_PASSWORD=mysecret
deploy:
restart_policy:
condition: on-failure
max_attempts: 3
pgadmin:
image: dpage/pgadmin4
container_name: some-pgadmin
volumes:
- ${PWD}/servers.json:/pgadmin4/servers.json
ports:
- 8080:80
environment:
- PGADMIN_DEFAULT_EMAIL=user@domain.com
- PGADMIN_DEFAULT_PASSWORD=admin
deploy:
restart_policy:
condition: on-failure
max_attempts: 3
複製代碼
該文件定義了兩個要建立的「服務」:Postgres 和 pgAdmin。每一個服務都包含一個從 Docker Hub 拉取的容器。Postgres 和 pgAdmin 將分別開放 5432 端口和 8080 端口。將你寫的任何程序指向主機名「localhost」,而後用瀏覽器訪問 http://localhost:8080 便可訪問 pgAdmin。git
繼續閱讀有關如何將 pgAdmin 指向 Postgres 的說明。程序員
在定義 Postgres 容器的這一行中,你須要準確指定所需的 Postgres 版本。在這裏,版本是一個標籤,而 9.6.12-alpine
就是示例中使用的版本。點擊這裏查看其餘可用的版本。github
上面的 docker-compose.yml
文件爲 Postgres 指定了兩個 volume 映射。這兩個映射將使 Postgres 能夠訪問你計算機上的目錄。web
/docker-entrypoint-initdb.d
的文件夾包含了初始化 Postgres 將會用到的 SQL 文件。將所需的 SQL 文件和 Shell 腳本放在該目錄中,它們將會按字母順序自動執行。/var/lib/postgresql/data
的文件夾存放了數據庫持久化存儲所須要的實際文件。當 Postgres 啓動時,他的簡單運行流程以下圖所示。若是數據庫中沒有數據,那麼它將執行被映射到 /docker-entrypoint-initdb.d
目錄中的每一個 SQL 文件和 Shell 腳本(按字母順序)。若是被映射到 /var/lib/postgresql/data
目錄的文件夾中有數據,那麼它將會忽略掉這些文件。sql
你是否須要掛載這兩個目錄?這個得視狀況而定。下表描述了經過 Postgres 的兩個不一樣映射獲得的一個預期結果。docker
個人建議是對這兩個文件目錄都作映射。若是你不想再初始化你的數據庫,你能夠從 init 目錄中刪除文件。你也能夠在你的計算機上刪除任何可能已經持久化的數據(當你下一次運行 docker-compose up
命令時,Docker 將會在其位置從新建立一個空文件夾)。
專業提示:你能夠將 CSV 文件放在計算機的 init 文件夾中,而後在 init 目錄中經過適當的 SQL 命令將 CSV 文件中的數據填充到數據表中。
CREATE TABLE Employee(id, first_name, last_name, salary);
COPY Employee FROM '/docker-entrypoint-initdb.d/emp.csv'
WITH (FORMAT CSV, HEADER);
複製代碼
儘管 pgAdmin 只是一個用於查看和配置數據庫的工具,但必須配置其與數據庫的鏈接。這能夠經過可視化工具中的 add server
指令完成。這裏須要注意的是,主機名(the hostname)是咱們在 YML 文件中配置的 container_name
這一參數的名稱,即 some-postgres
。一樣地,密碼也已經在 YML 文件中指定了,即 mysecret
。
另外一種方法是經過在 JSON 文件中指定這些配置(除了密碼以外的全部配置),經過這種方式能夠免去大量的單擊和輸入操做。爲了不手動配置 pgAdmin 到 Postgres 的鏈接,咱們須要將該 JSON 文件映射到容器 /pgadmin4/servers.json
上(在示例 YML 文件中的第 22 行)。
設置文件能夠指定 pgAdmin 和 Postgres 之間的多個鏈接(以不一樣用戶的身份鏈接或者鏈接到多個不一樣的數據庫)。下面是隻有一個數據庫鏈接的示例。
{
"Servers": {
"1": {
"Name": "my-postgres",
"Group": "Servers",
"Port": 5432,
"Username": "postgres",
"Host": "some-postgres",
"SSLMode": "prefer",
"MaintenanceDB": "postgres"
}
}
}
複製代碼
container_name
參數僅僅只表示一個名字。可是 pgAdmin 將使用這個名稱訪問 5432 端口上的數據庫。緣由以下圖所示。這兩個容器經過私有網絡相互鏈接,所以能夠經過它們的主機名(容器名)也就是 some-postgres
和 some-pgadmin
相互訪問。然而,你的主機(也就是你的計算機和 web 瀏覽器)只能訪問容器對外暴露的 5432 端口和 8080 端口,所以你能夠經過 localhost:5432
和 localhost:8080
訪問它們。
內部網絡的名稱能夠在 compose 文件中指定,可是爲一個從未被代碼引用的網絡命名沒有任何價值!若是你仍是好奇,能夠隨時查看你的私人及臨時網絡的名稱。在下面的代碼片斷中,我從桌面運行了 Docker Compose,所以將該網絡命名爲 desktop_default
。
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
23a6be9b8021 bridge bridge local
49a120440f88 desktop_default bridge local
44a949b56fa7 host host local
3892b16dca2d none null local
複製代碼
在這裏,我必須認可我在前言中過於簡化了命令操做,但只是稍微簡化了一點。
爲了啓動容器,可使用 docker-compose up -d
。-d
參數指定這是一個 detached
模式,它將會在後臺運行,而且不會影響你在命令提示符中執行其餘命令。
$ docker-compose up -d
Creating network "desktop_default" with the default driver
Creating some-postgres ... done
Creating some-pgadmin ... done
$
複製代碼
爲了關閉並刪除容器,你可使用 docker-compose down -v
。-v
參數表示刪除容器在運行時使用的 volume。這個不會刪除計算機映射到容器上的目錄。
$ docker-compose down -v
Stopping some-pgadmin ... done
Stopping some-postgres ... done
Removing some-pgadmin ... done
Removing some-postgres ... done
Removing network desktop_default
複製代碼
隨着時間的推移,若是不使用 -v
標誌,就會累積沒必要要的 volume。你可使用 docker volume ls
來驗證這一點。
若是要調試一個沒有正確啓動的容器,請使用 docker logs [container_name]
。例如,因爲 init 目錄中的一個 SQL 文件中出現錯誤,數據庫可能沒法正確初始化。經過執行 docker logs some-postgres
命令,能夠生成容器啓動時記錄的日誌,經過對該日誌的查閱,我在一個特殊命名的 SQL 文件中發現一個錯誤:
/usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/broken.sql
ERROR: syntax error at end of input at character 34
STATEMENT: CREATE TABLE Songs(id, name, year
psql:/docker-entrypoint-initdb.d/broken.sql:1: ERROR: syntax error at end of input
LINE 1: CREATE TABLE Song(id, name, year
複製代碼
日誌告訴我在 broken.sql
文件的第 1 行有一個錯誤。該命令缺乏右括號和分號。我能夠修復這個錯誤,並使用 down
和 up
來驗證。
使用 localhost 做爲 YML 文件中指定的主機名和密碼,鏈接到數據庫很容易。
import psycopg2
# connect to DB
conn = psycopg2.connect(host="localhost", dbname="postgres", user="postgres",
password="mysecret")
cursor = conn.cursor()
# execute SQL commands in SQL file
cursor.execute(open("emp.sql", "r").read())
# retrieve data from the database
cursor.execute("SELECT * FROM Employee")
print(cursor.fetchall())
複製代碼
簡單的訪問 http://localhost:8080 便可進入登陸界面,使用你在 docker-compose.yml
文件中定義的用戶名和密碼登陸便可(在咱們的示例中是 user@domain.com
和 admin
)。
若是你使用的是本文以前討論的 servers.json
文件來指定鏈接細節,你將會在展開用戶界面左側的導航樹時,收到系統要求你輸入 Postgres 數據庫的密碼的提示。在咱們示例的 docker-compose.yml
文件中,這個密碼是 mysecret
。若是你並無建立 servers.json
文件或文件中有錯誤,你就必須手動添加服務器。
如今,你應該可以查看和操做數據庫了。
有時候,開發者須要一個熟悉的命令行。Docker 使得訪問 PSQL 和執行高級用戶命令等操做變得更加容易。執行下面的命令進入 PSQL 命令行。
鏈接後,你就能夠執行全部 PSQL 命令,例如,輸入 \i
用於導入外部數據庫,輸入 \dt
顯示數據表的描述,輸入 \df
顯示函數的描述。想要退出,可使用 \q
命令。
$ docker exec -it some-postgres psql -U postgres
psql (9.6.12)
Type "help" for help.
postgres=# \dt
List of relations
Schema | Name | Type | Owner
--------+--------------+-------+----------
public | peak | table | postgres
public | climb | table | postgres
public | climber | table | postgres
複製代碼
pgAdmin 是 PostgreSQL 最多見的 GUI 管理工具,但咱們還有其餘選擇。Adminer 的使用更加簡單,而且你可能已經擁有使用它的經驗了,由於它支持多種風格的 SQL。若是你是剛開始使用 PostgreSQL 或者只有很是簡單的需求,那麼它多是一個更合適你的工具。
在登陸界面上,設置主機名爲 some-postgres
,密碼爲 mysecret
。
要在你的環境中用 Adminer 替換 pgAdmin,你須要在 docker-compose.yml
中替換幾行有關 pgAdmin 容器的定義。
adminer:
image: adminer
container_name: some-adminer
ports:
- 8080:8080
deploy:
restart_policy:
condition: on-failure
max_attempts: 3
複製代碼
全部優秀的開發者都依賴於產品文檔和其餘人員的經驗。這是我在建立工做流程和編寫本文時引用的參考資料。
若是發現譯文存在錯誤或其餘須要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可得到相應獎勵積分。文章開頭的 本文永久連接 即爲本文在 GitHub 上的 MarkDown 連接。
掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。