挂载配置文件是docker中mysql端口修改生效的前提,未挂载则重启必回滚;必须将/etc/mysql/my.cnf挂载至宿主机,且port = 3307须置于[mysqld]段内、同步调整-p映射与防火墙规则,并通过ss -tlnp和docker logs验证而非仅查select @@port。

确认容器是否挂载了配置文件
没挂载就硬改,等于每次重启都回滚。Docker里改端口最省事的方式,是在启动时就把 /etc/mysql/my.cnf 挂载到宿主机——这样后续所有修改都在宿主机上操作,容器一重启就生效。
检查当前容器有没有挂载配置目录:
- 运行
docker inspect mysql8 | grep -A 5 "Mounts",看输出里有没有类似"Source": "/path/on/host/my.cnf", "Destination": "/etc/mysql/my.cnf"的条目 - 如果没有,
docker exec -it mysql8 ls -l /etc/mysql/my.cnf查看该文件是否只读、是否属于镜像层(即不可写) - 如果没挂载且容器内不可写,别在容器里折腾 vim 或 apt install,直接停容器、重跑、加
-v /host/path/my.cnf:/etc/mysql/my.cnf
改配置必须写对段和格式
port = 3307 写错位置或格式,MySQL 启动时根本不会报错,但也不会监听新端口。它只会安静地继续听 3306 —— 你查 ss -tlnp | grep :3307 什么也看不到。
- 只能写在
[mysqld]段里,不能写在[client]或[mysql]下(那只是改客户端默认行为) - 等号前后允许空格,但行首不能有空格,行尾不能有中文分号、全角字符、注释符
#或多余空格 - 确保没有重复的
port行;如果有,以第一个有效行为准(后面会被忽略) - 删掉同段里的
skip-networking = 1,否则端口设置完全失效
宿主机端口映射和防火墙要同步动
容器内监听了 3307,不代表你能从外面连上。Docker 的 -p 是桥接映射,不是自动穿透。
- 原命令是
-p 3306:3306,得改成-p 3307:3307(左边是宿主机端口,右边是容器内端口) - 如果用的是
--network host模式,则不用-p,但宿主机防火墙(firewall-cmd或ufw)仍需放行 3307 - 云服务器(阿里云/腾讯云)的安全组规则必须手动新增入方向 TCP 3307,这个漏掉,连本地
telnet your-server-ip 3307都不通
验证端口是否真生效,别信 SELECT @@port
SELECT @@port 返回的是当前连接所用的端口,不是 MySQL 实际监听的端口。你可能连上了另一个实例(比如 Docker Compose 里另一个 MySQL 容器),而你刚改完配置的那个根本没起来。
- 先看进程监听:
docker exec mysql8 ss -tlnp | grep :3307(容器内)或ss -tlnp | grep :3307(宿主机) - 再看错误日志:
docker logs mysql8 2>&1 | tail -20,重点找Can't start server、Address already in use或bind相关报错 - 最后才是连进去查:
docker exec -it mysql8 mysql -uroot -p -e "show global variables like 'port';"
改端口这事,真正卡住人的从来不是配置文件那一行,而是改完之后没动映射、没开防火墙、没查日志就以为成功了。











