2.5.7.2 有关使用 Docker 部署 MySQL 服务器的更多主题

Note

下面的大多数示例命令在必须指定mysql/mysql-server作为 Docker 映像存储库时(例如 docker pulldocker run 命令);如果您的映像来自另一个存储库,请进行更改,例如,对于从我的 Oracle 支持下载的 MySQL 企业版映像,请将其替换为mysql/enterprise-server

为 Docker 优化的 MySQL 安装

MySQL 的 Docker 映像针对代码大小进行了优化,这意味着它们仅包含关键组件,这些组件与在 Docker 容器中运行 MySQL 实例的大多数用户有关。 MySQL Docker 安装在以下方面与常见的非 Docker 安装不同:

  • 包含的二进制文件仅限于:

  • /usr/bin/my_print_defaults

    • /usr/bin/mysql

    • /usr/bin/mysql_config

    • /usr/bin/mysql_install_db

    • /usr/bin/mysql_tzinfo_to_sql

    • /usr/bin/mysql_upgrade

    • /usr/bin/mysqladmin

    • /usr/bin/mysqlcheck

    • /usr/bin/mysqldump

    • /usr/bin/mysqlpump

    • /usr/sbin/mysqld

  • 所有二进制文件都被删除;它们不包含调试信息。

配置 MySQL 服务器

启动 MySQL Docker 容器时,可以通过 dockerrun **命令将配置选项传递给服务器。例如:

docker run --name mysql1 -d mysql/mysql-server:tag --character-set-server=utf8mb4 --collation-server=utf8mb4_col

该命令以utf8mb4作为默认字符集和utf8mb4_col作为数据库的默认排序规则来启动 MySQL Server。

配置 MySQL Server 的另一种方法是准备一个配置文件,并将其安装在容器内服务器配置文件的位置。有关详情,请参见持续的数据和配置更改

持续进行数据和配置更改

Docker 容器原则上是短暂的,如果容器被删除或损坏,则任何数据或配置都将丢失(请参阅讨论here)。但是Docker volumes提供了一种机制,可以持久化在 Docker 容器内创建的数据。在初始化时,MySQL Server 容器会为服务器数据目录创建一个 Docker 卷。在容器上运行 docker inspect 命令的 JSON 输出具有Mount键,其值提供有关数据目录卷的信息:

shell> 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选项bind-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 mysql/mysql-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

您还可以在文件中包括其他服务器配置选项。

  • 数据目录path-on-host-machine/datadir必须已经存在。为了进行服务器初始化,目录必须为空。您还可以挂载一个预填充有数据的目录,并使用该目录启动服务器。但是,必须确保以与创建数据的服务器相同的配置启动 Docker 容器,并且在启动容器时会挂载所需的所有主机文件或目录。
运行其他初始化脚本

如果要在创建数据库后立即在数据库上运行任何.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 mysql/mysql-server:tag
从另一个 Docker 容器中的应用程序连接到 MySQL

通过构建 Docker 网络,可以允许多个 Docker 容器相互通信,以便另一个 Docker 容器中的 Client 端应用程序可以访问服务器容器中的 MySQL Server。首先,创建一个 Docker 网络:

docker network create my-custom-net

然后,在创建和启动服务器和 Client 端容器时,请使用--network选项将它们放在您创建的网络上。例如:

docker run --name=mysql1 --network=my-custom-net -d mysql/mysql-server
docker run --name=myapp1 --network=my-custom-net -d myapp

然后,由于 Docker 自动为给定容器名称设置了 DNS,因此myapp1容器可以使用mysql1主机名连接到mysql1容器,反之亦然。在以下示例中,我们从myapp1容器内部运行mysqlClient 端,以连接到其自身容器中的主机mysql1

docker exec -it myapp1 mysql --host=mysql1 --user=myuser --password

有关容器的其他联网技术,请参阅 Docker 文档中的Docker 容器网络部分。

服务器错误日志

