在容器中部署MySQL
2022-04-30 09:18 abce 阅读(790) 评论(0) 编辑 收藏 举报MySQL的docker镜像是经过优化的代码,只是包含了大多数用户期望的组件。
MySQL的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 (for MySQL Enterprise Edition 8.0 only) /usr/sbin/mysqld
·所有的二级制文件都是被修剪过的,不包含debug信息
启动容器的时候,可以通过docker run传递参数给mysql,比如:
docker run --name mysql1 -d mysql/mysql-server:tag --character-set-server=utf8mb4 --collation-server=utf8mb4_col
持久化数据和配置的修改
容器被删除或损坏,任何数据和配置就丢失了。docker volumes为容器内数据持久化提供了一种机制。
在初始化容器的时候,MySQL Server容器创建一个docker卷作为数据目录。可以通过docker inspect命令来查看容器的挂载点,查找关键字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选项来绑定挂载一个本地主机目录用作数据持久化。比如以下命令会绑定数据目录和配置文件:
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
这里的mount命令会将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目录必须已经存在。在mysql容器初始化的时候,该目录必须是空的。启动mysql的时候,也可以挂载已经有数据的目录,但是你要确保启动的容器必须和创建该目录的mysql server具有相同的配置,任何文件或目录在启动的时候都要被挂载。
运行其它初始化脚本
如果你想在创建数据库后立即运行任何.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
从应用容器连接容器中的mysql
创建docker网络,你可以让容器互相通信,这样另一个容器中的客户端应用可以访问容器中的mysql server。
首先,创建docker网络:
docker network create my-custom-net
然后,当你在创建和启动mysqlserver和客户端容器的时候,使用--network,将这些节点放到容器网络中。比如:
docker run --name=mysql1 --network=my-custom-net -d mysql/mysql-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
错误日志
首次使用服务器容器启动 MySQL 服务器时,如果以下任一条件为真,则不会生成服务器错误日志
·主机上的配置文件已经被挂载,但是变量中没有包含参数log_error
·主机上的配置文件没有被挂载,但是容器环境变量mysql_log_console被设置为true(mysql8容器中是默认设置)。这样mysql错误日志被打印到stderr,日志就被记录在容器的log中,可以通过docker logs mysqld-container命令查看。
要想以上任何一个条件为真时,能生成错误日志,可以使用--log-error参数配置mysqlserver,在容器中指定位置生成错误日志。
要想持久化错误日志,可以像上面提到的那样配置持久化。但是,你必须要保证你的mysql在容器内具有对挂载点文件的读写权限。
使用基于容器的mysql企业版备份工具进行备份
要想备份,必须有对数据目录的访问权限。
使用容器版的mysql企业版备份工具备份容器中的mysql,要遵循以下步骤:
1.在mysql容器所在的主机上启动另一个备份工具容器来执行备份。使用关键字backup-to-image
$> 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!
2.使用--rm参数启动,备份结束后容器就会退出,并被移除。一个镜像快照已经被创建,可以在主机目录找到
$> ls /tmp/backups db.mbi
还原的过程
1.关闭mysql容器
docker stop mysqlserver
2.在主机上,删除绑定目录下的所有内容
rm -rf /path-on-host-machine/datadir/*
3.启动带有企业备份工具的容器
$> 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
4.重启mysql容器
docker restart mysqlserver
或者
docker run --name=mysqlserver2 \ --mount type=bind,src=/path-on-host-machine/datadir/,dst=/var/lib/mysql \ -d mysql/enterprise-server:8.0
docker环境变量
当创建mysql容器实例的时候,可以通过参数--env(缩写是-e)来指定一个或多个参数。如果挂载的数据目录不为空,初始化就会失败,设置变量也就无效。
·布尔变量
MYSQL_RANDOM_ROOT_PASSWORD, MYSQL_ONETIME_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD, MYSQL_LOG_CONSOLE
如果给这些变量设置任何非0长度的字符串,变量值就为true。
·MYSQL_RANDOM_ROOT_PASSWORD默认值为true(除非MYSQL_ROOT_PASSWORD或MYSQL_ALLOW_EMPTY_PASSWORD被设置为true),容器启动的时候给root用户生成一个随机密码。密码被打印在容器的stdout,可以通过查看容器的日志来发现
·MYSQL_ONETIME_PASSWORD默认值为true(除非MYSQL_ROOT_PASSWORD或MYSQL_ALLOW_EMPTY_PASSWORD被设置为true),会给root设置过期,必须修改密码才能使用
·MYSQL_DATABASE指定数据库名。如果提供了MYSQL_USER、MYSQL_PASSWORD,创建的用户就会被授予访问该数据库的超级权限(grant all)
·MYSQL_USER、MYSQL_PASSWORD。如果用户创建的时候没有指定关键MYSQL_DATABASE,就默认不授予任何权限
·MYSQL_HOST,默认创建的用户是‘root’@'localhost'
·MYSQL_LOG_CONSOLE:如果设置为true,错误日志被重定向到stderr,可用通过docker logs mysql-container查看
·MYSQL_ROOT_PASSWORD ·MYSQL_ALLOW_EMPTY_PASSWORD
docker inspect 示例
# docker inspect d4a31e9e36a6 [ { "Id": "d4a31e9e36a609c1df6b61f36be6da4ee31993042fd166669c234d2fddcb7699", "Created": "2019-12-03T11:04:26.399766499Z", "Path": "docker-entrypoint.sh", "Args": [ "mysqld" ], "State": { "Status": "running", "Running": true, "Paused": false, "Restarting": false, "OOMKilled": false, "Dead": false, "Pid": 71169, "ExitCode": 0, "Error": "", "StartedAt": "2019-12-03T11:04:36.393621191Z", "FinishedAt": "0001-01-01T00:00:00Z" }, "Image": "sha266:bddaf69df77093d9669a7b3277f6ff04bd966b0d0dc634a9b0bdfd006693ef6d", "ResolvConfPath": "/var/lib/docker/containers/d4a31e9e36a609c1df6b61f36be6da4ee31993042fd166669c234d2fddcb7699/resolv.conf", "HostnamePath": "/var/lib/docker/containers/d4a31e9e36a609c1df6b61f36be6da4ee31993042fd166669c234d2fddcb7699/hostname", "HostsPath": "/var/lib/docker/containers/d4a31e9e36a609c1df6b61f36be6da4ee31993042fd166669c234d2fddcb7699/hosts", "LogPath": "/var/lib/docker/containers/d4a31e9e36a609c1df6b61f36be6da4ee31993042fd166669c234d2fddcb7699/d4a31e9e36a609c1df6b61f36be6da4ee31993042fd166669c234d2fddcb7699-json.log", "Name": "/abce", "RestartCount": 0, "Driver": "overlay2", "Platform": "linux", "MountLabel": "", "ProcessLabel": "", "AppArmorProfile": "", "ExecIDs": [ "3c2e2066e2fc99cb69b236f6903cbadca3396c20b7bfe7337aa279226a7bcbf6", "993c1f9416d6beb919f6c660e64f2666a3ac6b0e9b7bd7eb61d6793c42239966", "fd6c9f93e9b1f1160a639d992e03696644e026dc6420ef0b9997907071d733b9", "d26946cc167da1999096c316b6269a4401ffb24bdf963d764b6f0f3aa93f09c0", "4667c02dc20fc6b4e6f342e6499c9dae96a76c6fee9c7d226f966e60f99fcfd9", "97a379c43660f699cf26b9bd2d1329f30ed4f29b737a9c3990c1a06a4269a623", "134a97dd9c34247aac979f7a417b41473b600996e970091da1a064317ac7ded0", "16b46d6671befcb6463ea96971b93e6efb9d9617997437933b96317476c9009a", "6f06471d7a69179d9cd36ca299d6033331e1ad3c676f1964f2a306e40eccca2e" ], "HostConfig": { "Binds": [ "/root/test/data/mariadb:/var/lib/mysql" ], "ContainerIDFile": "", "LogConfig": { "Type": "json-file", "Config": { "max-file": "3", "max-size": "1g" } }, "NetworkMode": "default", "PortBindings": { "3306/tcp": [ { "HostIp": "", "HostPort": "3306" } ] }, "RestartPolicy": { "Name": "always", "MaximumRetryCount": 0 }, "AutoRemove": false, "VolumeDriver": "", "VolumesFrom": null, "CapAdd": null, "CapDrop": null, "Capabilities": null, "Dns": [], "DnsOptions": [], "DnsSearch": [], "ExtraHosts": null, "GroupAdd": null, "IpcMode": "private", "Cgroup": "", "Links": null, "OomScoreAdj": 0, "PidMode": "", "Privileged": true, "PublishAllPorts": false, "ReadonlyRootfs": false, "SecurityOpt": [ "label=disable" ], "UTSMode": "", "UsernsMode": "", "ShmSize": 67109964, "Runtime": "runc", "ConsoleSize": [ 0, 0 ], "Isolation": "", "CpuShares": 0, "Memory": 0, "NanoCpus": 0, "CgroupParent": "", "BlkioWeight": 0, "BlkioWeightDevice": [], "BlkioDeviceReadBps": null, "BlkioDeviceWriteBps": null, "BlkioDeviceReadIOps": null, "BlkioDeviceWriteIOps": null, "CpuPeriod": 0, "CpuQuota": 0, "CpuRealtimePeriod": 0, "CpuRealtimeRuntime": 0, "CpusetCpus": "", "CpusetMems": "", "Devices": [], "DeviceCgroupRules": null, "DeviceRequests": null, "KernelMemory": 0, "KernelMemoryTCP": 0, "MemoryReservation": 0, "MemorySwap": 0, "MemorySwappiness": null, "OomKillDisable": false, "PidsLimit": null, "Ulimits": null, "CpuCount": 0, "CpuPercent": 0, "IOMaximumIOps": 0, "IOMaximumBandwidth": 0, "MaskedPaths": null, "ReadonlyPaths": null }, "GraphDriver": { "Data": { "LowerDir": "/var/lib/docker/overlay2/9c6b99c3d399aed0136d206be94f7e197c369efabcc4c991246e64cad9699393-init/diff:/var/lib/docker/overlay2/f63999479d9b7c440bd46696326a7e6792cf6b6cd491e2090bd6c042aaae91cc/diff:/var/lib/docker/overlay2/df3aa0ee0d40c1df7cad9bae013c9693caa44fb99c1f9a3a334cb0f039b76c23/diff:/var/lib/docker/overlay2/669f3969cb3e0daf3afbd6f7abf39dba640bbac3694d3aa626b6e6baaf9d6f6a/diff:/var/lib/docker/overlay2/0cc6eab39b7e36d16ba9b11ad37b44c0fa49f9677c99caf11940a4ef6c9ab6f0/diff:/var/lib/docker/overlay2/9041baa60966c293343699677da90d3ed1b09b7ec4ba94db966ffcf929baac9a/diff:/var/lib/docker/overlay2/76079077609ffc4de620229be23967c1f499e7b0676960cb711f3b477901ab40/diff:/var/lib/docker/overlay2/60477a4697dec3f7a93796d3d0396e6091add1fc14c0cbe327929bb12d3bad43/diff:/var/lib/docker/overlay2/79cae3146de3414934b0e9696066b6ed6e7d7cc0ab62ff1cbff7fffc462ece76/diff:/var/lib/docker/overlay2/ba4c19ce6d3ef7c623627c2e4d769afe316b326d0991fc7e6e99cce69dac44e4/diff:/var/lib/docker/overlay2/fdbf036fa609629b03919f466129c2d1161a7b2140beac69d6679ee49a7e66dc/diff:/var/lib/docker/overlay2/7a34ab43a76c0bf6f6e39961c66fe7f9edad67296f96e914f79f614aa6fea091/diff:/var/lib/docker/overlay2/c22a9966c30ae9fdfca2666d6031940e316694619cbec24936b29a31be111ac6/diff:/var/lib/docker/overlay2/b42092cffe9796196dda94316e34d9d66d2bd4e4ef0b7af3466306c676a91726/diff:/var/lib/docker/overlay2/6edb02afa6d461db16b6fa93ff1991496dcefbc91916601d3dca930e36ae33ac/diff:/var/lib/docker/overlay2/6662e3d9fddc96e003276ebe7723dc3249c90960296a6ee96b2064c926999f60/diff:/var/lib/docker/overlay2/7c21bc2fed92c43af76224b90caf29bd04172a6d6fd2b44fe71679ea9ab4e7dc/diff:/var/lib/docker/overlay2/971c69a1919e1e4a10cadc19071ad46ada7c6af2fbda761c4f1d96706f63b1f6/diff:/var/lib/docker/overlay2/430341b6ae26699411d7bd6ce9bb43604979e76e66406bfd6e29aa0a74ad620a/diff:/var/lib/docker/overlay2/c1e77dcfe7e626669d6b6a3776e6b4006ad67a4fb3f9334a9e01e4ec4d209db7/diff", "MergedDir": "/var/lib/docker/overlay2/9c6b99c3d399aed0136d206be94f7e197c369efabcc4c991246e64cad9699393/merged", "UpperDir": "/var/lib/docker/overlay2/9c6b99c3d399aed0136d206be94f7e197c369efabcc4c991246e64cad9699393/diff", "WorkDir": "/var/lib/docker/overlay2/9c6b99c3d399aed0136d206be94f7e197c369efabcc4c991246e64cad9699393/work" }, "Name": "overlay2" }, "Mounts": [ { "Type": "bind", "Source": "/root/test/data/mariadb", "Destination": "/var/lib/mysql", "Mode": "", "RW": true, "Propagation": "rprivate" } ], "Config": { "Hostname": "d4a31e9e36a6", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "ExposedPorts": { "3306/tcp": {} }, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "MYSQL_ROOT_PASSWORD=P@ssW0rd", "TZ=Asia/Shanghai", "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "GOSU_VERSION=1.10", "GPG_KEYS=177F4010FE66CA3336300306F1666F24C74CD1D9", "MARIADB_MAJOR=10.4", "MARIADB_VERSION=1:10.4.11+maria~bionic", "AUTO_RUN_DIR=/docker-entrypoint-initdb.d", "INSTALL_DB_SQL=test_0_efv_init.sql" ], "Cmd": [ "mysqld" ], "Image": "test_0_efv:10.4.11", "Volumes": { "/var/lib/mysql": {} }, "WorkingDir": "", "Entrypoint": [ "docker-entrypoint.sh" ], "OnBuild": null, "Labels": {} }, "NetworkSettings": { "Bridge": "", "SandboxID": "d1fa9c90777010769f9c2f6766732a0a72e0aa1477242203cee6f64966bee947", "HairpinMode": false, "LinkLocalIPv6Address": "", "LinkLocalIPv6PrefixLen": 0, "Ports": { "3306/tcp": [ { "HostIp": "0.0.0.0", "HostPort": "3306" } ] }, "SandboxKey": "/var/run/docker/netns/d1fa9c907770", "SecondaryIPAddresses": null, "SecondaryIPv6Addresses": null, "EndpointID": "139c9639f3d413ec9cff69f71eaf6f06f7617627746a1ba939c9f604eb96eb39", "Gateway": "172.17.0.1", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "IPAddress": "172.17.0.2", "IPPrefixLen": 16, "IPv6Gateway": "", "MacAddress": "02:42:ac:11:00:02", "Networks": { "bridge": { "IPAMConfig": null, "Links": null, "Aliases": null, "NetworkID": "aa026c39aa6f9bdb46d3d1c49ffd4e16bbeab4ea79627d2cfcbfbddce6261c29", "EndpointID": "139c9639f3d413ec9cff69f71eaf6f06f7617627746a1ba939c9f604eb96eb39", "Gateway": "172.17.0.1", "IPAddress": "172.17.0.2", "IPPrefixLen": 16, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "MacAddress": "02:42:ac:11:00:02", "DriverOpts": null } } } } ]