以下大多数示例命令都将 container-registry.oracle.com/mysql/community-server
作为正在使用的 Docker 镜像(例如 docker pull 和 docker run 命令);如果您的镜像来自其他存储库,请更改该镜像 - 例如,将其替换为从 Oracle 容器注册表 (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 不为在这样的更改后的容器或从更改后的 Docker 镜像创建的容器中运行的 MySQL 产品提供支持。
配置 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 8.4 服务器容器的变量默认状态)。然后,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: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
登录服务器以检查服务器是否正在使用已还原的数据运行。
在 Docker 中使用 mysqldump
除了使用 MySQL Enterprise Backup 备份在 Docker 容器中运行的 MySQL 服务器之外,您还可以通过使用在 Docker 容器内运行的 mysqldump 实用程序来执行服务器的逻辑备份。
以下说明假设您已经在 Docker 容器中运行了 MySQL 服务器,并且在容器首次启动时,主机目录 /path-on-host-machine/datadir/
已挂载到服务器的数据目录 /var/lib/mysql
上(有关详细信息,请参阅将主机目录绑定挂载到 MySQL 服务器的数据目录上),其中包含 mysqldump 和 mysql 可以用来连接到服务器的 Unix 套接字文件。我们还假设,在服务器启动后,已经创建了具有适当权限的用户(在本例中为 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 超级用户,默认情况下,将使用
MYSQL_ROOT_PASSWORD
和MYSQL_RANDOM_ROOT_PASSWORD
的描述中讨论的任一机制设置的密码来创建 root 超级用户,除非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 的默认设置。