以下大多數的範例命令都使用 container-registry.oracle.com/mysql/community-server
作為 Docker 映像 (就像 docker pull 和 docker run 命令一樣);如果您的映像來自其他儲存庫,請變更它—例如,針對從 Oracle Container Registry (OCR) 下載的 MySQL 企業版映像,請將其替換為 container-registry.oracle.com/mysql/enterprise-server
,或針對從 My Oracle Support 下載的 MySQL 企業版映像,請替換為 mysql/enterprise-server
。
適用於 Docker 的最佳化 MySQL 安裝
MySQL 的 Docker 映像針對程式碼大小進行了最佳化,這表示它們只包含預期與大多數在 Docker 容器中執行 MySQL 執行個體的使用者相關的重要元件。MySQL Docker 安裝在下列方面與常見的非 Docker 安裝不同
僅包含有限數量的二進位檔。
所有二進位檔都已剝除;它們不包含偵錯資訊。
使用者對 Docker 容器執行的任何軟體更新或安裝 (包括 MySQL 元件的更新或安裝) 可能會與 Docker 映像建立的最佳化 MySQL 安裝發生衝突。Oracle 不會針對在此類已變更的容器中執行的 MySQL 產品,或從已變更的 Docker 映像建立的容器提供支援。
設定 MySQL 伺服器
當您啟動 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 伺服器。
設定 MySQL 伺服器的另一種方式是準備組態檔,並將其掛載在容器內伺服器組態檔的位置。如需詳細資訊,請參閱保存資料和組態變更。
保存資料和組態變更
原則上,Docker 容器是暫時性的,而且如果容器遭到刪除或損毀,預期會遺失任何資料或組態 (請參閱這裡的討論)。Docker 磁碟區提供了一種機制,可以保存 Docker 容器內建立的資料。在其初始化時,MySQL 伺服器容器會為伺服器資料目錄建立 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 伺服器容器並繫結掛載資料目錄和伺服器組態檔
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 9.0 伺服器容器的變數預設狀態)。然後,MySQL 伺服器的錯誤日誌會重新導向至stderr
,以便錯誤日誌進入 Docker 容器的日誌,並可使用 docker logsmysqld-container
命令查看。
若要在符合這兩個條件中的任一條件時讓 MySQL 伺服器產生錯誤日誌,請使用 --log-error
選項來設定伺服器,以在容器內的特定位置產生錯誤日誌。若要保存錯誤日誌,請依照保存資料和組態變更 中的說明,將主機檔案掛載在容器內錯誤日誌的位置。但是,您必須確保容器內的 MySQL 伺服器具有對已掛載主機檔案的寫入權限。
搭配 Docker 使用 MySQL Enterprise Backup
MySQL Enterprise Backup 是 MySQL 伺服器的商業授權備份公用程式,可透過 MySQL Enterprise Edition 取得。MySQL Enterprise Backup 包含在 MySQL Enterprise Edition 的 Docker 安裝中。
在以下範例中,我們假設您已經在 Docker 容器中執行 MySQL 伺服器(請參閱關於如何使用 Docker 啟動 MySQL 伺服器實例的第 2.5.6.1 節「使用 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:9.0
使用此命令,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:9.0 \ 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:9.0 \ 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:9.0
登入伺服器以檢查伺服器是否使用還原的資料執行。
搭配 Docker 使用 mysqldump
除了使用 MySQL Enterprise Backup 備份在 Docker 容器中執行的 MySQL 伺服器之外,您還可以透過使用在 Docker 容器內部執行的 mysqldump 公用程式,對伺服器執行邏輯備份。
以下指示假設您已經在 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:9.0 \ -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:9.0 \ 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,否則預設為 true),會在啟動 Docker 容器時為伺服器的 root 使用者產生一個隨機密碼。該密碼會印到容器的stdout
中,並且可以透過查看容器的日誌找到(請參閱 啟動 MySQL 伺服器執行個體)。MYSQL_ONETIME_PASSWORD
:當此變數為 true 時(除非設定了MYSQL_ROOT_PASSWORD
或MYSQL_ALLOW_EMPTY_PASSWORD
設定為 true,否則預設為 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 9.0 伺服器容器,預設為 true),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。