如何在Docker中處理數據庫?

1.概述

在本文中,我們將回顧如何與Docker一起使用來管理數據庫。

在第一章中,我們將介紹在本地計算機上數據庫的安裝。然後,我們將發現數據持久性如何跨容器工作。

總之,我們將討論在Docker生產環境中實現數據庫的可靠性。

2.在本地運行Docker映像

2.1 從標準Docker映像開始

首先,我們必須安裝Docker Desktop 。**然後,我們應該從Docker Hub找到我們數據庫的現有映像**。找到它後,我們將從頁面右上角docker pull

在本教程中,我們將使用PostgreSQL,因此命令為:

$docker pull postgres

下載完成後, docker run命令將在Docker容器中創建一個正在運行的數據庫。對於PostgreSQL,必須使用-e選項POSTGRES_PASSWORD

$docker run -e POSTGRES_PASSWORD=password postgres

接下來,我們將測試數據庫容器連接。

2.2 將Java項目連接到數據庫

讓我們嘗試一個簡單的測試。我們將使用JDBC數據源將本地Java項目連接到數據庫。連接字符串應使用localhost5432

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

錯誤應通知我們該端口未打開。實際上,數據庫正在偵聽來自容器網絡內部的連接,而我們的Java項目正在其外部運行。

要修復它,我們需要將容器端口映射到我們的localhost端口。我們將為PostgreSQL使用默認端口5432:

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

該連接現在正在工作,並且我們應該能夠使用我們的JDBC數據源。

2.3 運行SQL腳本

現在,我們可以從外殼連接到我們的數據庫,例如,運行初始化腳本。

首先,讓我們找到正在運行的容器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

然後,我們將運行帶有交互式-it docker exec命令,以在容器內運行外殼程序

$docker exec -it 65d9163eece2 bash

最後,我們可以使用命令行客戶端連接到數據庫實例,並粘貼我們的SQL腳本:

[email protected]:/# 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

3.使用Docker卷持久化數據

3.1 為什麼我們需要卷Volume?

只要我們使用相同的容器,我們的基本設置就可以使用,每次需要重啟時docker container stop/start如果docker run ,則會創建一個新的空容器,並且我們將丟失數據。實際上,默認情況下,Docker將數據保留在臨時目錄中。

現在,我們將學習如何修改此體積映射。

3.2 Docker卷設置

第一項任務是檢查我們的容器,以查看數據庫使用了哪個卷:

$docker inspect -f "{{ .Mounts }}" 65d9163eece2

 [{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

我們必須通過在第2.1章中使用docker run命令中-v選項來修改此映射:

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

現在,我們可以看到在C:\docker-db-volume目錄中創建的數據庫文件。我們可以在這篇專門的文章中找到高級卷配置。

結果,每次我們使用docker run命令時,數據將與不同的容器執行一起保留。

另外,我們可能希望在團隊成員之間或在不同環境中共享配置。我們可以使用Docker Compose文件,該文件每次都會創建新的容器。在這種情況下,必須使用卷。

下一章將介紹生產環境中Docker數據庫的具體用法。

4.在生產中使用Docker

Docker Compose非常適合共享配置並將容器作為無狀態服務進行管理。如果服務失敗或無法處理工作量,我們可以將Docker Compose配置為自動創建新容器。這對於為REST後端構建生產集群非常有用,該集群在設計上是無狀態的。

但是,數據庫是有狀態的,並且它們的管理更為複雜:讓我們回顧一下不同的上下文。

4.1 單實例數據庫

讓我們假設我們正在構建一個非關鍵環境,用於測試或生產,該環境可以容忍停機時間(在部署,備份或故障期間)。

在這種情況下,我們不需要高可用性集群,我們可以簡單地將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擦除或破壞

4.2 集群的數據庫

現在讓我們假設我們的生產環境至關重要。

在這種情況下,諸如Docker SwarmKubernetes之類的編排工具對於無狀態容器是有好處的:它們提供垂直和水平群集,並具有負載平衡,故障轉移和自動擴展功能。

不幸的是,由於我們的數據庫容器是有狀態的,因此這些解決方案沒有提供卷複製機制。

另一方面,構建自製配置很危險,因為它可能導致嚴重的數據丟失。例如:

  • 對卷使用NFS或NAS之類的共享存儲不能保證在另一個實例中重新啟動數據庫時不會丟失數據
  • 在主從集群上,讓Docker業務流程選擇多個主節點是一個常見錯誤,這將導致數據損壞

到目前為止,我們的不同選擇是:

  • 不要將Docker用於數據庫,而應實現特定於數據庫或硬件的複制機制
  • 請勿將Docker用於數據庫,而訂閱OpenShift,Amazon AWS或Azure等平台即服務解決方案
  • 使用特定於Docker的複制機制,例如KubeDBPortworx

5.結論

在本文中,我們回顧了適用於開發,測試和非關鍵生產的基本配置。

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