公司配的电脑,Macbook Air M1 版的,以为搭建过了嘛,感觉上没什么压力,然后就又掉坑里了。

安装 ubuntu/jammy64 虚拟机

在按照之前搭建的教程,安装了基础的 vagrantvirtualbox 后,通过 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 支持 virtualboxarm64 架构,下载安装启动,OK。

bento/ubuntu-22.04

╭─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 v1Docker 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 logsyslog 不能同时写日志,不太清楚什么远离,但 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/mysqldr-x------,就是除了 owner 其他人都没有权限,chmod 755 /var/lib/mysql/ 将其更改为 drwxr-xr-x。去除掉之前加在 compose 配置里的 user: "1000:1000",最后启动成功!

总结

  • ubuntu 镜像要换成 arm64 版本的
  • amd64 旧镜像可以手动修改成 arm64 版本的
  • 启动需要参照文档,这个数据库需要先初始化,得大写加粗