skip to Main Content
# 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

Commands I run on a 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

The entrypoint.sh crashes with:

cannot execute binary file: Exec format error

What I tried:

  • add --platform linux/arm64 or linux/arm64/v8
  • inspecting the image architecture (arm64)
  • copying the executable to host and do file on it (arm64)
  • executing the executable on host – works
  • trying different runtime images (rust:bookworm, ubuntu, etc.)
  • using same build and runtime image
  • running the docker image one of the with the executable in --entrypoint directly

Note: I don’t build the exec in the image for a specific reason that I don’t want to change yet.

Any help would be appreciated

3

Answers


  1. Chosen as BEST ANSWER

    The problem was that I was putting a arm executable in a non arm environment (container), I also managed to build inside the Docker container by using

    cargo sqlx prepare --workspace
    

    Putting the .sqlx in the build and setting 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"]
    

    Thanks! It's open source: https://github.com/stellar-amenities/assistants


  2. Here you build your Rust application on your host machine which runs on MacOS, and run the application on an Ubuntu container which is a Linux Type OS. The difference between both OS architectures is likely why you’re having this issue.

    I don’t build the exec in the image for a specific reason that I don’t
    want to change yet.

    I see no reason why building your app in a Docker container is an issue. On the contrary, this is what you should do, otherwise you will be stuck with your issue.

    Moreover your builder stage is actually useless in your case because no further stage depends on it.

    Login or Signup to reply.
  3. If you want to release image for ubuntu you need to build the binary which is consistent with its architecture as well. You can specify the target as linux and cross compile your code for ubuntu.

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

    Do note that cross compilation has its own troubles it will not always work depending on what dependencies you are using but that’s the best in your scenario since you want to build for ubuntu.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search