Docker常用镜像:MySQL
2020/02/02
MySQL
Docker
> 以MySQL8.0.30为例 仓库地址以及教程:[https://hub.docker.com/_/mysql](https://hub.docker.com/_/mysql) 不想看一堆废话的请直接点击右侧菜单的`个人推荐实战` ## 拉取 ```bash docker pull mysql:8.0.30 ``` ## 端口 端口 | 协议 | 描述 ---|---|--- 3306 | tcp | 客户端至服务器的连接端口(MySQL协议) 33060 | tcp | 客户端至服务器的连接端口(MySQL X协议) > 一般情况下,仅使用`3306`即可 ## 环境变量 参数 | 描述 | 可选值 | 备注 ---|---|---|--- MYSQL_ROOT_PASSWORD | ROOT密码 | String | MYSQL_ALLOW_EMPTY_PASSWORD | 允许空密码 | yes | 初始化时使用 MYSQL_RANDOM_ROOT_PASSWORD | 随机ROOT密码 | yes | MYSQL_DATABASE | 默认创建数据库 | String | MYSQL_USER,MYSQL_PASSWORD | 默认普通用户与密码 | String | 用户名密码将作为MYSQL_DATABAS的用户名密码 MYSQL_ONETIME_PASSWORD | 将root用户密码设置为过期用户 | yes | MySQL 5.6+后可用 - `MYSQL_ROOT_PASSWORD`,`MYSQL_ALLOW_EMPTY_PASSWORD`和`MYSQL_RANDOM_ROOT_PASSWORD`必填一个; - `MYSQL_ONETIME_PASSWORD`不做举例,不会用; - `_FILE`可以附加到之前列出的参数中,可以安全的加载密码等敏感信息,不做举例,不会用。 > 以下仅示例,无需执行 ```bash # 自定义密码 docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=123 -p 3306:3306 mysql:8.0.30 # 使用空密码 docker run -d --name mysql -e MYSQL_ALLOW_EMPTY_PASSWORD=yes -p 3306:3306 mysql:8.0.30 # 使用随机密码,在日志内查看随机密码 docker run -d --name mysql -e MYSQL_RANDOM_ROOT_PASSWORD=yes -p 3306:3306 mysql:8.0.30 docker logs mysql | grep 'GENERATED ROOT PASSWORD' # 指定默认数据库,用户名,密码 docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=123 -e MYSQL_DATABASE=mydb -e MYSQL_USER=test -e MYSQL_PASSWORD=test -p 3306:3306 mysql:8.0.30 ``` ## 自定义MySQL配置文件 MySQL默认配置文件为`/etc/mysql/my.cnf`,其引入`/etc/mysql/conf.d/`、`/etc/mysql/mysql.conf.d/`两个文件夹下的配置文件。若自定义配置文件在`/my/custom/config-file.cnf`(`config-file.cnf`文件名可自定义),则使用`-v`参数自定义MySQL配置文件。 > 以下仅示例,无需执行 ```bash docker run -d --name mysql -v /my/custom:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123 -p 3306:3306 mysql:8.0.30 ``` ## 传参方式配置MySQL 此方法无需配置文件,即可修改MySQL配置,但是不够灵活。 > 以下仅示例,无需执行 ```bash docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=123 -p 3306:3306 mysql:8.0.30 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci ``` 运行以下命令查看完整参数列表(内容太多,不详细列举了) > 以下仅示例,无需执行 ```bash docker run -it --rm mysql:tag --verbose --help ``` ## 数据存储 容器内默认数据库存储位置为`/var/lib/mysql`,该路径是容器内`/etc/mysql/mysql.conf.d/mysqld.cnf`配置文件指定的;建议使用`-v`参数绑定物理机。 > 以下仅示例,无需执行 ```bash docker run -d --name mysql -v /my/data/:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123 -p 3306:3306 mysql:8.0.30 ``` ## 解决 mbind: Operation not permitted `Docker`环境运行`MySQL`时,日志中会出现`mbind: Operation not permitted`,需要设置`Seccomp`,示例如下: ```bash docker run --security-opt seccomp=unconfined ``` ## 注意事项 #### 在MySQL初始化完成之前没有连接 如果在容器启动时没有初始化数据库,则将创建一个默认数据库。尽管这是预期的行为,但这意味着在此类初始化完成之前,它将不接受传入的连接。使用自动化工具(例如)`docker-compose`同时启动多个容器时,这可能会引起问题。如果您尝试连接到MySQL的应用程序无法处理MySQL停机时间或等待MySQL正常启动,则可能有必要在服务启动之前放置connect-retry循环。 #### 针对现有数据库的用法 如果mysql使用已经包含数据库的数据目录启动容器实例,`MYSQL_ROOT_PASSWORD`则应在运行命令行中忽略该变量;在任何情况下都将忽略它,并且不会以任何方式更改现有数据库。 > 以下仅示例,无需执行 ```bash # 启动一个容器并指定数据库目录以及数据库密码 docker run -d --name mysql -v mydb:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -p 3306:3306 mysql:8.0.30 # 删除容器 docker rm -f mysql # 再次启动容器并使用刚刚的数据库目录,但是改变密码 docker run -d --name mysql -v mydb:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=654321 -p 3306:3306 mysql:8.0.30 # 此时,数据库的密码依旧是123456,即第二次启动时,环境变量不起作用 ``` #### 数据库备份与还原 > 官方示例如下: ```bash # 备份 docker exec some-mysql sh -c 'exec mysqldump --all-databases -uroot -p"$MYSQL_ROOT_PASSWORD"' > /some/path/on/your/host/all-databases.sql # 还原 docker exec -i mysql sh -c 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD"' < /some/path/on/your/host/all-databases.sql ``` 该示例中的`$MYSQL_ROOT_PASSWORD`使用的`docker run`时设置的参数,当MySQL手动更换密码,或者使用其他参数启动时,需要在`-p`后面使用明文密码 #### 时区 默认镜像的时区为`UTC+0`,使用`-e TZ=Asia/Shanghai`设置中国时区`UTC+8` ## 个人推荐实战 1. `mkdir -p /work/mysql`:在Linux跟路径下新建`work`目录用于存放工作数据,在`/work/`下新建`mysql`目录用于存储MySQL容器数据 2. `mkdir -p /work/mysql/data`:在`/work/mysql/`下新建`data`目录,用于存储MySQL数据文件。 3. `mkdir -p /work/mysql/config`:在`/work/mysql/`下新建`config`目录,用于存储MySQL配置文件。 4. `vim /work/mysql/config/config.cnf`:在`/work/mysql/config/`下新建`config.cnf`文件作为MySQL配置文件,内容如下: ```ini [mysql] # 客户端默认字符集 default-character-set=utf8mb4 [mysqld] # 服务器唯一ID(主从复制时需要不一样) server-id=1 # 是否只读,OFF(默认)表示读写(主机),ON表示只读(从机) read-only=OFF # 服务端使用的字符集 character-set-server=utf8mb4 # 数据库排序字符集 collation_server=utf8mb4_general_ci # 创建新表时将使用的默认存储引擎 default-storage-engine=INNODB # 最大承受包:默认4M max_allowed_packet=100M # 分组拼接最大长度:默认1024,64位最大18446744073709551615,32位最大4294967295 group_concat_max_len=18446744073709551615 # 当设置为0,该模式速度最快,但不太安全: # mysqld进程的崩溃会导致上一秒钟所有事务数据的丢失。 # 当设置为1,该模式是最安全的,但也是最慢的一种方式,也是默认模式: # 在mysqld 服务崩溃或者服务器主机crash的情况下,binary log 只有可能丢失最多一个语句或者一个事务。 # 当设置为2,该模式速度较快,也比0安全 # 只有在操作系统崩溃或者系统断电的情况下,上一秒钟所有事务数据才可能丢失。 innodb_flush_log_at_trx_commit=2 # 默认64,最大1000。当tablespace 空间已经满了后,需要MySQL系统需要自动扩展多少空间,每次tablespace 扩展都会让各个SQL 处于等待状态。增加自动扩展Size可以减少tablespace自动扩展次数。 innodb_autoextend_increment=64 # 默认16M(16777216)。InnoDB用来缓冲日志数据的缓冲区大小。因为它是每秒刷新一次的,所以将它设置得很大是没有意义的(即使是长事务)。 innodb_log_buffer_size=1M # 默认48M(50331648)。此配置项作用设定innodb 数据库引擎写日志缓存区。 innodb_log_file_size=48M # 默认128M(134217728)。InnoDB使用缓冲池来缓存索引和行数据。 innodb_buffer_pool_size=8M # innodb使用的CPU线程数,默认4(推荐与CPU核心数相同) innodb_read_io_threads=4 innodb_write_io_threads=4 # 允许最大同时连接数:默认151 max_connections=151 # 服务器关闭非交互连接之前等待活动的秒数(默认28800,即8小时) wait_timeout=3600 # 服务器关闭非交互连接之前等待活动的秒数(默认28800,即8小时) interactive_timeout=3600 # 关闭MySQLx(MySQL5.7不支持此选项,使用时需要注释此配置) mysqlx=0 # 开启慢查询日志(建议本地和测试环境开启) slow_query_log=ON # 慢查询时间阈值(单位:秒) long_query_time=3 # 二进制日志文件格式 binlog_format=MIXED ``` 5. 运行容器并使用`MYSQL_ALLOW_EMPTY_PASSWORD`设置默认空密码。命令如下 ```bash docker run -d --restart always --name mysql --security-opt seccomp=unconfined -v /work/mysql/config/:/etc/mysql/conf.d -v /work/mysql/data/:/var/lib/mysql -e TZ=Asia/Shanghai -e MYSQL_ALLOW_EMPTY_PASSWORD=yes -p 3306:3306 mysql:8.0.30 ``` 6. 使用`docker exec`进入容器内或者使用`SQLyog`、`Navicat`等工具连接MySQL,之后修改密码。命令如下 ```bash docker exec -it mysql sh -c 'mysql -uroot -p' # 直接空密码回车进入 use mysql; ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY "123"; flush privileges; DROP USER root@localhost; exit; ```
18