龙芯3B6000部署GitLab Runner Docker执行器:解决架构错配与镜像适配
如果你在龙芯 3B6000 平台上部署 GitLab Runner,并且选择了 Docker 执行器,那么你很可能已经踩过或即将踩入一个“深坑”:Runner 容器无法启动,或者启动后无法执行 CI/CD 流水线,错误日志里充斥着
exec format error
、
no matching manifest
或者
exec user process caused: exec format error
这类令人困惑的提示。
这背后的根本原因,是
CPU 架构的错配
。GitLab Runner 默认拉取的 Docker 镜像(如
alpine:latest
,
golang:latest
)通常是基于 x86_64 架构构建的。而龙芯 3B6000 使用的是
LoongArch64 (LA64)
架构。一个 x86 的二进制程序,自然无法在龙芯的 CPU 上运行,这就是所有问题的根源。
网上零散的解决方案,比如手动构建镜像、修改 Runner 配置,往往步骤繁琐且容易遗漏关键环节,导致问题反复出现。本文将提供一个 完整、系统、一键式 的解决方案,覆盖从环境诊断、镜像适配、Runner 配置到最佳实践的每一个环节。读完本文,你将能:
- 彻底理解 龙芯平台上 Docker 执行器问题的本质。
- 掌握一套 从零开始,在龙芯 3B6000 上搭建稳定 GitLab Runner Docker 执行器环境的方法。
- 获得一个 经过验证的、可复用的自动化配置脚本,真正做到“一键解决”。
- 规避未来 因架构问题导致的 CI/CD 流程中断风险。
无论你是龙芯平台的早期探索者,还是正在将项目迁移至国产化环境,这篇文章都将为你扫清最大的工程化障碍。
1. 问题根源:为什么 Docker 执行器在龙芯上“水土不服”?
很多人第一次遇到这个问题时,会以为是 Docker 没装好、权限不对或者网络问题。但核心矛盾在于 “镜像指令集” 与 “宿主机指令集” 的不匹配。
我们可以用一个简单的类比来理解:Docker 镜像就像一个打包好的“软件罐头”,里面包含了运行所需的所有文件和指令。GitLab Runner 的 Docker 执行器,就是打开这个罐头并在一个隔离环境(容器)里运行它。但如果这个罐头里的“说明书”(二进制指令)是用“英语”(x86指令集)写的,而你的“工人”(龙芯CPU)只懂“中文”(LoongArch指令集),那工人自然无法执行任何操作,最终报错。
具体到技术层面:
-
默认行为
:当你在
gitlab-runner的config.toml中指定image = “alpine:latest”时,Runner 会命令 Docker 引擎去拉取这个镜像。Docker 默认会根据你宿主机的架构(在龙芯上是linux/loong64)去请求对应架构的镜像。 -
镜像仓库的响应
:Docker Hub 等公共仓库对于
alpine:latest这类流行镜像,通常都提供了多架构支持。当龙宿主机请求时,仓库应该返回linux/loong64的镜像清单。 -
问题发生点
:
-
仓库未提供
:很多镜像,特别是小众或特定版本的镜像,并没有构建
linux/loong64的版本。此时 Docker 会拉取默认的linux/amd64版本,导致架构错误。 -
标签歧义
:像
latest这样的标签是动态的。可能今天仓库提供了龙芯版本,明天维护者更新了amd64版本但忘了同步龙芯版本,导致拉取的镜像再次出错。 -
自定义镜像
:如果你在 CI 脚本中使用了
docker build构建自己的镜像,而基础镜像(FROM)指定的是没有龙芯版本的镜像,那么构建出的镜像也无法运行。
-
仓库未提供
:很多镜像,特别是小众或特定版本的镜像,并没有构建
所以,解决方案的核心思路非常明确:
确保在龙芯 3B6000 上拉取或构建的所有 Docker 镜像,都是基于
linux/loong64
架构的。
2. 环境准备:确认你的龙芯平台基础状态
在开始“一键解决”之前,我们需要确保基础环境是正常的。请在你的龙芯 3B6000 服务器上执行以下检查。
2.1 确认系统架构与内核
打开终端,运行以下命令:
uname -m
预期输出应该是
loongarch64
,这确认了你的 CPU 架构。
cat /etc/os-release
查看操作系统信息。常见的龙芯发行版有 Loongnix(麒麟)、UOS、openEuler 龙芯版等。记录下系统版本,例如
PRETTY_NAME="Loongnix Server 20"
。
2.2 安装并验证 Docker
龙芯平台的 Docker 安装方式可能与 x86 不同,通常需要通过发行版的包管理器或从龙芯社区获取适配版本。
对于 Loongnix/Debian 系:
sudo apt update
sudo apt install docker.io docker-compose
安装后验证:
sudo systemctl start docker
sudo systemctl enable docker
sudo docker version
确保 Docker 客户端和服务端都能正常显示版本,并且没有明显的错误信息。
关键验证:查看 Docker 默认平台
sudo docker info --format '{{.OSType}}/{{.Architecture}}'
输出应为
linux/loong64
。这证明 Docker 服务端正确识别了宿主机的架构。
2.3 安装 GitLab Runner
同样,通过包管理器安装:
# 添加 GitLab Runner 官方仓库(请根据你的系统查找对应龙芯架构的仓库或安装包,有时需要直接下载rpm/deb包)
# 例如,对于 Loongnix,可能需要从源码编译或使用社区提供的包。
# 这里假设你已经有了适合 loongarch64 的安装包。
# 示例:安装下载的 .deb 包
sudo dpkg -i gitlab-runner_<version>_loongarch64.deb
# 或者使用官方的安装脚本(注意:需要确认脚本是否支持 loongarch64)
# curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash
# sudo apt install gitlab-runner
安装后,注册 Runner 到你的 GitLab 实例(这一步与架构无关):
sudo gitlab-runner register
按照提示输入 GitLab 实例 URL 和注册令牌(从 GitLab 项目或群组设置中获取)。在注册时,执行器先选择
docker
。
3. 核心方案:构建龙芯可用的 Docker 镜像体系
这是解决问题的关键。我们不能依赖不可靠的
latest
标签,而必须建立一个确定的、支持
linux/loong64
的镜像来源。
3.1 策略一:使用已支持 LoongArch64 的官方镜像
越来越多的开源项目开始支持龙芯架构。我们可以优先选择这些镜像。
-
基础系统镜像
:
-
debian:12-slim(官方已支持多架构,包含loong64) -
ubuntu:22.04(官方已支持多架构,包含loong64) -
alpine:3.19(注意:Alpine 官方对loong64的支持可能还在完善中,建议优先使用 Debian/Ubuntu)
-
-
语言运行时镜像
:
-
openjdk:17-jdk-slim(基于 Debian,支持loong64) -
node:20-bookworm-slim(基于 Debian,支持loong64) -
python:3.12-slim(基于 Debian,支持loong64) -
golang:1.21-bookworm(基于 Debian,支持loong64)
-
如何验证镜像是否支持 loong64?
可以使用
docker manifest inspect
命令(需要开启 Docker CLI 的实验性功能),或者直接尝试拉取并运行一个简单命令:
sudo docker run --rm -it debian:12-slim uname -m
如果输出
loongarch64
,则镜像可用。
3.2 策略二:手动构建与推送自定义镜像(终极方案)
对于没有官方支持的镜像,或者你需要高度定制化的环境,必须自己构建。
步骤1:编写支持多架构的 Dockerfile
创建一个
Dockerfile
,尽量使用已支持
loong64
的基础镜像。
# 使用已支持 loong64 的 Debian 作为基础镜像
FROM debian:12-slim AS builder
# 安装你的应用依赖(以构建一个简单的Go应用为例)
RUN apt-get update && apt-get install -y wget && \
wget -O go.tar.gz https://golang.org/dl/go1.21.6.linux-loong64.tar.gz && \
tar -C /usr/local -xzf go.tar.gz && \
rm go.tar.gz
ENV PATH="/usr/local/go/bin:${PATH}"
WORKDIR /app
COPY . .
RUN go build -o myapp .
# 第二阶段,创建更小的运行时镜像
FROM debian:12-slim
COPY --from=builder /app/myapp /usr/local/bin/myapp
CMD ["myapp"]
步骤2:在龙芯宿主机上构建镜像
由于宿主机就是
loong64
,直接构建即可得到对应架构的镜像。
sudo docker build -t my-registry.example.com/my-loongapp:latest .
步骤3:推送至私有镜像仓库 为了在 CI/CD 中使用,需要将构建好的镜像推送到一个 Runner 能够访问的镜像仓库(如 Harbor, Docker Registry)。
sudo docker push my-registry.example.com/my-loongapp:latest
3.3 策略三:配置 Runner 使用明确的镜像标签
在 GitLab Runner 的配置中,避免使用
latest
。使用带有明确版本号且已知支持
loong64
的镜像标签。
编辑 Runner 配置文件(通常位于
/etc/gitlab-runner/config.toml
):
[[runners]]
name = "loong64-docker-runner"
url = "https://gitlab.example.com"
token = "YOUR_RUNNER_TOKEN"
executor = "docker"
[runners.docker]
# 关键配置:使用已知支持 loong64 的镜像
image = "debian:12-slim"
# 非常重要:禁用 TLS 验证(仅当使用私有仓库且为自签名证书时需要)
# pull_policy = "if-not-present"
# 如果需要,可以配置私有仓库认证
# [[runners.docker.services]]
# name = "postgres:15-alpine"
# # 注意:服务镜像也需要支持 loong64!
# alias = "db"
修改配置后,重启 Runner:
sudo gitlab-runner restart
4. 一键解决方案:自动化配置脚本
将上述步骤整合成一个 Shell 脚本,实现“一键”配置。将此脚本保存为
setup-loong64-gitlab-runner.sh
。
#!/bin/bash
# setup-loong64-gitlab-runner.sh
# 龙芯 3B6000 GitLab Runner Docker 执行器一键配置脚本
set -e # 遇到错误即退出
echo "=== 龙芯 GitLab Runner Docker 执行器配置脚本 ==="
echo "1. 检查系统架构..."
ARCH=$(uname -m)
if [ "$ARCH" != "loongarch64" ]; then
echo "错误:此脚本仅适用于 loongarch64 架构,当前架构为 $ARCH。"
exit 1
fi
echo "✓ 系统架构: $ARCH"
echo -e "\n2. 检查并安装 Docker..."
if ! command -v docker &> /dev/null; then
echo "Docker 未安装,尝试安装..."
# 根据不同的发行版调整安装命令
if [ -f /etc/debian_version ]; then
sudo apt update
sudo apt install -y docker.io docker-compose
elif [ -f /etc/redhat-release ]; then
sudo yum install -y docker docker-compose
else
echo "无法自动识别系统发行版,请手动安装 Docker。"
exit 1
fi
sudo systemctl start docker
sudo systemctl enable docker
else
echo "✓ Docker 已安装。"
fi
echo -e "\n3. 验证 Docker 架构..."
DOCKER_INFO=$(sudo docker info --format '{{.OSType}}/{{.Architecture}}')
if [ "$DOCKER_INFO" != "linux/loong64" ]; then
echo "警告:Docker 架构报告为 $DOCKER_INFO,可能与宿主机不匹配。"
else
echo "✓ Docker 架构: $DOCKER_INFO"
fi
echo -e "\n4. 拉取并测试基础镜像..."
TEST_IMAGE="debian:12-slim"
echo "拉取镜像 $TEST_IMAGE ..."
sudo docker pull $TEST_IMAGE
echo "测试镜像架构..."
CONTAINER_ARCH=$(sudo docker run --rm $TEST_IMAGE uname -m)
if [ "$CONTAINER_ARCH" = "loongarch64" ]; then
echo "✓ 基础镜像 $TEST_IMAGE 支持 loongarch64。"
else
echo "⚠ 镜像返回架构为 $CONTAINER_ARCH,可能存在兼容性问题。"
fi
echo -e "\n5. 安装 GitLab Runner..."
if ! command -v gitlab-runner &> /dev/null; then
echo "GitLab Runner 未安装。"
echo "请从以下方式选择一种:"
echo " A) 手动下载 loongarch64 安装包并安装。"
echo " B) 使用系统包管理器安装(如果仓库有)。"
echo " C) 从源码编译。"
echo "安装后,请重新运行此脚本。"
exit 1
else
echo "✓ GitLab Runner 已安装。"
fi
echo -e "\n6. 生成推荐 Runner 配置片段..."
cat << EOF
===========================================
请将以下配置添加到你的 Runner 配置中
(/etc/gitlab-runner/config.toml 的 [[runners]] 部分)
===========================================
[runners.docker]
# 使用已验证支持 loong64 的镜像
image = "debian:12-slim"
# 镜像拉取策略:'always' 每次都拉取,'if-not-present' 本地有则用本地
pull_policy = "if-not-present"
# 禁用特权模式(除非必要)
privileged = false
# 设置额外的卷挂载(例如缓存目录)
volumes = ["/cache", "/home/gitlab-runner/.m2:/root/.m2:rw"]
# 如果你的服务也需要特定镜像,例如数据库
# [[runners.docker.services]]
# name = "postgres:15"
# alias = "postgres"
EOF
echo -e "\n7. 创建缓存目录(可选)..."
sudo mkdir -p /cache
sudo chown -R gitlab-runner:gitlab-runner /cache 2>/dev/null || echo "无法更改 /cache 所有者,请手动检查。"
echo -e "\n=== 脚本执行完成 ==="
echo "下一步:"
echo "1. 使用 'sudo gitlab-runner register' 注册 Runner(如果尚未注册)。"
echo "2. 根据上面的提示修改 config.toml 配置文件。"
echo "3. 重启 Runner: sudo gitlab-runner restart"
echo "4. 在你的 .gitlab-ci.yml 中,确保使用的镜像标签是支持 loong64 的。"
给脚本添加执行权限并运行:
chmod +x setup-loong64-gitlab-runner.sh
sudo ./setup-loong64-gitlab-runner.sh
这个脚本会自动检查环境、安装必要组件、测试基础镜像,并输出关键的配置建议。
5. 编写适配龙芯的 .gitlab-ci.yml
Runner 配置好了,CI 脚本本身也需要适配。核心原则是:
所有
image:
和
services:
下指定的镜像,都必须明确使用支持
loong64
的版本。
下面是一个完整的示例,构建一个简单的 Go 项目:
# .gitlab-ci.yml
stages:
- test
- build
variables:
# 使用支持 loong64 的 Go 镜像
GO_IMAGE: "golang:1.21-bookworm"
# 构建输出的二进制名称
BINARY_NAME: "myapp-loong64"
# 所有作业共享的基础配置
.default-before_script:
before_script:
- uname -m # 打印架构,确认环境
- go version
unit-test:
stage: test
image: $GO_IMAGE
script:
- go test ./... -v
build-binary:
stage: build
image: $GO_IMAGE
script:
- go build -o $BINARY_NAME .
- ./$BINARY_NAME --version # 简单验证二进制文件能运行
artifacts:
paths:
- $BINARY_NAME
expire_in: 1 week
only:
- tags # 仅当打标签时构建
# 一个使用多阶段构建 Docker 镜像的作业示例
build-docker-image:
stage: build
# 使用 Docker-in-Docker (dind) 服务,注意 dind 镜像也需要支持 loong64!
image: docker:24.0
services:
- name: docker:24.0-dind
alias: docker
variables:
DOCKER_HOST: tcp://docker:2375
DOCKER_TLS_CERTDIR: ""
IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
script:
- docker --version
- docker build -t $IMAGE_TAG .
- docker push $IMAGE_TAG
# 注意:此作业要求 gitlab-runner 以 privileged 模式运行,且 docker:24.0 镜像有 loong64 版本。
# 如果找不到,你需要自己构建一个支持 loong64 的 docker 客户端镜像。
only:
- main
6. 常见问题与排查清单
即使按照上述步骤操作,仍可能遇到问题。下表列出了常见问题及解决方法:
| 问题现象 | 可能原因 | 排查命令/步骤 | 解决方案 |
|---|---|---|---|
exec /bin/sh: exec format error
|
拉取的 Docker 镜像架构错误(非
loong64
)。
|
1.
docker image inspect <image_name>
查看
Architecture
字段。
2. 在宿主机运行
docker run --rm <image_name> uname -m
。
|
1. 在
config.toml
和
.gitlab-ci.yml
中指定已知支持
loong64
的镜像标签。
2. 使用私有仓库,并确保推送的是在龙芯上构建的镜像。 |
no matching manifest for linux/loong64 in the manifest list entries
|
Docker Hub 或仓库中不存在该镜像的
loong64
版本。
|
docker manifest inspect <image_name>
(需开启 CLI 实验性功能)。
|
1. 更换为基础镜像(如
debian:12-slim
)。
2. 自行构建所需镜像并推送到私有仓库。 |
Runner 日志显示
Pulling docker image ...
后卡住或失败
| 网络问题,或私有仓库需要认证。 |
查看 Runner 日志
sudo gitlab-runner run
或
journalctl -u gitlab-runner
。
|
1. 配置 Docker 镜像加速器。
2. 在
config.toml
的
[runners.docker]
部分配置
pull_policy = "if-not-present"
并提前手动拉取镜像。
3. 配置私有仓库认证:
docker login
并在 Runner 配置中设置
[[runners.docker.volumes]]
挂载
~/.docker/config.json
。
|
作业中
docker build
失败
|
docker
客户端镜像或
dind
服务镜像不支持
loong64
。
|
检查作业中
image:
和
services:
指定的镜像。
|
寻找或构建支持
loong64
的
docker
客户端和
dind
镜像。或者考虑使用
kaniko
等无需 Docker daemon 的构建工具。
|
| 容器内无法访问宿主机服务或网络 | 容器网络模式配置问题。 |
检查
config.toml
中的
network_mode
。
|
可以尝试设置为
network_mode = "host"
(注意安全风险),或确保容器内使用正确的服务别名(在
services
中定义)。
|
权限错误(如无法写入
/cache
)
| 容器内用户与宿主机目录权限不匹配。 | 检查宿主机目录的权限和所有者。 |
1. 在
config.toml
的
volumes
中明确设置权限,如
:/cache:rw
。
2. 确保宿主机目录对 Runner 运行用户(通常是
gitlab-runner
)可写。
|
7. 最佳实践与长期维护建议
解决了基本问题后,为了团队协作和长期稳定,建议遵循以下实践:
-
建立私有镜像仓库并缓存基础镜像
:在内网搭建 Harbor 或 Docker Registry,将常用的、支持
loong64的基础镜像(如debian,golang,node)推送上去。在 Runner 配置中优先从私有仓库拉取,提升速度和稳定性。 -
固化镜像版本
:在 CI 配置中,永远不要使用
latest标签。使用完整的、带版本号的标签,例如debian:12.20240110-slim、golang:1.21.6-bookworm。这能保证构建环境的确定性。 - 创建项目专用的基础镜像 :对于大型项目,可以创建包含项目所有构建依赖的专属 Dockerfile,并在龙芯平台上构建、测试、推送至私有仓库。CI 脚本中直接使用这个专用镜像,可以极大减少作业准备时间。
-
将镜像构建纳入 CI 流程
:在仓库中维护用于龙芯环境的 Dockerfile。设置一个独立的 CI 流水线(例如在
main分支更新时),自动在龙芯 Runner 上构建并推送最新版本的基础镜像。这样,应用 CI 就能始终使用最新的、兼容的依赖。 -
Runner 标签管理
:给你的龙芯 Runner 打上特定的标签,如
loong64。在项目的.gitlab-ci.yml中,为需要在龙芯上运行的作业添加tags: - loong64。这样可以精确控制作业在哪个架构的 Runner 上执行,避免误调度。 -
定期检查与更新
:关注上游基础镜像(如 Debian, Go, Node.js)对
loong64架构的支持状态。定期更新你的基础镜像版本,以获取安全补丁和性能改进。
8. 总结
在龙芯 3B6000 平台上成功运行 GitLab Runner Docker 执行器,不是一个简单的配置问题,而是一个 从镜像供应链到 CI 流程的体系化适配过程 。问题的核心始终围绕 CPU 架构 。
本文提供的“一键解决”方案,其精髓在于脚本自动化背后的系统性思路:
- 诊断 :首先确认架构不匹配是万恶之源。
- 供给 :解决镜像来源问题,要么选用官方已支持的镜像,要么自己构建。
- 配置 :在 Runner 和 CI 脚本中,明确指定兼容的镜像标签。
-
验证
:通过简单的命令(如
uname -m)验证容器内环境。 - 优化 :建立私有仓库、固化版本、制作专用镜像,实现可持续的维护。
将文中的脚本和配置作为起点,结合你项目的具体技术栈进行调整,你就能在龙芯平台上建立起稳定、高效的 CI/CD 流水线。国产化平台的迁移,往往就卡在这些具体的工程细节上。希望这篇详尽的指南,能帮你顺利跨过这道坎。
更多推荐

所有评论(0)