【问题标题】:Define a path depending on the target platform within the Dockerfile in order to copy binaries根据 Dockerfile 中的目标平台定义路径以复制二进制文件
【发布时间】:2021-09-06 07:26:02
【问题描述】:

我有 GitHub Actions,它使用 rust-crossarm64 和其他硬件平台执行交叉编译。

我已经在主机上执行了交叉编译,并希望只使用要复制到Dockerfile 中的二进制文件和静态库并创建一个轻量级的 Alpine 容器。

警告

rust-cross中发布的二进制文件在特定目录下,例如:

arm64 -> target/aarch64-unknown-linux-gnu/release/
amd64 -> target/x86_64-unknown-linux-musl/release/
armv7 -> target/armv7-unknown-linux-gnueabihf/release/

试验

我正在尝试在我的Dockerfile 中使用case,它依赖于docker buildx 套件提供并基于来自BretFisher/multi-platform-docker 的一些有据可查的存储库提供TARGETPLATFORM

FROM alpine as base

FROM --platform=${BUILDPLATFORM} alpine as tiny-project

# Use BuildKit to help translate architecture names
ARG TARGETPLATFORM

RUN case ${TARGETPLATFORM} in \
         "linux/amd64")  TARGET_DIR=x86_64-unknown-linux-musl  ;; \
         "linux/arm64")  TARGET_DIR=aarch64-unknown-linux-gnu  ;; \
         *) exit 1 \ # ignore other architectures for now!
    esac \

WORKDIR /app

RUN cp target/<HOW TO PASS VALUE TARGET_DIR>/release/myBinary .
RUN cp target/<HOW TO PASS VALUE TARGET_DIR>/release/*.so .

FROM base as release
COPY --from=tiny-project /app/* ./

RUN echo '#!/bin/ash' > /entrypoint.sh
RUN echo 'echo " * Starting: /myBinary $*"' >> /entrypoint.sh
RUN echo 'exec /myBinary $*' >> /entrypoint.sh
RUN chmod +x /entrypoint.sh

EXPOSE 7447/udp
EXPOSE 7447/tcp
EXPOSE 8000/tcp

ENV RUST_LOG info

ENTRYPOINT ["/entrypoint.sh"]

我尝试了很多变化,但似乎TARGET_DIR 在主机上没有被识别

RUN cp ./target/$(echo $TARGET_DIR)/release/myBinary /
RUN cp ./target/$(echo $TARGET_DIR)/release/*.so /

# as well as storing the value in a file and calling it
# echo aarch64-unknown-linux-gnu > /tmp/rust_target.txt

RUN cp ./target/$(cat /tmp/rust_target.txt)/release/zenohd /
RUN cp ./target/$(cat /tmp/rust_target.txt)/release/*.so /

但似乎文件和变量都不适用于主机,并且在我的 GitHub 操作工作流日志中不断收到错误

要求

我希望保留一个Dockerfile,并基于来自docker buildx build 命令的platform,我想将二进制文件从适当的源目录复制到Dockerfile 中的目标目录。

如何做到这一点?

【问题讨论】:

    标签: docker rust dockerfile rust-cargo


    【解决方案1】:

    每个RUN 命令都在自己的shell(和自己的容器)中运行,因此您不能在一个持续超过该Dockerfile 行的RUN 命令中设置变量。

    但是,每个RUN 行也隐式地包裹在sh -c 中,因此您可以使用普通的shell 构造在单个RUN 指令中运行多个命令。由于您没有留下任何 Dockerfile 行,因此您设置的 shell 变量仍然有效:

    WORKDIR /app
    # All in a single RUN line:
    RUN case "${TARGETPLATFORM}" in \
             "linux/amd64")  TARGET_DIR=x86_64-unknown-linux-musl  ;; \
             "linux/arm64")  TARGET_DIR=aarch64-unknown-linux-gnu  ;; \
             *) exit 1 ;; \
        esac; \
        cp target/$TARGET_DIR/release/myBinary .; \
        cp target/$TARGET_DIR/release/*.so .
    

    将此逻辑放入您 COPYRUN 的 shell 脚本中,或者在主机上创建一个暂存目录,其中包含您想要包含在您想要和使用的布局中的文件也是合理的该目录作为docker build 上下文目录。

    rm -rf docker-build
    mkdir docker-build
    TARGET_DIR=...
    cp "target/$TARGET_DIR/release/myBinary" docker-build/myBinary
    cp Dockerfile docker-build
    docker build ./docker-build
    

    【讨论】:

    • 实际上我怀疑对target/ 目录的调用也会在这里失败,因为它无法从主机上找到目录。这是failed log,在原始日志中有一个错误ls: target/aarch64-unknown-linux-gnu/release/zenohd: No such file or directory,您提到的唯一可行的解​​决方案是将二进制文件移动到专用的主机目录中,然后将它们复制到容器中
    • 您可以在第一阶段 COPY target target 将构建树放入镜像中。
    • 你在这方面是对的。我尝试将target 复制到构建阶段并且它可以工作。我能够使用以下Dockerfile 传递我的构建但是我的高山容器拒绝找到二进制文件
    猜你喜欢
    • 2018-05-26
    • 1970-01-01
    • 1970-01-01
    • 2015-04-17
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    • 2013-08-19
    • 2013-11-06
    相关资源
    最近更新 更多