Documentation Home
MySQL 8.3 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 40.8Mb
PDF (A4) - 40.9Mb
Man Pages (TGZ) - 294.0Kb
Man Pages (Zip) - 409.0Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb
Excerpts from this Manual

MySQL 8.3 Reference Manual  /  ...  /  More Topics on Deploying MySQL Server with Docker

2.5.6.2 使用 Docker 部署 MySQL 服务器的更多主题

Note

大多数以下示例命令都使用 container-registry.oracle.com/mysql/community-server 作为 Docker 镜像(类似于 docker pulldocker run 命令);如果您的镜像是从其他仓库的,请将其更改为例如 container-registry.oracle.com/mysql/enterprise-server,用于从 Oracle 容器注册表(OCR)下载的 MySQL Enterprise Edition 镜像,或者 mysql/enterprise-server,用于从 My Oracle Support 下载的 MySQL Enterprise Edition 镜像。

Docker 优化的 MySQL 安装

Docker 镜像对于 MySQL 是优化的,以便在 Docker 容器中运行 MySQL 实例。与普通的非 Docker 安装相比,MySQL Docker 安装有以下区别:

  • 只有有限数量的二进制文件被包含。

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

Warning

用户对 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 卷 提供了一种机制来持久化容器中的数据。在其初始化时,MySQL 服务器容器创建了一个 Docker 卷用于服务器数据目录。从容器的 docker inspect 命令的 JSON 输出中,可以找到关于数据目录卷的信息:

$> 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 服务器数据目录中。

另一种持久化数据的方法是使用 bind-mount 主机目录时使用 --mount 选项创建容器。同样的技术也可以用于持久化服务器配置。以下命令创建了一个 MySQL 服务器容器,并将数据目录和服务器配置文件 bind-mount 到宿主机上:

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(容器内的数据目录)。以下条件必须满足以便 bind-mounting 生效:

  • 配置文件 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 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 文档中的 容器网络 部分。

服务器错误日志

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

  • 从主机挂载的服务器配置文件不包含系统变量 log_error(参阅 Persisting Data and Configuration Changes 中关于 bind-mounting 服务器配置文件的信息)。

  • 从主机挂载的服务器配置文件不存在,但 Docker 环境变量 MYSQL_LOG_CONSOLEtrue(这是 MySQL 8.3 服务器容器的默认状态)。然后,MySQL 服务器的错误日志将被重定向到 stderr,因此错误日志将进入 Docker 容器的日志,可以使用 docker logs mysqld-container 命令查看。

要使 MySQL 服务器生成错误日志,请使用 --log-error 选项配置服务器以生成错误日志在容器内的特定位置。要持久化错误日志,请按照 Persisting Data and Configuration Changes 中的说明将主机文件挂载到容器内的错误日志位置。但是,您必须确保 MySQL 服务器在容器内有写入访问权限。

使用 MySQL Enterprise Backup 与 Docker

MySQL Enterprise Backup 是 MySQL 服务器的商业许可备份实用程序,随 MySQL Enterprise Edition 一起提供。MySQL Enterprise Backup 包含在 Docker 安装的 MySQL Enterprise Edition 中。

在以下示例中,我们假设您已经在 Docker 容器中运行了 MySQL 服务器(参阅 Section 2.5.6.1, “基本步骤以部署 MySQL 服务器使用 Docker”)。要使 MySQL Enterprise Backup 备份 MySQL 服务器,必须访问服务器的数据目录。这可以通过例如 bind-mounting 主机目录到 MySQL 服务器的数据目录 来实现:

docker run --name=mysqlserver \
--mount type=bind,src=/path-on-host-machine/datadir/,dst=/var/lib/mysql \
-d mysql/enterprise-server:8.3

使用该命令,MySQL 服务器使用 MySQL 企业版的 Docker 镜像启动,并将主机目录 /path-on-host-machine/datadir/ 挂载到服务器的数据目录 (/var/lib/mysql) 内的容器中。我们还假设,在服务器启动后,已经为 MySQL 企业备份设置了所需的权限(见 授予 MySQL 权限给备份管理员,以获取详细信息)。使用以下步骤备份和恢复 MySQL 服务器实例。

