以下大多數範例命令都使用 container-registry.oracle.com/mysql/community-server
作為 Docker 映像 (例如,docker pull 和 docker run 命令);如果您的映像來自其他儲存庫,請變更它—例如,將其取代為 container-registry.oracle.com/mysql/enterprise-server
以用於從 Oracle Container Registry (OCR) 下載的 MySQL Enterprise Edition 映像,或取代為 mysql/enterprise-server
以用於從 My Oracle Support 下載的 MySQL Enterprise Edition 映像。
針對 Docker 最佳化的 MySQL 安裝
MySQL 的 Docker 映像已針對程式碼大小進行最佳化,這表示它們僅包含預期與在 Docker 容器中執行 MySQL 執行個體的大多數使用者相關的重要元件。MySQL Docker 安裝與一般的非 Docker 安裝在以下方面不同
僅包含有限數量的二進位檔案。
所有二進位檔案都已剝離;它們不包含偵錯資訊。
使用者對 Docker 容器執行的任何軟體更新或安裝 (包括 MySQL 元件的更新或安裝) 都可能與 Docker 映像所建立的最佳化 MySQL 安裝衝突。Oracle 不為在此類變更後的容器,或從變更後的 Docker 映像建立的容器中執行的 MySQL 產品提供支援。
設定 MySQL Server
當您啟動 MySQL Docker 容器時,您可以透過 docker run 命令將組態選項傳遞至伺服器。例如
docker run --name mysql1 -d container-registry.oracle.com/mysql/community-server:tag --character-set-server=utf8mb4 --collation-server=utf8mb4_col
此命令會以 utf8mb4
作為預設字元集和 utf8mb4_col
作為資料庫的預設定序來啟動 MySQL Server。
設定 MySQL Server 的另一種方法是準備一個組態檔案,並將其掛載到容器內伺服器組態檔案的位置。如需詳細資訊,請參閱持續保存資料和組態變更。
持續保存資料和組態變更
Docker 容器原則上是暫時性的,如果容器被刪除或損壞,任何資料或組態都將遺失 (請參閱此處的討論)。Docker 磁碟區提供了一種機制來持續保存在 Docker 容器內建立的資料。在初始化時,MySQL Server 容器會為伺服器資料目錄建立一個 Docker 磁碟區。容器上 docker inspect 命令的 JSON 輸出包含一個 Mount
金鑰,其值提供有關資料目錄磁碟區的資訊
$> docker inspect mysql1
...
"Mounts": [
{
"Type": "volume",
"Name": "4f2d463cfc4bdd4baebcb098c97d7da3337195ed2c6572bc0b89f7e845d27652",
"Source": "/var/lib/docker/volumes/4f2d463cfc4bdd4baebcb098c97d7da3337195ed2c6572bc0b89f7e845d27652/_data",
"Destination": "/var/lib/mysql",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
...
輸出顯示主機上持續保存資料的來源目錄 /var/lib/docker/volumes/4f2d463cfc4bdd4baebcb098c97d7da3337195ed2c6572bc0b89f7e845d27652/_data
已掛載在 /var/lib/mysql
,即容器內的伺服器資料目錄。
保存資料的另一種方法是在建立容器時,使用 --mount
選項繫結掛載主機目錄。相同的技術可用於持續保存伺服器的組態。以下命令會建立 MySQL Server 容器並繫結掛載資料目錄和伺服器組態檔案
docker run --name=mysql1 \
--mount type=bind,src=/path-on-host-machine/my.cnf,dst=/etc/my.cnf \
--mount type=bind,src=/path-on-host-machine/datadir,dst=/var/lib/mysql \
-d container-registry.oracle.com/mysql/community-server:tag
此命令會在 /etc/my.cnf
(容器內的伺服器組態檔案) 掛載
,並在 path-on-host-machine/my.cnf
/var/lib/mysql
(容器內的資料目錄) 掛載
。繫結掛載要能運作,必須滿足以下條件path-on-host-machine/datadir
組態檔案
必須已存在,而且必須包含使用者path-on-host-machine/my.cnf
mysql
啟動伺服器的規格[mysqld] user=mysql
您也可以在檔案中加入其他伺服器組態選項。
資料目錄
必須已經存在。為了讓伺服器初始化能順利進行,此目錄必須為空。您也可以掛載預先填入資料的目錄,並以此啟動伺服器;但是,您必須確保啟動 Docker 容器時的配置與建立資料的伺服器相同,並且在啟動容器時掛載任何所需的主機檔案或目錄。path-on-host-machine/datadir
執行額外的初始化腳本
如果有任何您想在資料庫建立後立即執行的 .sh
或 .sql
腳本,您可以將它們放入主機目錄,然後將該目錄掛載到容器內的 /docker-entrypoint-initdb.d/
。例如:
docker run --name=mysql1 \
--mount type=bind,src=/path-on-host-machine/scripts/,dst=/docker-entrypoint-initdb.d/ \
-d container-registry.oracle.com/mysql/community-server:tag
從另一個 Docker 容器連線到 MySQL
透過設定 Docker 網路,您可以允許多個 Docker 容器彼此通訊,以便另一個 Docker 容器中的客戶端應用程式可以存取伺服器容器中的 MySQL 伺服器。首先,建立一個 Docker 網路:
docker network create my-custom-net
然後,當您建立並啟動伺服器和客戶端容器時,請使用 --network
選項將它們放在您建立的網路上。例如:
docker run --name=mysql1 --network=my-custom-net -d container-registry.oracle.com/mysql/community-server
docker run --name=myapp1 --network=my-custom-net -d myapp
myapp1
容器接著可以使用 mysql1
主機名稱連線到 mysql1
容器,反之亦然,因為 Docker 會自動為給定的容器名稱設定 DNS。在以下範例中,我們從 myapp1
容器內部執行 mysql 客戶端,以連線到其自身容器中的主機 mysql1
:
docker exec -it myapp1 mysql --host=mysql1 --user=myuser --password
如需其他容器網路技術,請參閱 Docker 文件中的Docker 容器網路章節。
伺服器錯誤日誌
當 MySQL 伺服器首次使用您的伺服器容器啟動時,如果符合以下任一條件,則不會產生伺服器錯誤日誌:
已掛載來自主機的伺服器設定檔,但該檔案不包含系統變數
log_error
(請參閱持久化資料和設定變更,瞭解如何繫結掛載伺服器設定檔)。尚未掛載來自主機的伺服器設定檔,但 Docker 環境變數
MYSQL_LOG_CONSOLE
為true
(這是 MySQL 8.4 伺服器容器的變數預設狀態)。然後,MySQL 伺服器的錯誤日誌會重新導向到stderr
,因此錯誤日誌會進入 Docker 容器的日誌,並且可以使用 docker logsmysqld-container
命令檢視。
若要讓 MySQL 伺服器在符合任一條件時產生錯誤日誌,請使用 --log-error
選項來設定伺服器,以便在容器內的特定位置產生錯誤日誌。若要持久化錯誤日誌,請將主機檔案掛載到容器內錯誤日誌的位置,如持久化資料和設定變更中所述。但是,您必須確保容器內的 MySQL 伺服器具有寫入權限才能寫入掛載的主機檔案。
將 MySQL Enterprise Backup 與 Docker 搭配使用
MySQL Enterprise Backup 是 MySQL 伺服器的商業授權備份公用程式,可與MySQL Enterprise Edition 搭配使用。MySQL Enterprise Backup 包含在 MySQL Enterprise Edition 的 Docker 安裝中。
在以下範例中,我們假設您已經在 Docker 容器中執行 MySQL 伺服器(請參閱第 2.5.6.1 節「使用 Docker 部署 MySQL 伺服器的基本步驟」,瞭解如何使用 Docker 啟動 MySQL 伺服器執行個體)。為了讓 MySQL Enterprise Backup 備份 MySQL 伺服器,它必須能夠存取伺服器的資料目錄。例如,這可以透過在您啟動伺服器時將主機目錄繫結掛載到 MySQL 伺服器的資料目錄來實現。
docker run --name=mysqlserver \
--mount type=bind,src=/path-on-host-machine/datadir/,dst=/var/lib/mysql \
-d mysql/enterprise-server:8.4
透過此命令,MySQL 伺服器會使用 MySQL Enterprise Edition 的 Docker 映像啟動,並且主機目錄 /path-on-host-machine/datadir/
已掛載到伺服器容器內的伺服器資料目錄 (/var/lib/mysql
)。我們也假設在伺服器啟動後,已設定所需的權限,以便讓 MySQL Enterprise Backup 存取伺服器(詳細資訊請參閱授予備份管理員 MySQL 權限)。請使用以下步驟來備份和還原 MySQL 伺服器執行個體。
若要使用 Docker 的 MySQL Enterprise Backup 備份在 Docker 容器中執行的 MySQL 伺服器執行個體,請按照此處列出的步驟進行:
在執行 MySQL 伺服器容器的相同主機上,啟動另一個具有 MySQL Enterprise Edition 映像的容器,以使用 MySQL Enterprise Backup 命令
backup-to-image
執行備份。使用我們在上一個步驟中建立的繫結掛載,提供對伺服器資料目錄的存取權。此外,請將主機目錄(在此範例中為/path-on-host-machine/backups/
)掛載到容器中備份的儲存資料夾(範例中為/data/backups
),以便持久化我們正在建立的備份。以下是此步驟的範例命令,其中 MySQL Enterprise Backup 是使用從 My Oracle Support 下載的 Docker 映像啟動的:$> docker run \ --mount type=bind,src=/path-on-host-machine/datadir/,dst=/var/lib/mysql \ --mount type=bind,src=/path-on-host-machine/backups/,dst=/data/backups \ --rm mysql/enterprise-server:8.4 \ mysqlbackup -umysqlbackup -ppassword --backup-dir=/tmp/backup-tmp --with-timestamp \ --backup-image=/data/backups/db.mbi backup-to-image
務必檢查 mysqlbackup 的輸出結尾,以確保備份已順利完成。
容器會在備份作業完成後結束,而且使用用於啟動它的
--rm
選項,容器會在結束後移除。已建立映像備份,而且可以在上一個步驟中掛載的用於儲存備份的主機目錄中找到,如下所示:$> ls /tmp/backups db.mbi
若要使用 Docker 的 MySQL Enterprise Backup 還原 Docker 容器中的 MySQL 伺服器執行個體,請按照此處列出的步驟進行:
停止 MySQL 伺服器容器,這也會停止內部執行的 MySQL 伺服器:
docker stop mysqlserver
在主機上,刪除 MySQL 伺服器資料目錄繫結掛載中的所有內容:
rm -rf /path-on-host-machine/datadir/*
啟動具有 MySQL Enterprise Edition 映像的容器,以便使用 MySQL Enterprise Backup 命令
copy-back-and-apply-log
執行還原。繫結掛載伺服器的資料目錄和備份的儲存資料夾,就像我們在備份伺服器時所做的那樣:$> docker run \ --mount type=bind,src=/path-on-host-machine/datadir/,dst=/var/lib/mysql \ --mount type=bind,src=/path-on-host-machine/backups/,dst=/data/backups \ --rm mysql/enterprise-server:8.4 \ mysqlbackup --backup-dir=/tmp/backup-tmp --with-timestamp \ --datadir=/var/lib/mysql --backup-image=/data/backups/db.mbi copy-back-and-apply-log mysqlbackup completed OK! with 3 warnings
容器會在備份作業完成後結束,並顯示訊息「
mysqlbackup completed OK!
」,而且使用啟動時使用的--rm
選項,容器會在結束後移除。使用以下命令重新啟動伺服器容器,這也會重新啟動已還原的伺服器:
docker restart mysqlserver
或者,在新還原的資料目錄上啟動新的 MySQL 伺服器,如下所示:
docker run --name=mysqlserver2 \ --mount type=bind,src=/path-on-host-machine/datadir/,dst=/var/lib/mysql \ -d mysql/enterprise-server:8.4
登入伺服器以檢查伺服器是否正在使用已還原的資料執行。
將 mysqldump 與 Docker 搭配使用
除了使用 MySQL Enterprise Backup 備份在 Docker 容器中執行的 MySQL 伺服器之外,您還可以透過使用 mysqldump 公用程式(在 Docker 容器內執行)來執行伺服器的邏輯備份。
以下指示假設您已經在 Docker 容器中執行 MySQL 伺服器,而且在第一次啟動容器時,主機目錄 /path-on-host-machine/datadir/
已掛載到伺服器的資料目錄 /var/lib/mysql
(詳細資訊請參閱將主機目錄繫結掛載到 MySQL 伺服器的資料目錄),其中包含 mysqldump 和 mysql 可以連線到伺服器的 Unix Socket 檔案。我們也假設在伺服器啟動後,已建立具有適當權限的使用者(此範例中為 admin
),mysqldump 可以使用該使用者存取伺服器。請使用以下步驟來備份和還原 MySQL 伺服器資料:
使用 Docker 的 mysqldump 備份 MySQL 伺服器資料:
在執行 MySQL 伺服器容器的相同主機上,啟動另一個具有 MySQL 伺服器映像的容器,以使用 mysqldump 公用程式執行備份(請參閱公用程式的文件,瞭解其功能、選項和限制)。透過繫結掛載
/path-on-host-machine/datadir/
,提供對伺服器資料目錄的存取權。此外,請將主機目錄(在此範例中為/path-on-host-machine/backups/
)掛載到容器內備份的儲存資料夾(此範例中使用/data/backups
),以便持久化您正在建立的備份。以下是使用此設定備份伺服器上所有資料庫的範例命令:$> docker run --entrypoint "/bin/sh" \ --mount type=bind,src=/path-on-host-machine/datadir/,dst=/var/lib/mysql \ --mount type=bind,src=/path-on-host-machine/backups/,dst=/data/backups \ --rm container-registry.oracle.com/mysql/community-server:8.4 \ -c "mysqldump -uadmin --password='password' --all-databases > /data/backups/all-databases.sql"
在命令中,使用
--entrypoint
選項,以便在啟動容器後呼叫系統 Shell,並使用-c
選項來指定要在 Shell 中執行的 mysqldump 命令,其輸出會重新導向到備份目錄中的檔案all-databases.sql
。容器會在備份作業完成後結束,而且使用用於啟動它的
--rm
選項,容器會在結束後移除。已建立邏輯備份,而且可以在掛載用於儲存備份的主機目錄中找到,如下所示:$> ls /path-on-host-machine/backups/ all-databases.sql
使用 Docker 的 mysqldump 還原 MySQL 伺服器資料:
請確保您在容器中執行 MySQL 伺服器,您想要將備份的資料還原到該伺服器。
啟動具有 MySQL 伺服器映像的容器,以便使用 mysql 客戶端執行還原。繫結掛載伺服器的資料目錄,以及包含備份的儲存資料夾:
$> docker run \ --mount type=bind,src=/path-on-host-machine/datadir/,dst=/var/lib/mysql \ --mount type=bind,src=/path-on-host-machine/backups/,dst=/data/backups \ --rm container-registry.oracle.com/mysql/community-server:8.4 \ mysql -uadmin --password='password' -e "source /data/backups/all-databases.sql"
容器會在備份作業完成後結束,而且使用啟動時使用的
--rm
選項,容器會在結束後移除。登入伺服器以檢查已還原的資料現在是否在伺服器上。
已知問題
當使用伺服器系統變數
audit_log_file
來設定稽核日誌檔名時,請使用loose
選項修飾符;否則,Docker 無法啟動伺服器。
Docker 環境變數
當您建立 MySQL 伺服器容器時,您可以使用 --env
選項(簡寫為 -e
)並指定一個或多個環境變數來設定 MySQL 執行個體。如果已掛載的資料目錄不是空的,則不會執行伺服器初始化,在這種情況下,設定任何這些變數都無效(請參閱持久化資料和組態變更),並且在容器啟動期間不會修改目錄的現有內容,包括伺服器設定。
以下列出可用於設定 MySQL 執行個體的環境變數
布林變數,包括
MYSQL_RANDOM_ROOT_PASSWORD
、MYSQL_ONETIME_PASSWORD
、MYSQL_ALLOW_EMPTY_PASSWORD
和MYSQL_LOG_CONSOLE
,只要設定為任何非零長度的字串,就會被設為 true。因此,將它們設定為例如 “0”、“false” 或 “no” 並不會將它們設為 false,實際上是將它們設為 true。這是一個已知問題。MYSQL_RANDOM_ROOT_PASSWORD
:當此變數為 true 時(除非設定了MYSQL_ROOT_PASSWORD
或將MYSQL_ALLOW_EMPTY_PASSWORD
設為 true,否則為預設狀態),當 Docker 容器啟動時,會為伺服器的 root 使用者產生一個隨機密碼。該密碼會列印到容器的stdout
,並且可以透過查看容器的日誌找到(請參閱 啟動 MySQL 伺服器執行個體)。MYSQL_ONETIME_PASSWORD
:當此變數為 true 時(除非設定了MYSQL_ROOT_PASSWORD
或將MYSQL_ALLOW_EMPTY_PASSWORD
設為 true,否則為預設狀態),root 使用者的密碼會設定為過期,必須先變更才能正常使用 MySQL。MYSQL_DATABASE
:此變數允許您指定要在映像啟動時建立的資料庫名稱。如果使用MYSQL_USER
和MYSQL_PASSWORD
提供使用者名稱和密碼,則會建立該使用者並授予對此資料庫的超級使用者存取權限(相當於GRANT ALL
)。指定的資料庫是由 CREATE DATABASE IF NOT EXIST 陳述式所建立,因此如果資料庫已存在,則此變數無效。MYSQL_USER
、MYSQL_PASSWORD
:這些變數會一起使用,以建立使用者並設定該使用者的密碼,並且該使用者會被授予由MYSQL_DATABASE
變數指定的資料庫的超級使用者權限。必須設定MYSQL_USER
和MYSQL_PASSWORD
才能建立使用者 — 如果未設定其中任何一個變數,則會忽略另一個變數。如果兩個變數都已設定,但未設定MYSQL_DATABASE
,則會建立該使用者,但不具任何權限。注意無需使用此機制來建立 root 超級使用者,預設會建立 root 超級使用者,其密碼由
MYSQL_ROOT_PASSWORD
和MYSQL_RANDOM_ROOT_PASSWORD
描述中討論的其中一種機制設定,除非MYSQL_ALLOW_EMPTY_PASSWORD
為 true。MYSQL_ROOT_HOST
:預設情況下,MySQL 會建立'root'@'localhost'
帳戶。根據 從容器內部連線到 MySQL 伺服器 中的描述,只能從容器內部連線到此帳戶。若要允許從其他主機進行 root 連線,請設定此環境變數。例如,值172.17.0.1
(預設的 Docker 閘道 IP)允許從執行容器的主機進行連線。此選項僅接受一個條目,但允許使用萬用字元(例如,MYSQL_ROOT_HOST=172.*.*.*
或MYSQL_ROOT_HOST=%
)。MYSQL_LOG_CONSOLE
:當此變數為 true 時(對於 MySQL 8.4 伺服器容器,這是預設狀態),MySQL 伺服器的錯誤日誌會重新導向至stderr
,因此錯誤日誌會進入 Docker 容器的日誌,並且可以使用 docker logsmysqld-container
命令檢視。注意如果已從主機掛載伺服器設定檔,則此變數無效(請參閱 持久化資料和組態變更 中關於綁定掛載設定檔的說明)。
MYSQL_ROOT_PASSWORD
:此變數指定要為 MySQL root 帳戶設定的密碼。警告在命令列上設定 MySQL root 使用者密碼是不安全的。作為明確指定密碼的替代方法,您可以使用密碼檔案的容器檔案路徑來設定變數,然後從主機掛載一個包含密碼的檔案到容器檔案路徑。這仍然不是非常安全,因為密碼檔案的位置仍然會暴露。最好使用
MYSQL_RANDOM_ROOT_PASSWORD
和MYSQL_ONETIME_PASSWORD
都為 true 的預設設定。MYSQL_ALLOW_EMPTY_PASSWORD
。將其設定為 true 可允許容器在 root 使用者的密碼為空白的情況下啟動。警告將此變數設定為 true 是不安全的,因為它會讓您的 MySQL 執行個體完全不受保護,允許任何人取得完整的超級使用者存取權限。最好使用
MYSQL_RANDOM_ROOT_PASSWORD
和MYSQL_ONETIME_PASSWORD
都為 true 的預設設定。