Mac M1 下 vagrant + virturalbox + docker-ce 搭建开发环境
公司配的电脑,Macbook Air M1 版的,以为搭建过了嘛,感觉上没什么压力,然后就又掉坑里了。
安装 ubuntu/jammy64 虚拟机
在按照之前搭建的教程,安装了基础的 vagrant
和 virtualbox
后,通过 vagrant
下载 ubuntu/jammy64
镜像后,启动报错:
╭─jasonli at admindeMacBook-Air in ~ 25-07-18 - 15:19:19
╰─○ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Checking if box 'ubuntu/jammy64' version '20241002.0.0' is up to date...
==> default: Clearing any previously set forwarded ports...
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
default: Adapter 1: nat
==> default: Forwarding ports...
default: 22 (guest) => 2222 (host) (adapter 1)
==> default: Running 'pre-boot' VM customizations...
==> default: Booting VM...
There was an error while executing `VBoxManage`, a CLI used by Vagrant
for controlling VirtualBox. The command and stderr is shown below.
Command: ["startvm", "729f1177-5480-42d5-a449-1d0f23b52d61", "--type", "headless"]
Stderr: VBoxManage: error: The VM session was aborted
VBoxManage: error: Details: code NS_ERROR_FAILURE (0x80004005), component SessionMachine, interface ISession
一开始以为是配置文件 Vagrantfile
有问题,去掉所有的配置,之后重启依然报错。
百度各种解决方案都没有用。想到是不是 ubuntu 的镜像版本与 Mac M1 不兼容。
之后找了一个 bento/ubuntu-22.04
支持 virtualbox 和 arm64 架构,下载安装启动,OK。
╭─jasonli at admindeMacBook-Air in ~/bento 25-07-18 - 15:27:35
╰─○ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Box 'bento/ubuntu-22.04' could not be found. Attempting to find and install...
default: Box Provider: virtualbox
default: Box Version: 202502.21.0
==> default: Loading metadata for box 'bento/ubuntu-22.04'
default: URL: https://vagrantcloud.com/api/v2/vagrant/bento/ubuntu-22.04
==> default: Adding box 'bento/ubuntu-22.04' (v202502.21.0) for provider: virtualbox (arm64)
default: Downloading: https://vagrantcloud.com/bento/boxes/ubuntu-22.04/versions/202502.21.0/providers/virtualbox/arm64/vagrant.box
==> default: Successfully added box 'bento/ubuntu-22.04' (v202502.21.0) for 'virtualbox (arm64)'!
==> default: Importing base box 'bento/ubuntu-22.04'...
==> default: Matching MAC address for NAT networking...
==> default: Checking if box 'bento/ubuntu-22.04' version '202502.21.0' is up to date...
==> default: Setting the name of the VM: bento_default_1752823930502_21705
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
default: Adapter 1: nat
==> default: Forwarding ports...
default: 22 (guest) => 2222 (host) (adapter 1)
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
default: SSH address: 127.0.0.1:2222
default: SSH username: vagrant
default: SSH auth method: private key
default:
default: Vagrant insecure key detected. Vagrant will automatically replace
default: this with a newly generated keypair for better security.
default:
default: Inserting generated public key within guest...
default: Removing insecure key from the guest if it's present...
default: Key inserted! Disconnecting and reconnecting using new SSH key...
==> default: Machine booted and ready!
==> default: Checking for guest additions in VM...
==> default: Mounting shared folders...
default: /Users/jasonli/bento => /vagrant
docker 安装镜像服务
之前使用个人的 Mac,使用 Docker Desktop
本地安装 docker ,结果就报的这个错误,之后通过虚拟机嵌套了一层之后,可以正常安装。现在是 Mac M1 下已经在虚拟机环境去安装这些 docker 服务了,结果还是会有错误:
docker pull docker.xx.xx/xx/redis:v2.8.17-xx
v2.8.17-d2015080301: Pulling from xx/redis
Docker Image Format v1 and Docker Image manifest version 2, schema 1 support has been removed. Suggest the author of docker.xx.xx/xx/redis:v2.8.17-xx to upgrade the image to the OCI Format or Docker Image manifest v2, schema 2. More information at https://docs.docker.com/go/deprecated-image-specs/
docker pull docker.xx.xx/xx/mariadb:v10.1.10-d2015122701
v10.1.10-d2015122701: Pulling from xx/mariadb
Docker Image Format v1 and Docker Image manifest version 2, schema 1 support has been removed. Suggest the author of docker.xx.xx/xx/mariadb:v10.1.10-xx to upgrade the image to the OCI Format or Docker Image manifest v2, schema 2. More information at https://docs.docker.com/go/deprecated-image-specs/
不确定这些公司提供的镜像,与公共的镜像有什么区别,反正个人是没办法去更新这个镜像的版本了。
咨询 deepseek 最近支持 Docker Image Format v1
和 Docker Image manifest version 2
版本的 docker 版本,得到以下结果:
- Docker 26.x:默认禁用 v1 和 v2 schema 1 镜像格式,尝试拉取此类镜像时会收到弃用警告1。
- Docker 24.x 及更早版本:可能仍支持这些旧格式,但官方建议迁移至 OCI 格式 或 Manifest v2, Schema 21。
- Docker 19.03.8(较旧版本):仍可处理 v2 schema 1 镜像,但部分仓库(如 JFrog Artifactory)可能已限制其推送。
不确定 26.x
是否可用,如果只是警告则无所谓。删除当前的 5:28.3.2-1~ubuntu.22.04~jammy
,再次安装 5:26.1.4-1~ubuntu.22.04~jammy
,猜测这就是版本 26.x
。如果不行,就再删再装 5:24.0.9-1~ubuntu.22.04~jammy
。
测试 26.x
的还是不行,而 24.x
的就可以了。但客户端的版本是 28.x。多次删除发现,安装影响的是服务端的版本,客户端的版本一直是 28.x
。不管怎样,回退 docker 版本还是可以解决这个问题的。
docker version
Client: Docker Engine - Community
Version: 28.3.2
API version: 1.43 (downgraded from 1.51)
Go version: go1.24.5
Git commit: 578ccf6
Built: Wed Jul 9 16:13:42 2025
OS/Arch: linux/arm64
Context: default
Server: Docker Engine - Community
Engine:
Version: 24.0.9
API version: 1.43 (minimum version 1.12)
Go version: go1.20.13
Git commit: fca702d
Built: Thu Feb 1 00:48:38 2024
OS/Arch: linux/arm64
Experimental: false
containerd:
Version: 1.7.27
GitCommit: 05044ec0a9a75232cad458027ca83437aae3f4da
runc:
Version: 1.2.5
GitCommit: v1.2.5-0-g59923ef
docker-init:
Version: 0.19.0
GitCommit: de40ad0
docker compose 启动
docker compose up
启动报错:
! redis The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
! beanstalkd The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
! mariadb The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
! xx The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
显然,镜像 AMD64 与宿主机 ARM64 兼容性问题,仅仅依靠回版本到 24 之前,依然是不够的。
deepseek 给的解决方案:在 compose 配置文件中,指定镜像 image 的 platform:
version: "3"
services:
xx:
container_name: xx
image: docker.xx.xx/xx/xx:v1.1.1-xx
platform: linux/amd64
...
手动转换镜像
在每个镜像配置中都加了一个 platform: linux/arm64
表示以 arm64 兼容模式去运行,且安装了兼容软件,但还是报错平台(arm64)与镜像(amd64)不适配。
没办法,想着是否可以本地将这些 amd64 的包给下载到本地,然后转成 arm64,之后再通过 docker load -i xxx.tar
加载到 docker 中。
问了 deepseek,选择了手动转换镜像(适用于简单镜像)方案:
# 注意:此方法仅适用于纯软件镜像(如脚本语言应用),依赖二进制文件的镜像可能无法运行。
docker images
docker save beanstalkd:tag -o beanstalkd.tar
mkdir -p temp_bean && tar -xvf beanstalkd.tar -C temp_bean
# 编辑 manifest.json 和 config.json,将 "architecture": "amd64" 改为 "arm64"
tar -cvf ../fixed_beanstalkd.tar *
cd ../
docker load -i fixed_beanstalkd.tar
打包必须在解压的文件夹内执行,如果在外面执行 tar -cvf fixed_xxx.tar temp_xxx/*
,重新打包好的 tar 包在加载到 docker 中时会报错,比如这里的 redis 案例:open /var/lib/docker/tmp/docker-import-696364300/temp_redis/json: no such file or directory
修改的第一个镜像成功了,接着继续修改其他的镜像。
注意,在使用 docker 导出镜像 tar 包的时候,如果使用的是镜像 id,而非 repo:tag 的格式,会就出现查看 images 列表时出现 repo 和 tag 同时为空的情况。
此时需要修复缺失的 repo 和 tag,因为 docker-compose.yaml 文件中启动制定的是 reo:tag 形式。
可以手动打标签:docker tag 07cc362 redis:latest
。如果不确定镜像 id,可以翻看之前加载指令结束的时候,会有这样的 镜像 id 日志输出:
docker load -i xxx.tar
....
Loaded image ID: sha256:07cc362...
mariadb 报错退出
mariadb | 250728 05:42:15 mysqld_safe Can't log to error log and syslog at the same time. Remove all --log-error configuration options for --syslog to take effect.
mariadb | 250728 05:42:15 mysqld_safe Logging to '/var/log/mysql/error.log'.
mariadb | 250728 05:42:16 mysqld_safe Starting mysqld daemon with databases from /var/lib/mysql
mariadb | 250728 05:42:16 mysqld_safe mysqld from pid file /var/run/mysqld/mysqld.pid ended
mariadb exited with code 0
大概意思是 error log
和 syslog
不能同时写日志,不太清楚什么远离,但 deepseek 给出解决答案:
services:
mariadb:
image: mariadb:latest
command: --log-error=/var/log/mysql/error.log --skip-syslog # 禁用syslog
volumes:
- ./mysql/logs:/var/log/mysql # 挂载日志目录
- ./mysql/data:/var/lib/mysql # 挂载数据目录
environment:
MYSQL_ROOT_PASSWORD: yourpassword
主要是加了一个 command
配置,指定错误日志,禁用 syslog
。
启动报警告:overcommit_memory is set to 0
依然 depseek 问到推荐的修复方式。
# 编辑 sysctl 配置文件
sudo vim /etc/sysctl.conf
# 在文件末尾添加:
vm.overcommit_memory = 1
# 应用配置
sudo sysctl -p
mariadb 再报错
Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: exec: "--log-error=/var/log/mysql/error.log": stat --log-error=/var/log/mysql/error.log: no such file or directory: unknown
deepseek 又修正了之前的回答,因为 command
后面带着两个参数,所以需要换成列表的写法:
services:
mariadb:
image: mariadb:latest
command:
- --log-error=/var/log/mysql/error.log
- --skip-syslog
volumes:
- ./mysql/logs:/var/log/mysql
还是报错,还是那个错,说明 command
这样写还是不能被正确识别。
尝试按照 deepseek 中的第二个方法,也就是写成数组形式:
services:
mariadb:
image: mariadb:latest
command: ["mysqld", "--log-error=/var/log/mysql/error.log", "--skip-syslog"]
启动成功了!这时候我突然发现,上面列表缺一个 mysqld
参数啊,你这下面换成数组变出来了,上面变没了。
通过各种修复mariadb
的报错,并没有解决问题,服务依然在restarting
。
第三天
这已经搞了第三天了,别说,还真有些收获。
首先是 vagrant
共享文件夹总是过一段时间,就挂载失败需要重启的问题。在上面的功能操作中 vagrant 共享文件夹挂载不稳定
记录了几种解决方案。其中第一种使用 crontab
定时脚本去重新挂载,测试已经可以稳定,再没有出现代码文件夹访问不了的情况。第二种是安装新的驱动,区别与 nfs 类型。但安装没有成功。后面有机会再弄。
然后 docker 这边主要是镜像 amd64
与宿主机环境 arm64
不一致,也不兼容的问题。按照昨天的手动转化镜像,全部改完之后测试发现,mariadb
如何都启动不起来,把它明面上报的很多错误解决之后,它干脆的不报错了,直接就是启动即失败,然后因为重启机制,一直重启。
二次进入到解压缩后的 temp_mariadb
目录里,再次仔细的检查了目录下的配置文件,发现 LH/temp_mariadb/c2c5f80ad09ab2eec38e3b2edd8962fc9436379762bbd745b49ba9bcfa499b6a/json
文件中也有一个 amd64
。将其重新打包然后载入到现有的镜像中,再次启动依然报错。
检测镜像的版本:
docker inspect docker.xx.xx/xx/mariadb:v10.1.10-xx | grep Architectur
"Architecture": "arm64",
已经没有问题了,但如何都启动不起来。
mariadb:
container_name: mariadb
platform: linux/arm64
image: docker.xx.cn/xx/mariadb:v10.1.10-xx
command:
- mysqld
- --log-error=/var/log/mysql/error.log
- --skip-syslog # 正确参数
- --key_buffer_size=16M # 替换旧参数
volumes:
- /var/lib/mysql:/var/lib/mysql
- /var/log/mysql:/var/log/mysql
- ./mariadb/my.cnf:/etc/mysql/my.cnf
- ./mariadb/conf.d/binlog.cnf:/etc/mysql/conf.d/binlog.cnf
- ./mariadb/conf.d/mysqld_safe_syslog.cnf:/etc/mysql/conf.d/mysqld_safe_syslog.cnf
- /dev/log:/dev/log
ports:
- 3306:3306/tcp
environment:
MYSQL_ROOT_PASSWORD: 123456
MYSQL_INITDB_SKIP_TZINFO: "1" # 跳过时区初始化
restart: always
mariadb 需要先生成容器,初始化之后一系列操作之后才能使用。 之前遇到过 mariadb
看到怎么都启动不起来之后,问了需要先这样,然后才能启动。
这时候突然想起来了~ 我TMD...
按照之前的教程里操作之后,启动报了一个 mysqld: Can't change dir to '/var/lib/mysql/' (Errcode: 13 "Permission denied")
的错,此时 /var/lib/mysql
为 dr-x------
,就是除了 owner
其他人都没有权限,chmod 755 /var/lib/mysql/
将其更改为 drwxr-xr-x
。去除掉之前加在 compose
配置里的 user: "1000:1000"
,最后启动成功!
总结
- ubuntu 镜像要换成 arm64 版本的
- amd64 旧镜像可以手动修改成 arm64 版本的
- 启动需要参照文档,这个数据库需要先初始化,得大写加粗
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。