当首次使用服务器容器启动 MySQL Server 时,如果满足以下任一条件,则不会生成服务器错误日志

  • 主机上的服务器配置文件已被挂载,但该文件不包含系统变量log_error(有关绑定安装服务器配置文件的信息,请参阅持续的数据和配置更改)。

  • 尚未安装主机中的服务器配置文件,但 Docker 环境变量MYSQL_LOG_CONSOLEtrue(MySQL 5.7 服务器容器的变量默认状态为false)。然后将 MySQL Server 的错误日志重定向到stderr,以便将错误日志放入 Docker 容器的日志中,并可以使用 docker logs * mysqld-container *命令查看。

为了使 MySQL Server 在两个条件中的任何一个为 true 时都生成错误日志,请使用--log-error选项配置服务器在容器内的特定位置生成错误日志。要保留错误日志,请按照持续的数据和配置更改中的说明将主机文件安装在容器内错误日志的位置。但是,必须确保其容器内的 MySQL Server 对已装入的主机文件具有写权限。

Docker 环境变量

创建 MySQL Server 容器时,可以使用--env选项(简称-e)并指定以下一个或多个环境变量来配置 MySQL 实例。

Notes

  • 如果您装载的数据目录不为空,则以下变量均无效,因为届时将不尝试服务器初始化(有关更多详细信息,请参见持续的数据和配置更改)。容器启动期间,不会修改文件夹中所有先前存在的内容,包括所有旧服务器设置。

  • 通过将它们设置为任何非零长度的字符串,可以使布尔变量(包括MYSQL_RANDOM_ROOT_PASSWORDMYSQL_ONETIME_PASSWORDMYSQL_ALLOW_EMPTY_PASSWORDMYSQL_LOG_CONSOLE)为真。因此,将它们设置为例如“ 0”,“ false”或“ no”不会使它们错误,但实际上会使它们正确。这是 MySQL Server 容器的已知问题。

Note

无需使用此机制来创建 root 超级用户,除非使用MYSQL_ALLOW_EMPTY_PASSWORD为 true,否则该超级用户默认情况下是使用MYSQL_ROOT_PASSWORDMYSQL_RANDOM_ROOT_PASSWORD的描述中讨论的机制之一设置的密码创建的。

  • MYSQL_ROOT_HOST:默认情况下,MySQL 创建'root'@'localhost'帐户。如从容器内连接到 MySQL Server中所述,只能从容器内部连接该帐户。要允许来自其他主机的根连接,请设置此环境变量。例如,值172.17.0.1是默认的 Docker 网关 IP,它允许来自运行容器的主机的连接。该选项仅接受一个条目,但允许使用通配符(例如MYSQL_ROOT_HOST=172.*.*.*MYSQL_ROOT_HOST=%)。

  • MYSQL_LOG_CONSOLE:当变量为 true 时(MySQL 5.7 服务器容器的变量默认状态为false),MySQL 服务器的错误日志将重定向到stderr,以便错误日志进入 Docker 容器的日志,并且可以使用 查看 docker logs * mysqld-container *命令。

Note

如果已安装主机上的服务器配置文件,则该变量无效(请参阅持续的数据和配置更改关于绑定安装配置文件)。

Warning

在命令行上设置 MySQL root 用户密码不安全。作为显式指定密码的替代方法,您可以使用密码文件的容器文件路径设置变量,然后从主机装载在容器文件路径中包含密码的文件。这仍然不是很安全,因为密码文件的位置仍然公开。最好使用默认设置MYSQL_RANDOM_ROOT_PASSWORDMYSQL_ONETIME_PASSWORD均为 true。

Warning

将该变量设置为 true 是不安全的,因为它将使您的 MySQL 实例完全不受保护,从而使任何人都可以获得完全的超级用户访问权限。最好使用默认设置MYSQL_RANDOM_ROOT_PASSWORDMYSQL_ONETIME_PASSWORD均为 true。