苹果M1芯片Mac下Docker环境Rails执行db:migrate无输出不建库问题
根因分析
- MySQL镜像架构兼容性问题:你使用的
mysql/mysql-server:8.0.20官方镜像未提供原生arm64架构版本,在M1设备上运行时会通过QEMU动态转译amd64指令,执行数据库写入、schema变更类操作时容易出现无响应卡死,这是M1芯片Docker运行老版本非原生架构镜像的常见问题。 - 错误输出被屏蔽:入口脚本中将
db:migrate的错误输出重定向到了/dev/null,实际执行过程中产生的连接报错、权限报错、架构不兼容报错都会被吞掉,导致无任何提示直接卡住。 - mysql2 gem架构适配问题:如果Rails依赖的mysql2 gem是基于amd64架构的MySQL客户端库编译的,在arm64容器内运行时会出现系统调用适配异常,执行数据库操作时无响应。
排查步骤
- 临时修改入口脚本,删除错误重定向参数,将命令改为
bundle exec rake db:migrate || bundle exec rake db:setup,重新启动服务查看控制台输出的具体错误信息。 - 进入运行中的web容器,手动执行
rails db:create,检查是否可以正常创建数据库,确认是创建阶段卡住还是迁移执行阶段卡住。 - 执行
docker inspect mysql/mysql-server:8.0.20 | grep Architecture,查看MySQL镜像的架构,如果返回值为amd64则确认是非原生镜像转译运行导致的问题。 - 手动验证数据库连通性:在web容器内执行
mysql -h mysql -u 你的数据库用户名 -p 你的数据库密码,确认可以正常登录MySQL服务,排除网络连通问题。
解决方案
- 更换原生支持arm64的MySQL镜像:将docker-compose中的MySQL镜像替换为
mysql:8.0.28及以上版本,或mariadb:10.6及以上版本,以上镜像均提供官方arm64构建,无需转译可直接在M1设备上运行,兼容原有配置。 - 重新编译mysql2 gem:修改Dockerfile,在安装依赖阶段先安装arm64架构的MySQL客户端库,再重新编译mysql2 gem,示例命令如下:
apt update && apt install -y default-mysql-client default-libmysqlclient-dev gem uninstall mysql2 && gem install mysql2 - 调整数据库连接配置:在Rails的
database.yml中增加超时配置,避免无限制卡住:default: &default adapter: mysql2 connect_timeout: 5 read_timeout: 5 write_timeout: 5 # 其余原有配置保持不变 - 若必须使用
mysql/mysql-server:8.0.20版本,可在docker-compose的MySQL服务配置中增加platform: linux/amd64参数,强制指定架构运行,同时给Docker Desktop分配至少4核8G内存,降低转译卡顿概率,但该方案会带来30%以上的性能损失,仅作为临时 workaround 使用。
内容的提问来源于stack exchange,提问作者kazon
相关产品推荐
相关产品推荐

