在Docker中能使用資料庫嗎? | Baeldung

banq發表於2021-05-07

在本文中,我們將回顧如何與Docker一起使用來管理資料庫。
 
在本地執行Docker映像/映象
首先,我們必須安裝Docker Desktop。然後,我們應該從Docker Hub找到我們資料庫的現有映像。找到它後,我們將從頁面右上角選擇docker pull命令。
這裡使用PostgreSQL,因此命令為:

$docker pull postgres


當下載完成後,這個執行命令將建立一個Docker容器內正在執行的資料庫。對於PostgreSQL,必須使用-e選項指定POSTGRES_PASSWORD環境變數:

$docker run -e POSTGRES_PASSWORD=password postgres

接下來,我們將測試資料庫容器連線。
讓我們嘗試一個簡單的測試。我們將使用JDBC資料來源將本地Java專案連線到資料庫。連線字串應使用localhost上的預設PostgreSQL埠5432:

jdbc:postgresql://localhost:5432/postgres?user=postgres&password=password


錯誤是通知我們該埠未開啟。實際上,資料庫正在偵聽來自容器網路內部的連線,而我們的Java專案正在其外部執行。要修復它,我們需要將容器埠對映到我們的本地主機埠。我們將為PostgreSQL使用預設埠5432:

$docker run -p 5432:5432 -e POSTGRES_PASSWORD=password postgres


連線現在正在工作,並且我們應該能夠使用我們的JDBC資料來源。
現在,我們可以從外殼連線到我們的資料庫,例如,執行初始化指令碼。
首先,讓我們找到正在執行的容器ID:

$docker ps
CONTAINER ID   IMAGE      COMMAND                  CREATED          STATUS          PORTS                    NAMES
65d9163eece2   postgres   "docker-entrypoint.s…"   27 minutes ago   Up 27 minutes   0.0.0.0:5432->5432/tcp   optimistic_hellman

$docker exec -it 65d9163eece2 bash

最後,我們可以使用命令列客戶端連線到資料庫例項,並貼上我們的SQL指令碼:

root@65d9163eece2:/# psql -U postgres
postgres=CREATE DATABASE TEST;
CREATE TABLE PERSON(
  ID INTEGER PRIMARY KEY,
  FIRST_NAME VARCHAR(1000),
  LAST_NAME VARCHAR(1000)
);
...

例如,如果要載入較大的轉儲檔案,則必須避免複製貼上。我們可以直接從主機執行import命令,而不是使用docker exec命令:

$docker exec 65d9163eece2 psql -U postgres < dump.sql
 

使用Docker卷持久化資料
只要我們使用相同的容器,我們的基本設定就可以使用,每次需要重啟時,docker容器都會停止/啟動。如果再次使用docker run,則會建立一個新的空容器,並且我們將丟失資料。實際上,預設情況下,Docker將資料保留在臨時目錄中。
現在,我們將學習如何修改此卷對映。
第一項任務是檢查我們的容器,以檢視資料庫使用了哪個卷:

$docker inspect -f "{{ .Mounts }}" 65d9163eece2
<p class="indent">[{volume f1033d3 /var/lib/docker/volumes/f1033d3/_data /var/lib/postgresql/data local true }] 


我們可以看到卷f1033d3已將容器目錄/ var / lib / postgresql / data對映到在主機檔案系統中建立的臨時目錄/ var / lib / docker / volumes / f1033d3 / _data。

我們必須透過docker run命令中新增-v選項來修改此對映:

$docker run -v C:\docker-db-volume:/var/lib/postgresql/data -e POSTGRES_PASSWORD=password postgres


現在,我們可以看到在C:\ docker-db-volume目錄中建立的資料庫檔案。我們可以在這篇專門的文章中找到高階卷配置。

另外,我們可能希望在團隊成員之間或在不同環境中共享配置。我們可以使用Docker Compose檔案,該檔案每次都會建立新的容器。在這種情況下,必須使用卷。
下一章將介紹生產環境中Docker資料庫的具體用法。
 

在生產中使用Docker
Docker Compose非常適合共享配置並將容器作為無狀態服務進行管理。如果服務失敗或無法處理工作量,我們可以將Docker Compose配置為自動建立新容器。這對於為REST後端構建生產叢集非常有用,該叢集在設計上是無狀態的。
但是,資料庫是有狀態的,並且它們的管理更為複雜:讓我們回顧一下不同的上下文。
讓我們假設我們正在構建一個非關鍵環境,用於測試或生產,該環境可以容忍停機時間(在部署,備份或故障期間)。
在這種情況下,我們不需要高可用性叢集,我們可以簡單地將Docker Compose用於單例項資料庫:

  • 我們可以使用簡單的捲進行資料儲存,因為容器將在同一臺機器上執行
  • 我們可以限制它使用全域性模式一次執行一個容器

version: '3'
services:       
  database:
    image: 'postgres'
    deploy:
      mode: global
    environment:
      - POSTGRES_PASSWORD=password
    ports:
      - "5432:5432"
    volumes:
      - "C:/docker-db-volume:/var/lib/postgresql/data"


使用此配置,我們的產品將一次僅建立一個容器,並重新使用C:\ docker-db-volume目錄中的資料檔案。
但是,在此配置中進行定期備份甚至更為重要。如果發生配置錯誤,該目錄可能會被container擦除或破壞。

現在讓我們假設我們的生產環境至關重要。
在這種情況下,諸如Docker SwarmKubernetes之類的編排工具對於無狀態容器是有好處的:它們提供垂直和水平群集,並具有負載平衡,故障轉移和自動擴充套件功能。
不幸的是,由於我們的資料庫容器是有狀態的,因此這些解決方案沒有提供卷複製機制。
另一方面,構建自制配置很危險,因為它可能導致嚴重的資料丟失。例如:
  • 對卷使用NFS或NAS之類的共享儲存不能保證在另一個例項中重新啟動資料庫時不會丟失資料
  • 在主從叢集上,讓Docker業務流程選擇多個主節點是一個常見錯誤,這將導致資料損壞

到目前為止,我們的不同選擇是:
  • 不要將Docker用於資料庫,而應實現特定於資料庫或硬體的複製機制
  • 不要將Docker用於資料庫,而訂閱OpenShift,Amazon AWS或Azure之類的平臺即服務解決方案
  • 使用特定於Docker的複製機制,例如KubeDBPortworx


最後,我們得出結論,當在高可用性環境中使用Docker時,存在缺點。因此,應避免使用它或與專門用於資料庫群集的解決方案結合使用。

相關文章