构建多架构 Docker 镜像,但 Dockerfile 根据架构需要不同的包

Lew*_*uce 1 docker

我正在尝试使用 docker buildx,并注意到除了一件事之外,一切似乎都很简单。我的 Dockerfile 需要根据架构提取某些包。

例如,这是 Dockerfile 的一部分:

FROM XYZ

# Set environment variable for non-interactive install
ARG DEBIAN_FRONTEND=noninteractive

# Run basic commands to update the image and install basic stuff.
RUN apt update && \
    apt dist-upgrade -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" && \
    apt autoremove -y && \
    apt clean -y && \
    ...
    # Install amazon-ssm-agent
    mkdir /tmp/ssm && \
    curl https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/debian_amd64/amazon-ssm-agent.deb -o /tmp/ssm/amazon-ssm-agent.deb && \ 
Run Code Online (Sandbox Code Playgroud)

从上面可以看出,该命令设置为使用硬编码链接拉取 Amazon SSM 代理。

解决这个问题的最佳方法是什么?我应该修改这个 Dockerfile 来创建一堆 if 条件吗?

Dav*_*aze 6

当您使用 BuildKit 后端(现在是默认设置)时,Docker 会自动为您定义一组 ARG 。您需要声明ARG,然后(在RUN命令内)您可以使用环境变量$TARGETOS来引用目标操作系统(文档建议linuxwindows)。

FROM ...
# Must be explicitly declared, and after FROM
ARG TARGETOS
# Then it can be used like a normal environment variable
RUN curl https://s3.amazonaws.com/ec2-downloads-$TARGETOS/...
Run Code Online (Sandbox Code Playgroud)

如果您需要构建 x86 或 ARM 映像,则有类似的方法$TARGETPLATFORM,但其语法不一定与此 URL 中的内容匹配。如果$TARGETPLATFORMamd64or arm,您可能需要重建Debian 架构字符串。您可以在单个RUN命令中设置 shell 变量,该变量将持续到该命令结束,但不再持续。

ARG TARGETPLATFORM
RUN DEBARCH="$TARGETPLATFORM"; \
    if [ "$DEBARCH" = "arm" ]; then DEBARCH=arm64; fi; \
    curl .../debian-$DEBARCH/...
Run Code Online (Sandbox Code Playgroud)