在容器中部署MySQL
2022-04-30 09:18 abce 阅读(831) 评论(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
}
}
}
}
]

浙公网安备 33010602011771号