我一直觉得,用 Docker 跑 MySQL 是本地开发最省心的方案,没有之一。你不需要去官网找下载链接,不需要担心系统里残留旧版本,更不用为了给测试环境换一个 MySQL 8.0 而把自己机器上的 5.7 卸载掉。一条docker run命令,MySQL 就在你手边,用完还能随手删掉,删完数据文件照样留在宿主机里。这篇文章我直接以“用 Docker 启动 MySQL”为主线,从环境准备、镜像选择、容器启动、数据持久化到日常维护和问题排查,把步骤拆开讲透。适合刚接触 Docker 的新手,也适合那些已经装了 Docker 但每次启动 MySQL 都要翻文档的人。
先说清楚我能帮你解决什么:如果你经常需要在本机起一个 MySQL,或者准备写 JavaWeb 项目需要数据库环境,又或者想快速起一个指定版本的 MySQL 做测试,这篇文章都能直接照着抄。我会把每一步背后的原理讲明白,比如为什么要挂载数据卷、为什么要指定字符集,而不是只丢给你一串命令。
1. 为什么用 Docker 跑 MySQL 而不是直接装
1.1 本地安装的痛点
直接在操作系统里装 MySQL,最麻烦的就是“环境残留”。Windows 上卸载 MySQL 要手动删服务、清注册表,Linux 上要处理一堆依赖,稍不注意系统里就同时存在 mysql 和 mariadb 两个版本,3306端口被占、mysql命令指向另一个客户端,这些问题我踩过不止一次。你排查了半天,最后发现是环境变量 PATH 指向了旧版本,这种挫败感相信很多人都有。
还有多版本切换的问题。项目 A 用的是 MySQL 8.0,项目 B 用的是 5.7,本地直装方案几乎没法优雅共存。有人用 Docker 之前是怎么解决的?装两遍?用虚拟机再开一个?要么麻烦,要么笨重。Docker 把这些问题全部消灭在容器层面。
1.2 Docker 方案的核心优势
Docker 跑 MySQL 的核心逻辑就是“把数据库当作一个可随时创建和销毁的进程”。镜像把 MySQL 的二进制文件、配置模板、依赖环境全部打包好,容器启动后就是一个独立运行实例。你不需要关心它实际装在哪个目录,只需要通过端口、数据卷和环境变量来跟它交互。
隔离性是最直观的好处。宿主机上不需要安装任何 MySQL 相关的库,所有依赖都藏在镜像里。端口我是通过-p 3306:3306手动映射的,你想让 MySQL 暴露在 3307 端口也可以,完全不影响宿主机上已有的其他服务。
可重复性也极其重要。一个项目的数据库环境可以通过一段docker run命令或者一份docker-compose.yml完整描述,新同事入职拉下仓库,一条命令就还原出和你一模一样的 MySQL,彻底告别“在我电脑上是好的”这种经典借口。
1.3 适用场景
如果你问我什么场景下适合用 Docker 跑 MySQL,我列几个典型场景:
- 日常本地开发:写代码需要连数据库,随时起一个临时 MySQL,用完就停。
- 测试环境:反复初始化数据、切换版本,容器删掉重来只需要几秒钟。
- 多项目并行:不同项目依赖不同 MySQL 版本,用不同容器、不同端口相互隔离。
- 学习练手:学 SQL、学索引优化、学主从复制,不想弄脏自己的机器。
相反,如果是生产环境、高性能要求的正式业务,我一般不建议用 Docker 跑 MySQL,倒不是说容器技术不行,而是生产环境对运维监控、性能调优、故障恢复的要求更高,直接原生部署更容易跟监控系统对接。文章后面讲的都是开发、测试和个人项目场景。
2. 环境准备:先把 Docker 装好
2.1 Windows 上安装 Docker Desktop
Windows 上最常用的方案是 Docker Desktop。安装包可以直接从 Docker 官网下载,但有一个前提条件:系统需要开启虚拟化。如果你在安装后启动 Docker Desktop 时看到报错virtualization support not detected,大概率是虚拟化没开。
处理方式很简单:重启进 BIOS,找到 Intel Virtual Technology(Intel VT-x)或者 AMD SVM Mode,把它设为 Enabled,保存退出。如果 BIOS 里已经开了但还是报错,那就检查 Windows 的“虚拟机平台”和“适用于 Linux 的 Windows 子系统”这两个功能有没有启用。建议在“控制面板 - 程序 - 启用或关闭 Windows 功能”里勾选这两个选项,重启后再启动 Docker Desktop。
装好 Docker Desktop 后,建议在设置里把 WSL 2 作为后端,这是目前 Windows 下跑 Docker 最稳定的方案。WSL 2 的性能比老的 Hyper-V 方案更好,内存占用也更可控。安装时 Docker Desktop 一般会提示你启用 WSL,照着来就行。
2.2 macOS 与 Linux 上的安装
macOS 也是直接用 Docker Desktop,Apple Silicon 芯片选对应 arm64 版本,Intel 芯片选 x86_64 版本。双击安装,拖进 Applications 就行。Ubuntu 这类 Linux 发行版不需要桌面版,直接命令行装 Docker Engine:
sudo apt update sudo apt install -y docker.io sudo systemctl enable --now dockerCentOS/RHEL 系用yum install -y docker-ce或者yum install -y docker,具体看发行版本。装完验证一下:
docker version能看到 client 和 server 两段信息就说明安装成功。如果 server 段报错Cannot connect to the Docker daemon,多半是当前用户没有 docker 组权限,运行sudo usermod -aG docker $USER后重新登录一次。这是 Linux 上最常见的新手问题,一定要先加上。
2.3 验证 Docker 环境
容器能不能跑,先执行docker ps看当前运行的容器列表。如果没有任何报错,说明 Docker 守护进程是正常的。然后再跑一个最简单的测试:
docker run hello-world能正常打印出 Hello from Docker 的提示,说明整个流程通了。这一步其实很关键,因为后面 MySQL 容器启动失败时,你要能区分是 Docker 本身的问题还是 MySQL 配置的问题。我习惯在排查一切容器问题前先确保 hello-world 能跑通。
3. 选择镜像与版本:该拉哪个 MySQL 镜像
3.1 官方镜像与版本选择
Docker Hub 上的 MySQL 官方镜像叫mysql,我建议直接使用官方镜像,不要使用第三方打包的版本。官方镜像的维护质量、安全更新和文档完整度都是最有保障的。
版本方面,我的建议是:新项目直接用mysql:8.0,老项目需要兼容再选mysql:5.7。MySQL 8.0 是当前的主流版本,新建的 JavaWeb 项目、Spring Boot 项目基本都是围绕 8.0 开发的,8.0 的默认字符集是utf8mb4,对中文、emoji 的支持更完善。如果项目代码里用了老版本的mysql-connector-java或者某些老的 ORM 框架,那就要谨慎一点,8.0 的认证插件变化比较大,稍后我会在问题排查章节单独讲。
具体某个小版本可以不指定,直接用大版本标签就行,比如mysql:8.0会自动指向最新的 8.0 版本。如果你要复现一个特定环境,那就精确到mysql:8.0.38这样的完整标签。注意,mysql:latest目前也是 8.0 系列,但不建议用 latest 标签,因为它会随着官方更新变动,容易导致环境漂移。
3.2 镜像拉取与国内加速配置
拉取镜像:
docker pull mysql:8.0如果你在国内,直接拉官方镜像可能会比较慢,甚至超时。这时候可以配置镜像加速器。Docker Desktop 的设置里有一个 Docker Engine 配置项,把仓库地址写进去:
{ "registry-mirrors": [ "https://docker.m.daocloud.io" ] }保存后重启 Docker Desktop,再重新拉取镜像,速度会好很多。Linux 上则是修改/etc/docker/daemon.json,内容一样,改完重启 docker 服务:
sudo systemctl restart docker拉取完成后用docker images查看当前本地已有的镜像,能看到mysql镜像和对应的 tag 就说明拉取成功了。
3.3 镜像大小与分层视角
用 Docker 跑 MySQL 之前,你还要理解一个概念:镜像和容器的关系。镜像是一个只读模板,容器是它的运行实例。你可以把镜像理解为“光盘里的安装包”,容器是“电脑上跑起来的程序”。同一个镜像可以同时启动多个容器,只要端口和容器名不冲突就行。所以我拉取一个 MySQL 镜像后,可以同时跑一个 3306 端口的开发库和一个 3307 端口的测试库,互不干扰。
4. 用 docker run 启动 MySQL 容器
4.1 一条完整的启动命令
下面是我日常最常用的命令,直接复制就能用:
docker run -d \ --name mysql-dev \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORD=root123456 \ -e TZ=Asia/Shanghai \ -v mysql-data:/var/lib/mysql \ -v mysql-config:/etc/mysql/conf.d \ mysql:8.0-d表示后台运行,不加的话容器会占据当前终端,关掉终端容器就停了,很不方便。--name给容器起个名字,方便后续用docker stop mysql-dev、docker logs mysql-dev这样的命令操作。-p 3306:3306把宿主机的 3306 端口映射到容器的 3306 端口,前者是宿主机端口,后者是容器内端口。如果你宿主机 3306 被占,可以改成-p 3307:3306,那么客户端连接时就要连localhost:3307。
4.2 环境变量详解
MYSQL_ROOT_PASSWORD是 root 用户的初始密码,这是 MySQL 容器最核心的环境变量。MYSQL_DATABASE可以指定容器启动时自动创建数据库,MYSQL_USER和MYSQL_PASSWORD则可以创建一个普通用户并授权。比如:
docker run -d \ --name mysql-dev \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORD=root123456 \ -e MYSQL_DATABASE=mydb \ -e MYSQL_USER=test \ -e MYSQL_PASSWORD=test123 \ -v mysql-data:/var/lib/mysql \ mysql:8.0这样启动完成后,容器里就已经存在一个mydb数据库,以及test这个只对mydb有权限的用户。注意MYSQL_USER只会被赋予MYSQL_DATABASE的权限,不会自动赋予其他库的权限,需要额外用 SQL 授权。
TZ=Asia/Shanghai是时区设置。MySQL 容器默认时区是 UTC,如果不设置,NOW()函数的返回值会比北京时间早 8 个小时,排查问题时很容易让你怀疑人生。我没有用官方推荐的-e TZ=Asia/Shanghai时,写日志的时间全是 UTC 时间,后来踩过一次坑之后就养成了必加时区的习惯。
4.3 数据卷与持久化
MySQL 容器最忌讳的事情就是“删容器丢数据”。默认情况下,容器内的/var/lib/mysql目录是 MySQL 存放数据文件的位置,一旦容器被删除,数据会跟着容器消失。解决方式就是挂载数据卷。
-v mysql-data:/var/lib/mysql表示把名为mysql-data的 Docker 数据卷挂载到容器内的数据目录。这种叫 named volume,Docker 负责在宿主机上管理这个数据卷的实际存储位置,你不需要关心它在哪,备份和迁移时也有统一的接口。如果你想直接绑定宿主机的某个具体目录,也可以写:
-v /home/me/mysql/data:/var/lib/mysql这种叫 bind mount。好处是数据文件清晰可查,直接进目录就能看到;坏处是目录权限偶尔会出问题,比如容器里的 mysql 用户 UID 和宿主机的 UID 不一致可能导致无法写入。我个人更推荐 named volume,省心。
第二次挂载的-v mysql-config:/etc/mysql/conf.d是把配置目录挂载出来,后续想追加自定义my.cnf配置而不进入容器,直接往数据卷里放配置文件就行。这一步不是必须的,但值得做,因为 MySQL 调优、修改字符集等场景下你会感谢这个挂载。
4.4 启动后验证
执行完docker run,马上验证容器状态:
docker ps输出里能看到mysql-dev的状态是Up,端口一列显示0.0.0.0:3306->3306/tcp,说明启动成功。如果状态是Exited或者还在Restarting,继续往下看日志:
docker logs mysql-dev看到类似于ready for connections的日志,又或者是mysqld: ready for connections,就可以尝试连接了。在宿主机上执行:
mysql -h127.0.0.1 -P3306 -uroot -p如果你宿主机没有安装 MySQL 客户端,可以进入容器执行:
docker exec -it mysql-dev mysql -uroot -p输入之前设置的MYSQL_ROOT_PASSWORD,出现mysql>提示符就说明整套流程已经走通。之所以用-h127.0.0.1而不是localhost,是因为有些客户端把localhost解析成 socket 文件连接,而容器里的 socket 文件路径跟宿主机不一样,容易报ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock'。用 IP 连接可以绕过这个问题。
5. 日常操作:进入容器管理 MySQL
5.1 容器内执行 SQL
容器启动起来之后,日常管理操作用得最多的是docker exec。这个命令的语法是:
docker exec -it mysql-dev mysql -uroot -p-it组合参数表示开启交互式终端。进去之后就是正常的 MySQL 命令行,你想执行 SQL 就敲 SQL。除了交互模式,还可以直接传入 SQL 命令,适合写脚本和快速查看数据:
docker exec mysql-dev mysql -uroot -p123456 -e "show databases;"注意-p和密码之间不要有空格,直接连写-p123456,否则会提示你手动输入。这种方式在脚本里很实用,比如快速查看某个表的数据、快速执行一条更新。我不建议把密码写在命令里用于生产环境,但本地开发图个方便完全没问题。
5.2 创建数据库与用户授权
进入 MySQL 后,第一件事通常是创建业务库和一个专门的业务账号。用 root 直接跑业务代码不是好习惯,root 权限太大,一旦代码里存在 SQL 注入漏洞,数据库会被整个拖走。我的习惯是每个业务库配一个独立账号。
创建数据库:
CREATE DATABASE myapp DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;创建用户并授权:
CREATE USER 'myapp_user'@'%' IDENTIFIED BY 'myapp_pass123'; GRANT ALL PRIVILEGES ON myapp.* TO 'myapp_user'@'%'; FLUSH PRIVILEGES;这里的'%'表示允许从任意主机连接。如果只想允许本机连接,改成'localhost'即可,但容器环境下一般客户端是通过宿主机 IP 连接,所以%更实用。记得把字符集明确指定为utf8mb4,MySQL 8.0 默认就是utf8mb4,但手动写出来可以避免老配置文件带来的不确定性。
5.3 修改 root 密码与认证插件
本地开发时可以随时改 root 密码:
ALTER USER 'root'@'%' IDENTIFIED BY 'newpassword123'; FLUSH PRIVILEGES;改完以后重启容器或者重新连接生效。很多时候客户端工具连接不上 MySQL 8.0,报Authentication plugin 'caching_sha2_password' cannot be loaded,这是因为 MySQL 8.0 默认认证插件是caching_sha2_password,而一些老的客户端(特别是老版本 Navicat、旧版 JDBC 驱动)不支持。这种情况有两个解法:
第一种,升级客户端到最新版本。现在 Navicat 16+、最新 MySQL Workbench、最新的mysql-connector-java都支持caching_sha2_password。
第二种,把用户的认证插件改回mysql_native_password:
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'root123456'; FLUSH PRIVILEGES;这个操作对老客户端兼容性最好,但安全性理论上低于caching_sha2_password。本地开发图省事可以直接改,生产环境建议升级客户端而不是降级认证插件。
5.4 容器内配置自定义 my.cnf
如果你需要修改 MySQL 配置,比如开启慢查询日志、调整max_connections、修改sql_mode,推荐的做法不是直接docker exec进容器改文件,因为容器重建后修改就没了。正确做法是往挂载的配置目录里放一个自定义的my.cnf文件。
前面我挂载了mysql-config:/etc/mysql/conf.d,现在往这个数据卷里写一份配置:
docker run -it --rm -v mysql-config:/etc/mysql/conf.d mysql:8.0 bash进入容器后创建文件:
echo -e "[mysqld]\nmax_connections=500\ncharacter-set-server=utf8mb4\ncollation-server=utf8mb4_general_ci" > /etc/mysql/conf.d/custom.cnf exit然后重启容器:
docker restart mysql-dev重启后用SHOW VARIABLES LIKE 'max_connections';看到值是 500,说明配置生效了。--rm参数表示容器退出后自动删除,这种方式可以快速进入一个临时容器修改数据卷里的文件,不会影响正在运行的mysql-dev容器。
6. 用 Docker Compose 管理 MySQL
6.1 为什么需要 Compose
当你只需要跑一个 MySQL 容器时,docker run足够。但现实情况往往是:一个项目里除了 MySQL,还有 Redis、Nginx、后端应用,如果全部手动docker run,记不住参数不说,清理和重建也麻烦。Docker Compose 用一份 YAML 文件描述“一组容器”的启动配置,一条命令全部拉起,一条命令全部停掉。
MySQL 的 Compose 配置其实是把docker run里的参数翻译成 YAML 结构,本质没有任何区别,但可读性和可维护性大大提升。配置还能提交到 Git,团队成员拿到项目仓库后一条命令就能还原数据库环境,这是我强烈推荐你使用 Compose 的原因。
6.2 编写 docker-compose.yml
创建一个项目目录,比如docker-mysql-demo,在里面新建docker-compose.yml:
services: mysql: image: mysql:8.0 container_name: mysql-compose restart: unless-stopped environment: MYSQL_ROOT_PASSWORD: root123456 MYSQL_DATABASE: mydb TZ: Asia/Shanghai ports: - "3306:3306" volumes: - mysql_data:/var/lib/mysql - ./mysql-conf:/etc/mysql/conf.d command: - --character-set-server=utf8mb4 - --collation-server=utf8mb4_unicode_ci volumes: mysql_data:这里的./mysql-conf是宿主机当前目录下的一个文件夹,用来放自定义配置。command里可以直接追加 mysqld 的启动参数,效果和写配置文件差不多。restart: unless-stopped表示除非手动停止,否则容器会自动重启,这个参数对开发机和服务器很友好。
6.3 Compose 常用命令
在docker-compose.yml所在目录执行:
docker compose up -d这条命令会自动拉取镜像、创建数据卷、启动容器。-d表示后台运行。查看状态:
docker compose ps查看日志:
docker compose logs -f mysql停止但不删除容器:
docker compose stop停止并删除容器(数据卷里的数据还在):
docker compose down注意,down默认不会删除 named volume,数据卷mysql_data还在,下次up数据自动恢复。如果你连数据卷也想一起删就是docker compose down -v,除非你确定数据不要了,否则别加-v。
Docker 的新版命令默认是docker compose(带空格),老的docker-compose命令在旧版本里也能用,新项目直接学新命令即可。如果你还需要批量管理多个 Docker 环境,后续可以把 Compose 项目扩展到 K8s,但那是后话了,先把 Compose 用熟,日常开发已经非常够用。
6.4 数据库备份与恢复
备份 MySQL 数据,最直接的方案是使用mysqldump。即使你的容器在运行,也可以用它导出逻辑备份:
docker exec mysql-compose mysqldump -uroot -p123456 mydb > mydb_backup.sql注意这里mysqldump是在容器内执行的,输出的内容通过 shell 重定向保存到宿主机当前目录。恢复时反过来:
cat mydb_backup.sql | docker exec -i mysql-compose mysql -uroot -p123456 mydb-i参数表示保持标准输入打开,让管道里的 SQL 进入容器内的 mysql 进程。两边都要指定数据库名,恢复前先确保目标数据库存在。这套备份恢复方案在开发环境里已经足够可靠,生产环境一般还要做物理备份和 binlog 增量备份。
7. 常见问题与排查实录
7.1 端口被占用
启动容器时报错Bind for 0.0.0.0:3306 failed: port is already allocated,说明宿主机 3306 端口已经被占用。最常见的原因是本机直接装过 MySQL,服务还开着。排查方式:
netstat -ano | grep 3306找到占用进程后,要么停掉本机 MySQL 服务,要么把容器的宿主机端口映射改成 3307:
docker run -d --name mysql-dev -p 3307:3306 \ -e MYSQL_ROOT_PASSWORD=root123456 \ -v mysql-data:/var/lib/mysql \ mysql:8.0后续连接时使用-P 3307即可。这个方案也适用于同时跑多个 MySQL 实例,比如一个 5.7、一个 8.0,各占一个端口,互不干扰。
7.2 容器启动后秒退或反复重启
容器启动后状态一直显示Restarting,或者起来几秒就退了,第一件事看日志:
docker logs mysql-dev常见错误之一:
[ERROR] [MY-011087] [Server] Different lower_case_table_names settings for server ('1') and data dictionary ('0').这个错误的意思是:数据目录里的初始化配置和容器启动参数里的lower_case_table_names不一致。首次初始化数据卷时使用过某个参数,之后再用不同参数启动同一数据卷就会报这个错。解决办法就是删除数据卷重新初始化:
docker stop mysql-dev docker rm mysql-dev docker volume rm mysql-data注意这个操作会清空所有数据,执行前先确认数据是否已经备份。重新初始化后保持一致参数即可,比如统一使用默认值。
另一个常见错误是权限问题:
[ERROR] [MY-012574] [InnoDB] Unable to lock ./ibdata1 error: 11这个大概率是数据卷目录的权限问题。如果是 bind mount 挂在宿主机目录,容器内 mysql 用户没有写入权限。解决办法是给目录授权:
chown -R 1000:1000 /home/me/mysql/dataMySQL 官方镜像内的 mysql 用户 UID 是 999 还是 1000,不同版本有细微差别,检查后调整。最省事的方案是改用 named volume,让 Docker 自己管理目录权限。
7.3 无法连接:socket 文件报错
宿主机上执行mysql -uroot -p时报:
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock'这个报错在 Docker 环境下非常经典。原因是mysql客户端默认通过 socket 文件连接,但容器里的 socket 文件路径是/var/run/mysqld/mysqld.sock,宿主机当然找不到。解决办法就是强制走 TCP:
mysql -h127.0.0.1 -P3306 -uroot -p加了-h127.0.0.1后客户端就不再尝试 socket 而是走 TCP 协议。还有一种类似情况是容器内执行mysql命令时正常,但宿主机执行报错,也是同一个原因。
7.4 Navicat 等客户端连不上
用 Navicat 连接 Docker 里的 MySQL,遇到以下报错要分清原因:
| 报错信息 | 原因 | 解决办法 |
|---|---|---|
Access denied for user 'root'@'...' | 密码错误或用户未授权 | 检查密码,确认 root 允许%远程登录 |
Authentication plugin 'caching_sha2_password' cannot be loaded | 客户端版本过老 | 升级 Navicat/客户端,或者改回mysql_native_password |
SSL connection error | 客户端开启了 SSL 但服务器证书不可用 | 连接时把 SSL 选项置为 DISABLED |
Navicat 新版一般不会遇到认证插件问题,老版本建议直接升级。SSL 问题在本地环境也可以关掉,因为内网传输默认不加密问题不大,生产环境才需要认真配置证书。
7.5 容器删了数据还在吗
这是新手最容易恐慌的问题。直接回答:只要你用了-v mysql-data:/var/lib/mysql之类的挂载,容器删除后数据还在。你把容器删了、镜像删了,数据卷里的数据文件依然完好。下次重新启动挂载同一个数据卷,数据自动恢复。
如果当初没有挂载数据卷,容器删除后就真的什么都没了。所以我的建议从第一条启动命令开始就加上-v参数,养成习惯。
查看当前数据卷列表:
docker volume ls查看某个数据卷的详细信息:
docker volume inspect mysql-data在这个输出里可以看到Mountpoint路径,这是宿主机上真实存储数据的位置。备份时可以直接打包这个目录,恢复时放到原位置。
7.6 Docker Desktop 启动失败
在 Windows 上遇到 Docker Desktop 无法启动,常见报错有Docker Desktop failed to start because virtualization support is disabled、Cannot connect to the Docker daemon这类。排错顺序我建议是:
- 确认 BIOS 里的虚拟化已开启。
- 确认 Windows 功能里的“虚拟机平台”和“适用于 Linux 的 Windows 子系统”已启用。
- 确认 WSL2 已安装:
wsl --status或者wsl --update。 - 关闭第三方杀毒软件和防火墙试试。
- 检查 Docker Desktop 是否需要更新,旧版本对新系统兼容性差。
遇到failed to connect to the docker api at npipe:////./pipe/dockerDesktopLinuxEngine这样的报错,通常是 Docker 引擎还没启动完成就尝试连接。点击 Docker Desktop 图标,等托盘图标稳定成绿色再执行命令,别急。
8. 几个实操层面的小建议
8.1 容器资源限制
MySQL 是吃内存的大户。如果你本机内存有限,启动容器前最好就限制资源:
docker run -d --name mysql-dev \ --memory=512m --memory-swap=512m \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORD=root123456 \ -v mysql-data:/var/lib/mysql \ mysql:8.0--memory=512m限制容器最多使用 512MB 内存,--memory-swap同时限制 swap。这样跑多个容器时不会因为一个数据库把整机内存吃满。在做生产级调优之前,先用资源限制保证自己的开发机不卡,这是最直接有效的保护手段。
8.2 用别名和脚本固化操作
每次敲一长串docker run命令确实容易打错。我的做法是写一个start_mysql.sh脚本,放在项目里,内容就是完整的docker run命令。以后只要执行脚本就能起一个标准环境。进阶一点可以写几个 alias:
alias mysql-dev='docker exec -it mysql-dev mysql -uroot -p'以后想进 MySQL 命令行,直接敲mysql-dev就行。这套习惯在项目维护中很省时间,尤其是一段时间没碰,回头再看脚本就明白当时是怎么配置的。
8.3 避免使用 root 跑业务
刚用 Docker 跑 MySQL 时,最容易犯的错就是用 root 账号连接业务代码。当年我偷懒直接 root 跑了一个内部系统,后来发现 compile time 没问题,但审计时心里总是不舒服。正确的做法是每个项目建一个独立账号,只授予它需要的库权限。这不是什么高性能技巧,但却是数据库安全的基本素养。用 Docker 建库建用户如此简单,没必要图省事。
9. 最后分享一个我常用的完整流程
我每次在新机器上搭建 MySQL 环境,基本就是下面这套节奏,你可以直接抄:
# 1. 拉镜像 docker pull mysql:8.0 # 2. 启动容器 docker run -d \ --name mysql-dev \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORD=root123456 \ -e MYSQL_DATABASE=mydb \ -e TZ=Asia/Shanghai \ -v mysql-data:/var/lib/mysql \ -v ./mysql-conf:/etc/mysql/conf.d \ mysql:8.0 # 3. 验证 docker ps docker logs mysql-dev # 4. 连接 mysql -h127.0.0.1 -P3306 -uroot -p # 5. 创建业务账号(在 mysql> 里执行) CREATE USER 'app'@'%' IDENTIFIED BY 'app123456'; GRANT ALL PRIVILEGES ON mydb.* TO 'app'@'%'; FLUSH PRIVILEGES;以上这套流程,我在 Windows、macOS、Linux 三种系统上都实测过,能覆盖 90% 的开发场景。Docker 跑 MySQL 真正上手后,你会觉得安装数据库这件事再也不是项目的阻碍,而是基础设施里最平平无奇的一环。对我个人而言,最大的体会有两个:一是数据卷的使用越早养成习惯越好,二是任何奇怪的问题先看docker logs永远比瞎猜高效。希望这篇文章能让你少走点弯路,把更多时间花在真正有价值的业务代码上。