以下大多数示例命令都使用 container-registry.oracle.com/mysql/community-server
作为 Docker 镜像(例如 docker pull 和 docker run 命令);如果您的镜像来自其他存储库,请更改该镜像 - 例如,将其替换为从 Oracle Container Registry (OCR) 下载的 MySQL 企业版镜像的 container-registry.oracle.com/mysql/enterprise-server
,或替换为从 我的 Oracle 支持 下载的 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
该命令将
挂载到 path-on-host-machine/my.cnf
(容器内的服务器配置文件),并将 /etc/my.cnf
挂载到 path-on-host-machine/datadir
/var/lib/mysql
(容器内的数据目录)。要使绑定挂载正常工作,必须满足以下条件
配置文件
必须已存在,并且它必须包含由用户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 企业版一起使用。MySQL Enterprise Backup 包含在 MySQL 企业版的 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 企业版的 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 服务器的数据目录上绑定挂载主机目录),该目录包含 Unix 套接字文件,mysqldump 和 mysql 可以通过该文件连接到服务器。我们还假设,在服务器启动后,已经创建了一个具有适当权限的用户(本例中为 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
在内的布尔变量可以通过将其设置为任何非零长度的字符串来设为真。因此,将它们设置为例如 “0”、“false” 或 “no” 不会使它们变为假,而实际上使它们变为真。这是一个已知问题。MYSQL_RANDOM_ROOT_PASSWORD
:当此变量为真时(这是其默认状态,除非设置了MYSQL_ROOT_PASSWORD
或将MYSQL_ALLOW_EMPTY_PASSWORD
设置为真),则在 Docker 容器启动时会为服务器的 root 用户生成一个随机密码。该密码将打印到容器的stdout
,可以通过查看容器的日志找到该密码(请参阅启动 MySQL 服务器实例)。MYSQL_ONETIME_PASSWORD
:当该变量为真时(这是其默认状态,除非设置了MYSQL_ROOT_PASSWORD
或将MYSQL_ALLOW_EMPTY_PASSWORD
设置为真),则 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 超级用户,默认情况下会使用
MYSQL_ROOT_PASSWORD
和MYSQL_RANDOM_ROOT_PASSWORD
的描述中讨论的任一机制设置的密码创建 root 超级用户,除非MYSQL_ALLOW_EMPTY_PASSWORD
为真。MYSQL_ROOT_HOST
:默认情况下,MySQL 会创建'root'@'localhost'
帐户。只能按照从容器内部连接到 MySQL 服务器中的描述从容器内部连接到此帐户。要允许从其他主机进行 root 连接,请设置此环境变量。例如,值172.17.0.1
(默认的 Docker 网关 IP)允许从运行容器的主机进行连接。该选项仅接受一个条目,但允许使用通配符(例如,MYSQL_ROOT_HOST=172.*.*.*
或MYSQL_ROOT_HOST=%
)。MYSQL_LOG_CONSOLE
:当该变量为真时(这是 MySQL 9.0 服务器容器的默认状态),MySQL 服务器的错误日志将重定向到stderr
,以便错误日志进入 Docker 容器的日志中,并且可以使用 docker logsmysqld-container
命令查看。注意如果已挂载来自主机的服务器配置文件(请参阅绑定挂载配置文件上的持久化数据和配置更改),则该变量无效。
MYSQL_ROOT_PASSWORD
:此变量指定为 MySQL root 帐户设置的密码。警告在命令行上设置 MySQL root 用户密码是不安全的。作为显式指定密码的替代方法,您可以使用密码文件的容器文件路径设置变量,然后从主机挂载包含该容器文件路径中的密码的文件。这仍然不是很安全,因为密码文件的位置仍然暴露在外。最好使用
MYSQL_RANDOM_ROOT_PASSWORD
和MYSQL_ONETIME_PASSWORD
都为真的默认设置。MYSQL_ALLOW_EMPTY_PASSWORD
。将其设置为 true 以允许使用 root 用户的空白密码启动容器。警告将此变量设置为 true 是不安全的,因为它会使您的 MySQL 实例完全不受保护,允许任何人获得完整的超级用户访问权限。最好使用
MYSQL_RANDOM_ROOT_PASSWORD
和MYSQL_ONETIME_PASSWORD
都为真的默认设置。