【docker】配置mysql及数据持久化
前言
一、使用docker时常用的命令
1、用usermod命令向docker用户组添加新用户
当前登陆用户是hero,直接使用命令docker ps会报错
Cannot connect to the Docker daemon at unix:///home/hero/.docker/desktop/docker.sock. Is the docker daemon running?
- 增加用户权限
- 考虑home目录下面残存的.docker文件夹的配置
sudo usermod -aG docker hero
# 等效命令如下
# sudo gpasswd -a $USER docker
重新登陆后,再使用不带sudo前缀的命令
docker ps
systemctl daemon-reload && systemctl restart docker
问题:使用docker ps的时候不行,使用sudo docker ps的时候可以。
思考:使用sudo是提升权限,可hero用户已具备docker组的权限了,为什么还是不行?
分析:可能是docker的配置过程使用了装饰模式,并在不断的装饰流程中存在优先级更高的配置。
操作:删除hero专属的/home/hero/.docker文件夹,就一切正常了。
结论:曾安装过docker中残留的配置文件夹.docker将/etc/docker中的套接字设置覆盖了,使用sudo命令不经过当前用户的配置文件夹。
2、给docker的images打标签
docker image tag mysql:latest mysql:new
docker image tag mysql:latest mysql:new
# 删除原来的镜像
docker rmi mysql:new
重新登陆后,再使用不带sudo前缀的命令
docker ps
systemctl daemon-reload && systemctl restart docker
问题:使用docker ps的时候不行,使用sudo docker ps的时候可以。
思考:使用sudo是提升权限,可hero用户已具备docker组的权限了,为什么还是不行?
分析:可能是docker的配置过程使用了装饰模式,并在不断的装饰流程中存在优先级更高的配置。
操作:删除hero专属的/home/hero/.docker文件夹,就一切正常了。
结论:曾安装过docker中残留的配置文件夹.docker将/etc/docker中的套接字设置覆盖了,使用sudo命令不经过当前用户的配置文件夹。
二、docker相关的环境配置
1、配置文件的生效条件
/etc/profile文件的环境变量所有用户可用,只在用户登陆的时候执行一次,安装编译好的全局软件时常用。
2、 系统状态查看
三、工具配置
- docker添加镜像源
- docker配置mysql
1、配置docker镜像源
# 1. 去阿里云获取私有的镜像源地址
# https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors
sudo vi /etc/docker/daemon.json
# 2. 输入类似下面的内容(下面的n1856ohl是虚拟的,你需要到阿里云的容器镜像服务中复制)
{
"registry-mirrors": ["https://n1856ohl.mirror.aliyuncs.com"]
}
# 3. 保存上面结果后,重启docker以便使配置生效
systemctl restart docker
进行验证
docker info
输出的倒数几行出现提示Registry Mirrors:后面的内容正确
......(省略前面部分内容)
Docker Root Dir: /var/lib/docker
Debug Mode: false
Experimental: false
Insecure Registries:
127.0.0.0/8
Registry Mirrors:
https://n1856ohl.mirror.aliyuncs.com/
Live Restore Enabled: false
2、使用docker创建容器(以mysql为例)
查看镜像版本信息
可以去网站https://hub.docker.com/查看镜像的版本信息
拉取镜像
拉取镜像的命令可以在docker官网寻找,或者直接使用命令docker search mysql:8.0 --no-trunc寻找
docker pull mysql:8.0.18
创建和启动
init-create-container-mysql8.sh
其中创建目录的-p有如下作用:
如果目录不存在,mkdir -p 会创建它以及所有必要的上级目录。如果目录已经存在,mkdir -p 会静默地成功执行,不会显示任何错误消息或警告。
# 新建挂载目录,分别是数据、配置文件
mkdir -p /my_data/docker_data/mysql8/lib_data
mkdir -p /my_data/docker_data/mysql8/logs
mkdir -p /my_data/docker_data/mysql8/conf
cp my.cnf /my_data/docker_data/mysql8/conf/my.cnf
bash create-container-mysql8.sh
运行文件create-container-mysql8.sh的内容如下,特别注意以下几点
:
- 每行中,符号""后面不要留下空格,否则会运行错误;
- 使用-v挂载的是宿主机路径:容器路径,如果没有针对容器内环境进行特定修改,那么容器内的路径是固定的不可修改的!
- 从第二点出发再强调一下,宿主机路径也就是真实物理机路径放在冒号前面
#!/bin/sh
docker run \
-p 3307:3306 \
--name mysql8 \
--privileged=true \
--restart unless-stopped \
-v /my_data/docker_data/mysql8/conf:/etc/mysql/conf.d \
-v /my_data/docker_data/mysql8/logs:/logs \
-v /my_data/docker_data/mysql8/lib_data:/var/lib/mysql \
-v /etc/localtime:/etc/localtime \
-e MYSQL_ROOT_PASSWORD=123456 \
-d mysql:8.0.20
# -p 端口映射 【这里有个特殊的地方是把3306映射给了3307、后续链接数据库的时候用3307链接不用3306】
# --name mysql8 名称是mysql8
# --privileged=true 挂载文件权限设置
# --restart unless-stopped 设置 开机后自动重启容器
# -v /my_data/docker_data/mysql8/conf:/etc/mysql/conf.d \ 挂载配置文件
# -v /my_data/docker_data/mysql8/logs:/logs \ 挂载日志
# -v /my_data/docker_data/mysql8/lib_data:/var/lib/mysql \ 挂载数据文件 持久化到主机
# -v /etc/localtime:/etc/localtime 容器时间与宿主机同步
# -e MYSQL_ROOT_PASSWORD=123456 设置密码
# -d mysql:8.0.20 指定之前pull的image,如果pull过多个mysql,就要加上冒号并注明版本号
超级简单化的示例版本
#启动
docker run --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=Lzslov123! -d mysql:8.0.20
进入mysql容器
# 进入容器内部
docker exec -it mysql8 bash
# 在容器内部登陆mysql,使用mysql的root用户,密码是之前启动镜像的123456
mysql -u root -p
# 查看mysql自带的root用户的原始数据表
show databases;
“WITH mysql_native_password” 是 MySQL 数据库中的一种身份验证插件,用于对用户进行身份验证。它使用 MySQL 原生的密码加密算法,是 MySQL 8.0 版本之后默认的身份验证方式。使用 “WITH mysql_native_password” 可以保证数据库的安全性,并且兼容旧版本的 MySQL 客户端。
如果是mysql8之前的版本,那么就要额外使用ALTER USER ‘root’@‘%’ IDENTIFIED WITH mysql_native_password BY ‘123456’;
创建新用户,并更改可以使用的作用域。
# 使用记录有用户信息的数据库mysql
use mysql
#添加远程登录用户
CREATE USER 'sxl'@'%' IDENTIFIED WITH mysql_native_password BY '20000307';
GRANT ALL PRIVILEGES ON *.* TO 'sxl'@'%';
# 查看mysql服务中mysql数据表中记录的用户和允许访问的站点IP范围
select user,host from user;
#删除多余的root用户
DROP USER 'root'@'localhost';
select user,host from user;
退出mysql容器
使用Ctrl +D,或者输入exit后回车
停止并删除容器
docker stop mysql8
docker rm -f mysql8
docker ps命令只能看到当前正在运行的容器,
docker ps -a命令能看到正在运行的容器和已stop的容器,
docker rm -f 命令可以删除容器,
docker start 命令可以重新启动容器,
docker restart 等效于docker stop + docker start命令
四、导入数据
使用vscode迁移后,
进入mysql容器,然后使用下面的命令进入mysql
mysql -u root -p
source /home/my_app_data_10_1_1_102-2024_07_23_20_52_48-dump.sql
show databases;
五、错误记录
1、启动失败问题排查
(1)利用logs来寻找启动失败的原因
先将启动选项里面的–restart unless-stopped变为–restart no,然后启动镜像后,使用命令docker logs mysql8
docker rm -f mysql8
chmod 755 my.cnf
bash init-create-container-mysql8.sh
还是会出现错误:
[ERROR] [MY-011087] [Server] Different lower_case_table_names settings for server ('1') and data dictionary ('0').
原因是之前的my.cnf没有生效,而数据文件生效。
数据文件中默认的linux设置中mysql8的默认设置是lower_case_table_names=0,和现在的lower_case_table_names=1冲突。
措施是删除数据持久文件夹/my_data/docker_data/mysql8/lib_data的内容,并重新部署
docker logs mysql8
docker ps
2. 记录相关设置,开发时候留意
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
STRICT_TRANS_TABLES:
这个模式要求 MySQL 对事务型表(InnoDB、NDB)执行严格的检查。如果插入或更新的数据违反了表的列定义(如数据类型不匹配、超出范围等),MySQL 将拒绝执行并返回错误。这有助于防止数据损坏,确保数据的完整性和准确性。然而,对于非事务型表(如 MyISAM),此模式可能不会强制执行严格的检查。
NO_ZERO_IN_DATE:
禁用日期和月份中的零值。这意味着,如果尝试插入或更新日期字段为 ‘2023-00-01’ 或 ‘2023-01-00’,MySQL 将拒绝此类操作并返回错误。这有助于防止创建无效的日期值。
NO_ZERO_DATE:
禁用零日期(‘0000-00-00’)。在默认情况下,MySQL 允许使用 ‘0000-00-00’ 作为有效的日期值,但这在某些情况下可能会引起混淆或错误。启用此模式后,任何尝试插入或更新为零日期的操作都将被拒绝。
ERROR_FOR_DIVISION_BY_ZERO:
当执行除法运算时,如果除数为零,MySQL 默认会返回 NULL。但是,如果启用了此模式,MySQL 将改为返回错误,而不是 NULL。这有助于捕获潜在的逻辑错误,特别是在数据可能意外包含零值的情况下。
NO_ENGINE_SUBSTITUTION:
禁止在自动创建或修改表时,如果首选的存储引擎不可用,MySQL 自动选择其他存储引擎。默认情况下,如果 MySQL 无法使用指定的存储引擎(如 InnoDB),它可能会选择另一个可用的存储引擎(如 MyISAM)。启用此模式后,如果首选的存储引擎不可用,MySQL 将拒绝创建或修改表,并返回错误。
总结
易错点:
- 写sql语句的时候,from不要写成form;
- 从mysql8开始,数据库一开始的初始化就要决定好区分不区分大小写,并且后续不支持修改,详情见[4];
- 记录my.cnf里面的sql_mode设置,进行开发的时候注意遵守;
[1] https://www.cnblogs.com/wuyicode/p/18136825
[2] https://blog.csdn.net/a1150499208/article/details/131437199
[3] https://www.runoob.com/docker/docker-install-mysql.html
[4] https://www.cnblogs.com/greatsql/p/16634739.html