为Mac M1构建Rust可执行文件和Docker映像时出现问题:无法执行二进制文件:Exec格式错误

vql8enpb  于 2024-01-06  发布在  Docker
关注(0)|答案(3)|浏览(149)
# Use an official Rust runtime as a parent image
FROM rust:bookworm as builder

# Set the working directory in the image to /app
WORKDIR /app

# Copy the current directory contents into the container at /app
COPY . /app

FROM --platform=$BUILDPLATFORM ubuntu:22.04

RUN apt-get update && apt-get install -y libssl-dev openssl curl

# Set the environment variables
ENV DATABASE_URL postgres://postgres:secret@pg:5432/mydatabase
ENV REDIS_URL=redis://redis/
ENV S3_ENDPOINT=http://minio1:9000
ENV S3_ACCESS_KEY=minioadmin
ENV S3_SECRET_KEY=minioadmin
ENV S3_BUCKET_NAME=mybucket

# Set the working directory
WORKDIR /app

# Copy the wait script to the image
COPY ee/k8s/readiness-probe.sh /app/readiness-probe.sh
RUN chmod +x /app/readiness-probe.sh

COPY ./target/release/run_consumer /app/run_consumer
COPY ./target/release/assistants-api-communication /app/assistants-api-communication

# Copy the entrypoint script
COPY docker/entrypoint.sh /app/entrypoint.sh

# Make the entrypoint script executable
RUN chmod +x /app/entrypoint.sh

# Run the entrypoint script when the container launches
ENTRYPOINT ["/app/entrypoint.sh"]

字符串
entrypoint.sh

#!/bin/bash

# Run the consumer and server applications concurrently
run_consumer &
assistants-api-communication &

# Wait for all background processes to finish
wait


我在Mac M2上运行的命令:

cargo build --release --bin run_consumer
cargo build --release --bin assistants-api-communication

docker build -t foo:latest -f docker/Dockerfile .
    
docker run --env-file .env -p 8080:8080 foo:latest


entrypoint.sh崩溃:
无法执行二进制文件:Exec格式错误
我所尝试的:

  • 添加--platform linux/arm64linux/arm64/v8
  • 检查图像结构(arm64)
  • 将可执行文件复制到主机并在其上执行file(arm64)
  • 在主机上执行可执行文件
  • 尝试不同的运行时映像(rust:bookworm,ubuntu等)
  • 使用相同的构建和运行时映像
  • 直接在--entrypoint中使用可执行文件运行Docker镜像之一

注意:我没有在映像中构建exec,因为我还不想改变它。
任何帮助将不胜感激

68de4m5k

68de4m5k1#

如果你想发布ubuntu镜像,你需要构建与其架构一致的二进制文件,你可以指定目标为Linux,然后交叉编译你的代码。

rustup target add x86_64-unknown-linux-gnu
cargo build --release --bin run_consumer --target x86_64-unknown-linux-gnu

字符串
请注意交叉编译也有它自己的麻烦,它并不总是工作,这取决于你使用的依赖项,但这是你的情况下最好的,因为你想为ubuntu构建。

6ioyuze2

6ioyuze22#

问题是我将arm可执行文件放在非arm环境(容器)中,我还设法在Docker容器中使用

cargo sqlx prepare --workspace

字符串
.sqlx放入构建并设置ENV SQLX_OFFLINE true

FROM rust:bookworm as builder

# Set the working directory in the image to /app
WORKDIR /app

# Copy the current directory contents into the container at /app
COPY assistants-api-communication /app/assistants-api-communication
COPY assistants-core /app/assistants-core
COPY assistants-extra /app/assistants-extra
COPY Cargo.toml /app/Cargo.toml
COPY .sqlx /app/.sqlx

ENV SQLX_OFFLINE true

RUN cargo build --release --bin run_consumer && \
    cargo build --release --bin assistants-api-communication

# Start a new stage to create a lean final image
FROM debian:bookworm-slim

RUN apt-get update && apt-get install -y libssl-dev openssl curl

# Set the environment variables
ENV DATABASE_URL postgres://postgres:secret@postgres:5432/mydatabase
ENV REDIS_URL=redis://redis/
ENV S3_ENDPOINT=http://minio1:9000
ENV S3_ACCESS_KEY=minioadmin
ENV S3_SECRET_KEY=minioadmin
ENV S3_BUCKET_NAME=mybucket

# Set the working directory
WORKDIR /app

# Copy the wait script to the image
COPY ./ee/k8s/readiness-probe.sh /app/readiness-probe.sh
RUN chmod +x /app/readiness-probe.sh

# Copy the binary from the builder stage
COPY --from=builder /app/target/release/run_consumer /usr/local/bin/run_consumer
COPY --from=builder /app/target/release/assistants-api-communication /usr/local/bin/assistants-api-communication

# Copy the entrypoint script
COPY ./docker/entrypoint.sh /app/entrypoint.sh

# Make the entrypoint script executable
RUN chmod +x /app/entrypoint.sh

# Run the entrypoint script when the container launches
ENTRYPOINT ["/app/entrypoint.sh"]


谢谢!它是开源的:https://github.com/stellar-amenities/assistants

b0zn9rqh

b0zn9rqh3#

在这里,您在运行于MacOS的主机上构建Rust应用程序,并在Linux Type OS的Ubuntu容器上运行应用程序。这两种操作系统架构之间的差异可能是您遇到此问题的原因。
我没有在映像中构建exec,因为我还不想改变一个特定的原因。
我看不出为什么在Docker容器中构建应用程序是一个问题。相反,这是你应该做的,否则你会被你的问题卡住。
此外,您的builder阶段在您的情况下实际上是无用的,因为没有进一步的阶段依赖于它。

相关问题