写在最前
1. Buildx
1.1 部署安装
发布日期:2024 年 6 月 25 日
GitHub 页面:
https://github.com/docker/buildx/releases/tag/v0.26.1
# 创建 CLI 插件目录(如果不存在)
mkdir -p ~/.docker/cli-plugins
# 下载 buildx v0.26.1 for linux-amd64
curl -L https://github.com/docker/buildx/releases/download/v0.26.1/buildx-v0.26.1.linux-amd64 -o ~/.docker/cli-plugins/docker-buildx
# 添加执行权限
chmod +x ~/.docker/cli-plugins/docker-buildx
# 查看版本确认成功
docker buildx version
[root@localhost ~]# # 下载 buildx v0.26.1 for linux-amd64
[root@localhost ~]# curl -L https://github.com/docker/buildx/releases/download/v0.26.1/buildx-v0.26.1.linux-amd64 -o ~/.docker/cli-plugins/docker-buildx
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
100 64.5M 100 64.5M 0 0 11.2M 0 0:00:05 0:00:05 --:--:-- 14.4M
[root@localhost ~]# # 添加执行权限
[root@localhost ~]# chmod +x ~/.docker/cli-plugins/docker-buildx
[root@localhost ~]# # 查看版本确认成功
[root@localhost ~]# docker buildx version
github.com/docker/buildx v0.26.1 1a8287f22cf5a38339a4c1bf432b803c5f8b2aae
[root@localhost ~]#
1.2 代理配置
172.31.0.1:7890 是我在 Windows 上通过 Clash for Windows 配置的代理端口,用来让容器或其他服务访问外网资源(如 docker.io)。
# 删除缓存
docker buildx prune --all --force
rm -rf ~/.docker/buildx/
#创建buildx环境,并使用本机代理
docker buildx create --use --name mybuilder --driver-opt env.http_proxy=172.31.0.1:7890 --driver-opt env.https_proxy=172.31.0.1:7890
#修改所使用的buildx环境
docker buildx use mybuilder
#使用完毕后如果你不想要这个代理网络了,可以删除环境
docker buildx rm mybuilder
1.3 使用方式
# 默认构建出来使用docker images是看不到的,你要么使用--push直接推送上去仓库,要么使用--load才能使用docker images看到
# --progress=plain 输出详细格式化后的内容
docker buildx build --platform linux/amd64,linux/arm64 --push -t tanqidi/builder-base:v3.1.0-podman .
2. 试验流程
为了支持在 ARM 架构上部署 Kubesphere 3.4.1 的 DevOps 流水线,官方没有提供相应的 ARM 架构镜像。因此,我们将自己动手构建这些镜像,以确保能够在 ARM 环境中顺利运行。
2.1 分析镜像层级
在 v3.2.0 的 maven/podman/Dockerfile
中,我们注意到其基础镜像使用的是 kubespheredev/builder-base:v3.1.0-podman
。经过确认这个镜像目前仅支持 amd64 架构,因此问题的根源就在这里。我们必须先将 builder-base:v3.1.0-podman
适配为 arm64 这样才能顺利完成后续镜像的构建。
2.2 构建 builder-base:v3.1.0-podman
构建时和运行时 runtime 不一定完全同步
构建镜像时(
podman build
),你可以指定使用runc
或crun
,这会影响镜像构建过程的底层容器运行时。容器运行时(
podman run
)默认可能是crun
,除非你也修改了运行时配置。这就导致构建和运行时用的 runtime 不一定一样,可能会出现兼容差异。
Podman 与 Docker 的兼容性
Podman 力求兼容 Docker CLI 和镜像标准,但底层实现不完全一样。
crun
和runc
都是 OCI runtime,理论上兼容,但实际细节和特性支持有差异,可能导致某些镜像构建或运行异常。Podman 的
crun
通常更轻量快速,但相较runc
有时在某些边缘场景表现不同。
# 这里仅作为记录,实际上构建Dockerfile可能会出现一点问题例如:
sh-5.1# podman info --format '{{.Host.OCIRuntime.Name}}'
crun
# 可能的异常
。。。。。。。
STEP 3/7: ENV TZ Asia/Shanghai
--> 3c485a8a8503
STEP 4/7: RUN bash -c 'touch /app/test-devops.jar'
error running container: from /usr/bin/crun creating container for [/bin/sh -c bash -c 'touch /app/test-devops.jar']: cannot resolve `null` under rootfs: No such file or directory
: exit status 1
time="2025-08-05T12:28:45Z" level=error msg="did not get container create message from subprocess: EOF"
Error: building at STEP "RUN bash -c 'touch /app/test-devops.jar'": while running runtime: exit status 1
script returned exit code 1
创建独立目录存放不同架构的 runc
可执行文件,并分别命名为 runc-amd64
和 runc-arm64
。
https://github.com/opencontainers/runc/releases/download/v1.1.9/runc.arm64
https://github.com/opencontainers/runc/releases/download/v1.1.9/runc.amd64
FROM almalinux:9.4
# FROM centos:7
# utils
RUN yum install -y epel-release ca-certificates && \
yum install -y unzip \
glibc-locale-source \
glibc-langpack-zh \
glibc-langpack-en \
which \
make \
wget \
zip \
bzip2 \
gcc \
gcc-c++ \
curl-devel \
autoconf \
expat-devel \
gettext-devel \
openssl-devel \
perl-devel \
zlib-devel \
python-pip \
git \
java-1.8.0-openjdk && \
yum -y clean all --enablerepo='*'
# Set the locale(en_US.UTF-8)
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8
# USER jenkins
WORKDIR /home/jenkins
ENV SONAR_SCANNER_VERSION 3.3.0.1492
RUN curl -o sonar_scanner.zip https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-${SONAR_SCANNER_VERSION}-linux.zip && \
unzip sonar_scanner.zip && rm sonar_scanner.zip \
&& rm -rf sonar-scanner-$SONAR_SCANNER_VERSION-linux/jre && \
sed -i 's/use_embedded_jre=true/use_embedded_jre=false/g' /home/jenkins/sonar-scanner-$SONAR_SCANNER_VERSION-linux/bin/sonar-scanner && \
mv /home/jenkins/sonar-scanner-$SONAR_SCANNER_VERSION-linux /usr/bin
ENV PATH $PATH:/usr/bin/sonar-scanner-$SONAR_SCANNER_VERSION-linux/bin
COPY ./ ./
ENV EXCLUDE_DOCKER 1
RUN ./hack/install_utils.sh && rm -rf ./*
# Install podman
RUN curl -L -o /etc/yum.repos.d/devel:kubic:libcontainers:stable.repo https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/CentOS_7/devel:kubic:libcontainers:stable.repo && \
yum -y install podman fuse-overlayfs && \
echo "alias docker=podman" >> /root/.bashrc
COPY storage.conf /etc/containers/storage.conf
COPY containers.conf /etc/containers/containers.conf
# 用 buildx 的内置变量,不用自己传
ARG TARGETARCH
COPY runc-${TARGETARCH}/runc /usr/bin/runc
RUN chmod +x /usr/bin/runc
# 配置 podman 使用 runc 而非 crun
# 创建 containers.conf 文件(如果不存在)并设置 runtime = "runc"
RUN mkdir -p /etc/containers && \
if [ ! -f /etc/containers/containers.conf ]; then \
echo -e '[engine]\nruntime = "runc"' > /etc/containers/containers.conf; \
elif grep -q '^runtime *= *' /etc/containers/containers.conf; then \
sed -i 's/^runtime *= *.*/runtime = "runc"/' /etc/containers/containers.conf; \
else \
echo 'runtime = "runc"' >> /etc/containers/containers.conf; \
fi
VOLUME /var/lib/containers
CMD ["podman", "info"]
docker buildx build --platform linux/arm64 --load -t tanqidi/builder-base:v3.1.0-podman .
2.3 构建 builder-maven:v3.2.0-podman
FROM tanqidi/builder-base:v3.1.0-podman
# ----------- Java (固定版本,ARM64) ------------
RUN curl -fsSL https://github.com/adoptium/temurin8-binaries/releases/download/jdk8u392-b08/OpenJDK8U-jdk_aarch64_linux_hotspot_8u392b08.tar.gz \
| tar -xz -C /opt && \
mv /opt/jdk8u392-b08 /opt/java
ENV JAVA_HOME=/opt/java
ENV PATH="${JAVA_HOME}/bin:${PATH}"
# ----------- Maven(固定版本) ------------
RUN curl -fsSL https://archive.apache.org/dist/maven/maven-3/3.5.3/binaries/apache-maven-3.5.3-bin.tar.gz \
| tar -xz -C /opt && \
mv /opt/apache-maven-3.5.3 /opt/maven
ENV M2_HOME=/opt/maven
ENV PATH="${M2_HOME}/bin:${PATH}"
# ----------- Ant(固定版本,可选) ------------
RUN curl -fsSL https://archive.apache.org/dist/ant/binaries/apache-ant-1.10.7-bin.tar.gz \
| tar -xz -C /opt && \
mv /opt/apache-ant-1.10.7 /opt/ant
ENV ANT_HOME=/opt/ant
ENV PATH="${ANT_HOME}/bin:${PATH}"
#
RUN ln -sf /usr/bin/podman /usr/bin/docker
# 默认运行 Maven 版本查看
CMD ["mvn", "-version"]
网络不行?可以先下载再构建吧。
https://github.com/adoptium/temurin8-binaries/releases/download/jdk8u392-b08/OpenJDK8U-jdk_aarch64_linux_hotspot_8u392b08.tar.gz
https://archive.apache.org/dist/maven/maven-3/3.5.3/binaries/apache-maven-3.5.3-bin.tar.gz
https://archive.apache.org/dist/ant/binaries/apache-ant-1.10.7-bin.tar.gz
FROM tanqidi/builder-base:v3.1.0-podman
# ----------- Java (固定版本,ARM64) ------------
COPY OpenJDK8U-jdk_aarch64_linux_hotspot_8u392b08.tar.gz /tmp/
RUN tar -xzf /tmp/OpenJDK8U-jdk_aarch64_linux_hotspot_8u392b08.tar.gz -C /opt && \
mv /opt/jdk8u392-b08 /opt/java && \
rm -f /tmp/OpenJDK8U-jdk_aarch64_linux_hotspot_8u392b08.tar.gz
ENV JAVA_HOME=/opt/java
ENV PATH="${JAVA_HOME}/bin:${PATH}"
# ----------- Maven(本地文件) ------------
COPY apache-maven-3.5.3-bin.tar.gz /tmp/
RUN tar -xz -C /opt -f /tmp/apache-maven-3.5.3-bin.tar.gz && \
rm /tmp/apache-maven-3.5.3-bin.tar.gz
ENV M2_HOME=/opt/apache-maven-3.5.3
ENV PATH="${M2_HOME}/bin:${PATH}"
# ----------- Ant(本地文件) ------------
COPY apache-ant-1.10.7-bin.tar.gz /tmp/
RUN tar -xz -C /opt -f /tmp/apache-ant-1.10.7-bin.tar.gz && \
mv /opt/apache-ant-1.10.7 /opt/ant && \
rm /tmp/apache-ant-1.10.7-bin.tar.gz
ENV ANT_HOME=/opt/ant
ENV PATH="${ANT_HOME}/bin:${PATH}"
# 将 podman 映射为 docker
RUN ln -sf /usr/bin/podman /usr/bin/docker
# 默认运行 Maven 版本查看
CMD ["mvn", "-version"]
# --progress=plain 输出详细格式化后的内容
docker buildx build --platform linux/arm64 --load -t tanqidi/builder-maven:v3.2.0-podman .
2.4 构建 builder-maven-jdk21
docker buildx build --platform linux/arm64 --load -t tanqidi/builder-maven:jdk21-maven3.9.9 .
https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.8%2B9/OpenJDK21U-jdk_aarch64_linux_hotspot_21.0.8_9.tar.gz
https://archive.apache.org/dist/maven/maven-3/3.9.9/binaries/apache-maven-3.9.9-bin.tar.gz
https://archive.apache.org/dist/ant/binaries/apache-ant-1.10.7-bin.tar.gz
FROM tanqidi/builder-base:v3.1.0-podman
# ----------- Java (固定版本,ARM64) ------------
COPY OpenJDK21U-jdk_aarch64_linux_hotspot_21.0.8_9.tar.gz /tmp/
RUN tar -xzf /tmp/OpenJDK21U-jdk_aarch64_linux_hotspot_21.0.8_9.tar.gz -C /opt && \
mv /opt/jdk-21.0.8+9 /opt/java && \
rm -f /tmp/OpenJDK21U-jdk_aarch64_linux_hotspot_21.0.8_9.tar.gz
ENV JAVA_HOME=/opt/java
ENV PATH="${JAVA_HOME}/bin:${PATH}"
# ----------- Maven(本地文件) ------------
COPY apache-maven-3.9.9-bin.tar.gz /tmp/
RUN tar -xz -C /opt -f /tmp/apache-maven-3.9.9-bin.tar.gz && \
rm /tmp/apache-maven-3.9.9-bin.tar.gz
ENV M2_HOME=/opt/apache-maven-3.9.9
ENV PATH="${M2_HOME}/bin:${PATH}"
# ----------- Ant(本地文件) ------------
COPY apache-ant-1.10.7-bin.tar.gz /tmp/
RUN tar -xz -C /opt -f /tmp/apache-ant-1.10.7-bin.tar.gz && \
mv /opt/apache-ant-1.10.7 /opt/ant && \
rm /tmp/apache-ant-1.10.7-bin.tar.gz
ENV ANT_HOME=/opt/ant
ENV PATH="${ANT_HOME}/bin:${PATH}"
# 将 podman 映射为 docker
RUN ln -sf /usr/bin/podman /usr/bin/docker
# 默认运行 Maven 版本查看
CMD ["mvn", "-version"]
2.5 构建 builder-nodejs-nvm
docker buildx build --platform linux/arm64 --load -t tanqidi/builder-nodejs-nvm:latest .
# 使用 tanqidi 的基础镜像
FROM tanqidi/builder-base:v3.1.0-podman
# 创建 nvm 目录并下载 nvm
RUN mkdir -p /root/.nvm && \
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash
# 设置 nvm 环境变量并加载 nvm
RUN echo 'export NVM_DIR="/root/.nvm"' >> /root/.bashrc && \
echo '[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"' >> /root/.bashrc && \
echo '[ -s "$NVM_DIR/bash_completion" ] && . "$NVM_DIR/bash_completion"' >> /root/.bashrc
# 使用 nvm 安装多个 Node.js 版本,并设置默认版本
RUN bash -c 'export NVM_DIR="/root/.nvm" && \
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" && \
nvm install node && \
nvm install 4 && \
nvm install 6 && \
nvm install 8 && \
nvm install 10 && \
nvm install 12 && \
nvm install 14 && \
nvm install 16 && \
nvm install 18 && \
nvm install 19 && \
nvm install 20 && \
nvm install 21 && \
nvm install 22 && \
nvm alias default 14 && \
nvm ls'
# 确认所有安装的 Node.js 版本(nvm ls)
RUN bash -c 'export NVM_DIR="/root/.nvm" && \
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" && \
nvm ls'
# 将 podman 映射为 docker
RUN ln -sf /usr/bin/podman /usr/bin/docker
# 默认启动 shell
CMD ["bash", "-l"]
set +x
. ~/.nvm/nvm.sh
. ~/.bashrc
nvm list --no-colors
# 根据需求变更版本
nvm use 16
npm --version
node -v
npm config set registry https://registry.npmmirror.com/
npm install --ignore-scripts --prefer-offline --no-audit --verbose
npm run build
2.x openjdk8 with skywalking
2.x openjdk21 with skywalking
2.x nginx1.24.0
3. 镜像成品
tanqidi/builder-base:v3.1.0-podman
tanqidi/builder-maven:v3.2.0-podman
tanqidi/builder-maven:jdk21-maven3.9.9
tanqidi/builder-nodejs-nvm:latest
评论