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

笔记

以下大多数示例命令都有`mysql/mysql-服务器`必须指定时作为 Docker 映像存储库（例如**码头工人拉**和**码头运行**命令）；如果您的图像来自另一个存储库，请更改它 - 例如，将其替换为`container-registry.oracle.com/mysql/enterprise-server`对于从 Oracle Container Registry (OCR) 下载的 MySQL Enterprise Edition 映像，或`mysql/企业服务器`用于从下载的 MySQL Enterprise Edition 映像[我的 Oracle 支持](https://support.oracle.com/).

-   [Docker 优化 MySQL 安装](docker-mysql-more-topics.html#docker-optimized-installation)

-   [配置 MySQL 服务器](docker-mysql-more-topics.html#docker-configuring-server)

-   [持久化数据和配置更改](docker-mysql-more-topics.html#docker-persisting-data-configuration)

-   [运行其他初始化脚本](docker-mysql-more-topics.html#docker-additional-init)

-   [从另一个 Docker 容器中的应用程序连接到 MySQL](docker-mysql-more-topics.html#docker-app-in-another-container)

-   [服务器错误日志](docker-mysql-more-topics.html#docker-server-error-log)

-   [将 MySQL 企业备份与 Docker 一起使用](docker-mysql-more-topics.html#docker-meb)

-   [已知的问题](docker-mysql-more-topics.html#docker-known-issues)

-   [Docker 环境变量](docker-mysql-more-topics.html#docker-environment-variables)

##### 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/bin/mysqlbackup`（仅适用于 MySQL Enterprise Edition 8.0）

    -   `/usr/sbin/mysqld`

-   所有二进制文件都被剥离；它们不包含调试信息。

##### 配置 MySQL 服务器

启动 MySQL Docker 容器时，可以通过**码头运行**命令。例如：

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

该命令使用以下命令启动 MySQL 服务器`utf8mb4`作为默认字符集和`utf8mb4_col`作为数据库的默认排序规则。

配置 MySQL 服务器的另一种方法是准备一个配置文件并将其挂载到容器内服务器配置文件的位置。看[持久化数据和配置更改](docker-mysql-more-topics.html#docker-persisting-data-configuration)详情。

##### 持久化数据和配置更改

Docker 容器原则上是短暂的，如果容器被删除或损坏，任何数据或配置都将丢失（参见讨论[这里](https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/)）。[Docker 卷](https://docs.docker.com/engine/admin/volumes/volumes/)提供了一种机制来持久化在 Docker 容器中创建的数据。在初始化时，MySQL 服务器容器为服务器数据目录创建一个 Docker 卷。来自的 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`，容器内的服务器数据目录。

保存数据的另一种方法是[绑定安装](https://docs.docker.com/engine/reference/commandline/service_create/#add-bind-mounts-volumes-or-memory-filesystems)主机目录使用`- 山`创建容器时的选项。可以使用相同的技术来持久化服务器的配置。以下命令创建一个 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 mysql/mysql-server:tag
```

命令挂载`*`主机上的路径/my.cnf`*`在`/etc/my.cnf`（容器内的服务器配置文件），和`*`主机上的路径/数据目录`*`在`/var/lib/mysql`（容器内的数据目录）。绑定安装必须满足以下条件：

-   配置文件`*`主机上的路径/my.cnf`*`必须已经存在，并且必须包含用户启动服务器的规范`mysql`：

    ```
    [mysqld]
    user=mysql
    ```

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

-   数据目录`*`主机上的路径/数据目录`*`必须已经存在。要进行服务器初始化，目录必须为空。您还可以挂载一个预先填充了数据的目录并使用它启动服务器；但是，您必须确保使用与创建数据的服务器相同的配置启动 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 容器中的客户端应用程序就可以访问服务器容器中的 MySQL Server。首先，创建一个 Docker 网络：

```
docker network create my-custom-net
```

然后，当您创建和启动服务器和客户端容器时，使用`- 网络`将它们放在您创建的网络上的选项。例如：

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

```
docker run --name=myapp1 --network=my-custom-net -d myapp
```

这`我的应用程序1`然后容器可以连接到`mysql1`容器与`mysql1`主机名，反之亦然，因为 Docker 会自动为给定的容器名称设置 DNS。在下面的示例中，我们运行[**mysql**](mysql.html)客户从内部`我的应用程序1`连接到主机的容器`mysql1`在自己的容器中：

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

有关容器的其他网络技术，请参阅[Docker 容器网络](https://docs.docker.com/engine/userguide/networking/)Docker 文档中的部分。

##### 服务器错误日志

当 MySQL 服务器首次使用您的服务器容器启动时，[服务器错误日志](error-log.html)如果以下任一条件为真，则不会生成：

-   主机的服务器配置文件已挂载，但该文件不包含系统变量[`日志错误`](server-system-variables.html#sysvar_log_error)（看[持久化数据和配置更改](docker-mysql-more-topics.html#docker-persisting-data-configuration)在绑定挂载服务器配置文件时）。

-   来自主机的服务器配置文件尚未挂载，但 Docker 环境变量[`MYSQL_LOG_CONSOLE`](docker-mysql-more-topics.html#docker_var_mysql-log-console)是`真的`（这是 MySQL 8.0 服务器容器的变量默认状态）。MySQL 服务器的错误日志然后被重定向到`标准错误`, 以便错误日志进入 Docker 容器的日志并且可以使用**码头工人日志*`mysqld-容器`***命令。

    要使 MySQL 服务器在两个条件中的任何一个为真时生成错误日志，请使用[`--日志错误`](server-options.html#option_mysqld_log-error)选项[配置服务器](docker-mysql-more-topics.html#docker-configuring-server)在容器内的特定位置生成错误日志。要保留错误日志，请在容器内的错误日志位置挂载一个主机文件，如中所述[持久化数据和配置更改](docker-mysql-more-topics.html#docker-persisting-data-configuration).但是，您必须确保其容器内的 MySQL 服务器对挂载的主机文件具有写入权限。

##### 将 MySQL 企业备份与 Docker 一起使用

[MySQL 企业备份](https://dev.mysql.com/doc/mysql-enterprise-backup/8.0/en/)是 MySQL 服务器的商业许可备份实用程序，可通过[MySQL企业版](https://www.mysql.com/products/enterprise/).MySQL Enterprise Backup 包含在 MySQL Enterprise Edition 的 Docker 安装中。

在以下示例中，我们假设您已经在 Docker 容器中运行了 MySQL 服务器（请参阅[第 2.5.6.1 节，“使用 Docker 部署 MySQL 服务器的基本步骤”](docker-mysql-getting-started.html)关于如何使用 Docker 启动 MySQL 服务器实例）。为了让 MySQL Enterprise Backup 备份 MySQL 服务器，它必须有权访问服务器的数据目录。这可以通过例如，[在 MySQL 服务器的数据目录上绑定挂载主机目录](docker-mysql-more-topics.html#docker-persisting-data-configuration)当你启动服务器时：

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

使用此命令，MySQL 服务器将使用 MySQL 企业版的 Docker 映像启动，并且主机目录*`/主机上的路径/数据目录/`*已挂载到服务器的数据目录（`/var/lib/mysql`) 在服务器容器内。我们还假设，在服务器启动后，还为 MySQL Enterprise Backup 设置了访问服务器所需的权限（请参阅[将 MySQL 权限授予备份管理员](https://dev.mysql.com/doc/mysql-enterprise-backup/8.0/en/mysqlbackup.privileges.html), 详情）。使用以下步骤备份和恢复 MySQL Server 实例。

要使用 MySQL Enterprise Backup with Docker 备份在 Docker 容器中运行的 MySQL 服务器实例，请按照此处列出的步骤操作：

1.  在运行 MySQL Server 容器的同一主机上，使用 MySQL Enterprise Edition 的映像启动另一个容器，以使用 MySQL Enterprise Backup 命令执行备份[`备份到映像`](https://dev.mysql.com/doc/mysql-enterprise-backup/8.0/en/backup-commands-backup.html#option_meb_backup-to-image).使用我们在上一步中创建的绑定挂载提供对服务器数据目录的访问。另外，挂载一个主机目录（*`/主机上的路径/备份/`*在此示例中）到容器中备份的存储文件夹（`/数据/备份`在示例中）以持久化我们正在创建的备份。这是此步骤的示例命令，其中 MySQL Enterprise Backup 使用从下载的 Docker 映像启动[我的 Oracle 支持](https://support.oracle.com/)):

    ```
    $> 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.0 \
    mysqlbackup -umysqlbackup -ppassword --backup-dir=/tmp/backup-tmp --with-timestamp \
    --backup-image=/data/backups/db.mbi backup-to-image

    [Entrypoint] MySQL Docker Image 8.0.11-1.1.5
    MySQL Enterprise Backup version 8.0.11 Linux-4.1.12-61.1.16.el7uek.x86_64-x86_64 [2018-04-08  07:06:45]
    Copyright (c) 2003, 2018, Oracle and/or its affiliates. All Rights Reserved.

    180921 17:27:25 MAIN    INFO: A thread created with Id '140594390935680'
    180921 17:27:25 MAIN    INFO: Starting with following command line ...
    ...

    -------------------------------------------------------------
       Parameters Summary
    -------------------------------------------------------------
       Start LSN                  : 29615616
       End LSN                    : 29651854
    -------------------------------------------------------------

    mysqlbackup completed OK!
    ```

    检查输出的结尾很重要**mysql备份**以确保备份已成功完成。

2.  一旦备份作业完成，容器就会退出，并且`- R M`用于启动它的选项，退出后将其删除。镜像备份已创建，可以在上一步挂载的用于存储备份的主机目录中找到，如下所示：

    ```
    $> ls /tmp/backups
    db.mbi
    ```

    要使用 MySQL Enterprise Backup with Docker 在 Docker 容器中恢复 MySQL 服务器实例，请按照此处列出的步骤操作：

3.  停止 MySQL Server 容器，这也会停止在其中运行的 MySQL Server：

    ```
    docker stop mysqlserver
    ```

4.  在主机上，删除 MySQL Server 数据目录的绑定挂载中的所有内容：

    ```
    rm -rf /path-on-host-machine/datadir/*
    ```

5.  使用 MySQL Enterprise Edition 的映像启动容器以使用 MySQL Enterprise Backup 命令执行还原[`复制回并应用日志`](https://dev.mysql.com/doc/mysql-enterprise-backup/8.0/en/backup-commands-restore.html#option_meb_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.0 \
    mysqlbackup --backup-dir=/tmp/backup-tmp --with-timestamp \
    --datadir=/var/lib/mysql --backup-image=/data/backups/db.mbi copy-back-and-apply-log

    [Entrypoint] MySQL Docker Image 8.0.11-1.1.5
    MySQL Enterprise Backup version 8.0.11 Linux-4.1.12-61.1.16.el7uek.x86_64-x86_64 [2018-04-08  07:06:45]
    Copyright (c) 2003, 2018, Oracle and/or its affiliates. All Rights Reserved.

    180921 22:06:52 MAIN    INFO: A thread created with Id '139768047519872'
    180921 22:06:52 MAIN    INFO: Starting with following command line ...
    ...
    180921 22:06:52 PCR1    INFO: We were able to parse ibbackup_logfile up to
              lsn 29680612.
    180921 22:06:52 PCR1    INFO: Last MySQL binlog file position 0 155, file name binlog.000003
    180921 22:06:52 PCR1    INFO: The first data file is '/var/lib/mysql/ibdata1'
                                  and the new created log files are at '/var/lib/mysql'
    180921 22:06:52 MAIN    INFO: No Keyring file to process.
    180921 22:06:52 MAIN    INFO: Apply-log operation completed successfully.
    180921 22:06:52 MAIN    INFO: Full Backup has been restored successfully.

    mysqlbackup completed OK! with 3 warnings
    ```

    一旦备份作业完成，容器就会退出，并且`- R M`启动时使用的选项，退出后将其删除。

6.  使用以下命令重新启动服务器容器，这也会重新启动恢复的服务器：

    ```
    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.0
    ```

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

##### 已知的问题

-   使用服务器系统变量时[`审计日志文件`](audit-log-reference.html#sysvar_audit_log_file)要配置审计日志文件名，请使用`松动的` [选项修饰符](option-modifiers.html)用它;否则，Docker 无法启动服务器。

##### Docker 环境变量

创建 MySQL 服务器容器时，可以使用`--env`选项（缩写形式`-e`) 并指定一个或多个环境变量。如果挂载的数据目录不为空，则不执行服务器初始化，在这种情况下，设置这些变量中的任何一个都无效（请参阅[持久化数据和配置更改](docker-mysql-more-topics.html#docker-persisting-data-configuration))，并且在容器启动期间不会修改目录的现有内容，包括服务器设置。

此处列出了可用于配置 MySQL 实例的环境变量：

-   布尔变量包括[`MYSQL_RANDOM_ROOT_PASSWORD`](docker-mysql-more-topics.html#docker_var_mysql_random_root_password),[`MYSQL_ONETIME_PASSWORD`](docker-mysql-more-topics.html#docker_var_mysql_onetime_password),[`MYSQL_ALLOW_EMPTY_PASSWORD`](docker-mysql-more-topics.html#docker_var_mysql-allow-empty-password)， 和[`MYSQL_LOG_CONSOLE`](docker-mysql-more-topics.html#docker_var_mysql-log-console)通过将它们设置为任何非零长度的字符串来实现。因此，将它们设置为例如“0”、“false”或“no”不会使它们为假，而是实际上使它们为真。这是一个已知的问题。

-   [](<>) [`MYSQL_RANDOM_ROOT_PASSWORD`](docker-mysql-more-topics.html#docker_var_mysql_random_root_password): 当这个变量为真时（这是它的默认状态，除非[`MYSQL_ROOT_PASSWORD`](docker-mysql-more-topics.html#docker_var_mysql-root-password)设置或[`MYSQL_ALLOW_EMPTY_PASSWORD`](docker-mysql-more-topics.html#docker_var_mysql-allow-empty-password)设置为true），则在启动Docker容器时会为服务器的root用户生成一个随机密码。密码打印到`标准输出`容器，可以通过查看容器的日志找到（参见[启动 MySQL 服务器实例](docker-mysql-getting-started.html#docker-starting-mysql-server)）。

-   [](<>) [`MYSQL_ONETIME_PASSWORD`](docker-mysql-more-topics.html#docker_var_mysql_onetime_password)：当变量为真时（这是它的默认状态，除非[`MYSQL_ROOT_PASSWORD`](docker-mysql-more-topics.html#docker_var_mysql-root-password)设置或[`MYSQL_ALLOW_EMPTY_PASSWORD`](docker-mysql-more-topics.html#docker_var_mysql-allow-empty-password)设置为true），root用户的密码设置为过期，必须更改才能正常使用MySQL。

-   [](<>) [`MYSQL_DATABASE`](docker-mysql-more-topics.html#docker_var_mysql_database)：此变量允许您指定要在映像启动时创建的数据库的名称。如果提供了用户名和密码[`MYSQL_USER`](docker-mysql-more-topics.html#docker_var_mysql_user_password)和[`MYSQL_PASSWORD`](docker-mysql-more-topics.html#docker_var_mysql_user_password)，用户被创建并授予对此数据库的超级用户访问权限（对应于`全部授予`）。指定的数据库是由一个[如果不存在则创建数据库](create-database.html)语句，这样如果数据库已经存在，变量就不起作用。

-   [](<>) [`MYSQL_USER`](docker-mysql-more-topics.html#docker_var_mysql_user_password),[`MYSQL_PASSWORD`](docker-mysql-more-topics.html#docker_var_mysql_user_password)：这些变量一起用于创建用户并设置该用户的密码，并且该用户被授予对由指定的数据库的超级用户权限[`MYSQL_DATABASE`](docker-mysql-more-topics.html#docker_var_mysql_database)多变的。两个都[`MYSQL_USER`](docker-mysql-more-topics.html#docker_var_mysql_user_password)和[`MYSQL_PASSWORD`](docker-mysql-more-topics.html#docker_var_mysql_user_password)是创建用户所必需的——如果两个变量中的任何一个未设置，则忽略另一个。如果两个变量都设置但[`MYSQL_DATABASE`](docker-mysql-more-topics.html#docker_var_mysql_database)不是，用户是在没有任何权限的情况下创建的。

    笔记

    无需使用此机制来创建 root 超级用户，默认情况下使用密码由描述中讨论的任一机制设置的密码创建[`MYSQL_ROOT_PASSWORD`](docker-mysql-more-topics.html#docker_var_mysql-root-password)和[`MYSQL_RANDOM_ROOT_PASSWORD`](docker-mysql-more-topics.html#docker_var_mysql_random_root_password)， 除非[`MYSQL_ALLOW_EMPTY_PASSWORD`](docker-mysql-more-topics.html#docker_var_mysql-allow-empty-password)是真的。

-   [](<>) [`MYSQL_ROOT_HOST`](docker-mysql-more-topics.html#docker_var_mysql-root-host)：默认情况下，MySQL 创建`'根'@'本地主机'`帐户。此帐户只能从容器内部连接，如中所述[从容器内连接到 MySQL 服务器](docker-mysql-getting-started.html#docker-connecting-within-container).要允许来自其他主机的 root 连接，请设置此环境变量。例如，值`172.17.0.1`，这是默认的 Docker 网关 IP，允许来自运行容器的主机的连接。该选项只接受一个条目，但允许使用通配符（例如，`MYSQL_ROOT_HOST=172.*.*.*`要么`MYSQL_ROOT_HOST=%`）。

-   [](<>) [`MYSQL_LOG_CONSOLE`](docker-mysql-more-topics.html#docker_var_mysql-log-console)：当变量为真（这是 MySQL 8.0 服务器容器的默认状态）时，MySQL 服务器的错误日志被重定向到`标准错误`, 以便错误日志进入 Docker 容器的日志并且可以使用**码头工人日志*`mysqld-容器`***命令。

    笔记

    如果安装了来自主机的服务器配置文件，则该变量无效（请参阅[持久化数据和配置更改](docker-mysql-more-topics.html#docker-persisting-data-configuration)在绑定安装配置文件时）。

-   [](<>) [`MYSQL_ROOT_PASSWORD`](docker-mysql-more-topics.html#docker_var_mysql-root-password)：此变量指定为 MySQL root 帐户设置的密码。

    警告

    在命令行上设置 MySQL root 用户密码是不安全的。作为显式指定密码的替代方法，您可以使用密码文件的容器文件路径设置变量，然后从您的主机挂载一个文件，该文件在容器文件路径中包含密码。这仍然不是很安全，因为密码文件的位置仍然暴露在外。最好使用默认设置[`MYSQL_RANDOM_ROOT_PASSWORD`](docker-mysql-more-topics.html#docker_var_mysql_random_root_password)和[`MYSQL_ONETIME_PASSWORD`](docker-mysql-more-topics.html#docker_var_mysql_onetime_password)两者都是真实的。

-   [](<>) [`MYSQL_ALLOW_EMPTY_PASSWORD`](docker-mysql-more-topics.html#docker_var_mysql-allow-empty-password).将其设置为 true 以允许使用 root 用户的空密码启动容器。

    警告

    将此变量设置为 true 是不安全的，因为它将使您的 MySQL 实例完全不受保护，从而允许任何人获得完全的超级用户访问权限。最好使用默认设置[`MYSQL_RANDOM_ROOT_PASSWORD`](docker-mysql-more-topics.html#docker_var_mysql_random_root_password)和[`MYSQL_ONETIME_PASSWORD`](docker-mysql-more-topics.html#docker_var_mysql_onetime_password)两者都是真实的。