要备份在 Docker 容器中运行的 MySQL 服务器实例,请按照以下步骤操作:

  1. 在同一主机上,启动另一个容器,以 MySQL 企业版的镜像执行备份,使用 MySQL 企业备份命令 backup-to-image。提供对服务器数据目录的访问权限,使用我们在上一步创建的绑定挂载。还将主机目录 (/path-on-host-machine/backups/ 在这个示例中) 挂载到容器中的备份存储文件夹 (/data/backups 在这个示例中),以便持久化备份。以下是该步骤的示例命令,其中 MySQL 企业备份是从 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.3 \
    mysqlbackup -umysqlbackup -ppassword --backup-dir=/tmp/backup-tmp --with-timestamp \
    --backup-image=/data/backups/db.mbi backup-to-image

    请务必检查 mysqlbackup 的输出结尾,以确保备份已经成功完成。

  2. 容器将在备份作业完成后退出,并且由于使用了 --rm 选项启动它,因此它将在退出后被删除。现在已经创建了一个镜像备份,可以在上一步挂载的备份存储文件夹中找到:

    $> ls /tmp/backups
    db.mbi

要恢复在 Docker 容器中运行的 MySQL 服务器实例,请按照以下步骤操作:

  1. 停止 MySQL 服务器容器,这也将停止容器中的 MySQL 服务器:

    docker stop mysqlserver
  2. 在主机上,删除 MySQL 服务器数据目录的绑定挂载的所有内容:

    rm -rf /path-on-host-machine/datadir/*
  3. 启动一个容器,以 MySQL 企业版的镜像执行恢复,使用 MySQL 企业备份命令 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.3 \
    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

    容器将在备份作业完成后退出,并且由于使用了 --rm 选项启动它,因此它将在退出后被删除。

  4. 重新启动服务器容器,这也将重新启动恢复的服务器,使用以下命令:

    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.3

    登录服务器,以检查服务器是否正在使用恢复的数据运行。

使用 mysqldump with Docker

除了使用 MySQL 企业备份来备份在 Docker 容器中运行的 MySQL 服务器外,还可以使用 mysqldump 实用程序,在 Docker 容器中运行,以执行逻辑备份。

以下说明假设您已经在 Docker 容器中运行了 MySQL 服务器,并且在容器首次启动时,已经将主机目录 /path-on-host-machine/datadir/ 挂载到服务器的数据目录 /var/lib/mysql(见 将主机目录绑定到 MySQL 服务器的数据目录 详细信息),其中包含 Unix 套接字文件,以便 mysqldumpmysql 连接到服务器。我们还假设,在服务器启动后,已经创建了一个具有适当权限的用户(在这个示例中为 admin),以便 mysqldump 访问服务器。使用以下步骤备份和恢复 MySQL 服务器数据:

使用 mysqldump 和 Docker 备份 MySQL 服务器数据

  1. 在同一个主机上运行 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.3 \
    -c "mysqldump -uadmin --password='password' --all-databases > /data/backups/all-databases.sql"

    在命令中,使用 --entrypoint 选项,以便在容器启动后启动系统 shell,并使用 -c 选项指定要在 shell 中运行的 mysqldump 命令,其输出被重定向到备份目录中的 all-databases.sql 文件中。

  2. 容器在备份作业完成后退出,并且使用 --rm 选项启动它,因此它在退出后被删除。逻辑备份已经创建,可以在挂载的备份目录中找到,如下所示:

    $> ls /path-on-host-machine/backups/
    all-databases.sql

使用 mysqldump 和 Docker 还原 MySQL 服务器数据

  1. 确保您有一个正在运行的 MySQL 服务器容器,您想将备份的数据还原到该容器中。

  2. 启动一个容器,使用 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.3 \
    mysql -uadmin --password='password' -e "source /data/backups/all-databases.sql"

    容器在备份作业完成后退出,并且使用 --rm 选项启动它,因此它在退出后被删除。

  3. 登录服务器以检查还原的数据现在是否在服务器上。

已知问题
  • 当使用服务器系统变量 audit_log_file 配置审核日志文件名时,使用 loose 选项修改器;否则,Docker 无法启动服务器。

Docker 环境变量

当您创建 MySQL 服务器容器时,可以使用 --env 选项(短选项 -e)和指定一个或多个环境变量来配置 MySQL 实例。只有在挂载的数据目录为空时,服务器初始化才会执行,在这种情况下,设置这些变量没有效果(请参阅 持久化数据和配置更改),并且容器启动时不会修改目录的现有内容,包括服务器设置。

可以用于配置 MySQL 实例的环境变量列举如下:

  • 布尔变量,包括 MYSQL_RANDOM_ROOT_PASSWORD, MYSQL_ONETIME_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORDMYSQL_LOG_CONSOLE,可以通过设置它们为任何非零长度的字符串来使其为真。因此,将它们设置为例如 0, falseno 不会使它们为假,而实际上使它们为真。这是一个已知的问题。

  • MYSQL_RANDOM_ROOT_PASSWORD: 当该变量为真(默认情况下,除非 MYSQL_ROOT_PASSWORD 被设置或 MYSQL_ALLOW_EMPTY_PASSWORD 被设置为真)时,容器启动时将生成一个随机密码用于服务器的根用户。密码将被打印到容器的 stdout 中,可以通过查看容器的日志(请参阅 启动 MySQL 服务器实例)来找到。

  • MYSQL_ONETIME_PASSWORD: 当该变量为真(默认情况下,除非 MYSQL_ROOT_PASSWORD 被设置或 MYSQL_ALLOW_EMPTY_PASSWORD 被设置为真)时,根用户的密码将被设置为过期,必须在使用 MySQL 之前更改密码。

  • MYSQL_DATABASE:这个变量允许您指定在图像启动时创建的数据库的名称。如果提供了用户名和密码与MYSQL_USERMYSQL_PASSWORD,则创建用户并授予该数据库的超级用户访问权限(对应于GRANT ALL)。指定的数据库是通过CREATE DATABASE IF NOT EXIST语句创建的,因此该变量对已经存在的数据库没有影响。

  • MYSQL_USERMYSQL_PASSWORD:这些变量用于共同创建用户并设置该用户的密码,并授予该用户对MYSQL_DATABASE变量指定的数据库的超级用户权限。两个MYSQL_USERMYSQL_PASSWORD都是必需的,以创建用户——如果任何一个变量未设置,另一个将被忽略。如果两个变量都设置了,但MYSQL_DATABASE未设置,则创建用户没有任何权限。

    Note

    不需要使用这种机制来创建root超级用户,该用户默认创建,密码设置为MYSQL_ROOT_PASSWORDMYSQL_RANDOM_ROOT_PASSWORD,除非MYSQL_ALLOW_EMPTY_PASSWORD为true。

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

  • MYSQL_LOG_CONSOLE:当变量为true(这是MySQL 8.3服务器容器的默认状态)时,MySQL Server的错误日志被重定向到stderr,因此错误日志进入Docker容器的日志,并可以使用docker logs mysqld-container命令查看。

    Note

    如果从主机装载了服务器配置文件(请参阅持久化数据和配置更改关于绑定装载配置文件),则该变量无效。

  • MYSQL_ROOT_PASSWORD:该变量指定了MySQL根账户的密码。

    Warning

    在命令行上设置MySQL根用户密码是不安全的。作为替代方案,可以将变量设置为容器文件路径的密码文件,然后从主机装载包含密码的文件到容器文件路径。这仍然不是非常安全,因为密码文件的位置仍然暴露出来。更好的方法是使用MYSQL_RANDOM_ROOT_PASSWORDMYSQL_ONETIME_PASSWORD都设置为true。

  • MYSQL_ALLOW_EMPTY_PASSWORD。将其设置为true,以允许容器使用空密码启动根用户。

    Warning

    将该变量设置为true是不安全的,因为这将使MySQL实例完全不受保护,允许任何人获得完全的超级用户访问权限。更好的方法是使用MYSQL_RANDOM_ROOT_PASSWORDMYSQL_ONETIME_PASSWORD都设置为true。