Docker 代理缓存问题分析

Summary: Author: 张亚飞 | Read Time: 2 minute read | Published: 2023-02-02
Filed under Categories: MarkDownTags: Tag,

Docker 代理缓存

记录一次 docker 镜像架构不同导致本地编译通过,但 jenkins 上构建失败的经过

以下是详细操作步骤:

在本地电脑执行以下命令将 golang 镜像推送到 harbor 仓库

docker image pull golang:1.19.12-alpine3.18
docker image tag golang:1.19.12-alpine3.18 harbor.baijiayun.com/proxy/golang:1.19.12-alpine3.18
docker image push harbor.baijiayun.com/proxy/golang:1.19.12-alpine3.18

在某项目中使用此镜像作为基础镜像

Dockerfile

FROM --platform=$BUILDPLATFORM harbor.baijiayun.com/proxy/golang:1.19.12-alpine3.18 AS builder

ARG TARGETOS
ARG TARGETARCH
ARG VERSION=0.0.0
ARG APP_ENV=local

ENV HOME /app

WORKDIR /app/
COPY . /app/

# 移除敏感配置文件
WORKDIR /app/config/envs
RUN cp $APP_ENV.yaml run.yaml

本地 Mac 使用 docker buildx 正常编译通过

docker buildx build --build-arg VERSION=release-test-db34b82 --build-arg COMMIT_HASH=db34b82 --build-arg GITLAB_USER=cicd --build-arg GITLAB_TOKEN=*** --build-arg NODE_ENV=test --build-arg APP_ENV=test --platform=linux/amd64 --tag harbor.baijiayun.com/bdata/vloud-collections:release-test-db34b829 -f Dockerfile --push .

但是通过 jenkins 构建失败,提示 RUN cp test.yaml run.yaml: 报错

#12 [builder  5/13] RUN cp test.yaml run.yaml
#12 sha256:15dba135ea73fc3a2f9e30b220edd2cfffc9a8c5f62ae415ff6bb68143c199c6
#12 0.073 standard_init_linux.go:228: exec user process caused: exec format error
#12 ERROR: process "/bin/sh -c cp $APP_ENV.yaml run.yaml" did not complete successfully: exit code: 1
------
 > [builder  5/13] RUN cp test.yaml run.yaml:
------
Dockerfile:15
--------------------
  13 |     # 移除敏感配置文件
  14 |     WORKDIR /app/config/envs
  15 | >>> RUN cp $APP_ENV.yaml run.yaml
  16 |     #RUN rm -r `ls | grep -v '.gitignore\|run.yaml'`
  17 |     RUN ls | grep -v '.gitignore\|run.yaml' | xargs rm -rf
--------------------
error: failed to solve: rpc error: code = Unknown desc = process "/bin/sh -c cp $APP_ENV.yaml run.yaml" did not complete successfully: exit code: 1
Build step 'Execute shell' marked build as failure

在本地电脑试了多次均正常编译,无法复现错误,于是在一台 Linux 服务器执行构建编译完进入容器提示以下错误

$ docker run --rm -it harbor.baijiayun.com/bdata/vloud-collections:release-test /bin/sh --login
exec /bin/sh: exec format error

造成这种问题的原因是在本地使用的是 Mac 电脑同步基础镜像的是 arm64 架构,但是 jenkins 编译的是 amd64 架构,基础镜像架构不对导致编译失败。

其实在 jenkins 构建已提示 #12 0.073 standard_init_linux.go:228: exec user process caused: exec format error,当时没注意

问题找到了,那就好解决了,解决方案有两种:

  • 使用和 jenkins 相同的 Linux 服务器构建基础镜像,再推送到 Harbor 镜像仓库
  • 使用 Harbor 镜像仓库作为 docker 镜像代理缓存,自动缓存多平台架构

第一种方案需要手动拉镜像,打 tag 别名,最后再推送到 harbor 仓库,过程比较繁琐,明显使用第二种方案更加灵活,并且适配多架构环境, 于是在 harbor 配置了一个镜像仓库项目 docker-proxy,使用 https://hub.docker.com 作为源仓库,配置好后使用命令拉取即可。

镜像仓库格式:

harbor.baijiayun.com/docker-proxy/library/<image_name>:<tag>

例如需要拉取 docker 仓库的 golang:1.19.12-alpine3.18 镜像,直接使用如下命令

docker image pull harbor.baijiayun.com/docker-proxy/library/golang:1.19.12-alpine3.18

将上面的 Dockerfile 改成以下配置即可解决

FROM --platform=$BUILDPLATFORM harbor.baijiayun.com/docker-proxy/library/golang:1.19.12-alpine3.18 AS builder

参考

How to use Harbor Registry to Eliminate Docker Hub Rate Limits


Comments

Cor-Ethan, the beverage → www.iirii.com