skip to Main Content

I want to create a Docker image for aarch64 (Github here).

The image itself works on amd64 but on aarch64 with a command:

$ docker run --rm -it sineverba/serverless cat /etc/os-release I get

exec /usr/local/bin/docker-entrypoint.sh: exec format error

This is the Dockerfile:

ARG NODE_VERSION=20.10.0
FROM --platform=$BUILDPLATFORM node:$NODE_VERSION-alpine3.19
# Set versions from Make, otherwise use default
## NPM
ARG NPM_VERSION=latest
ENV NPM_VERSION $NPM_VERSION
## SERVERLESS
ARG SERVERLESS_VERSION=latest
ENV SERVERLESS_VERSION $SERVERLESS_VERSION
# Update and upgrade
RUN apk update && 
    apk upgrade --available --no-cache && 
    rm -rf /var/cache/apk/*
# Install
RUN npm install -g npm@$NPM_VERSION && npm install -g serverless@$SERVERLESS_VERSION
# Set workdir
WORKDIR /app

and this is the command build launched from Semaphore CI:

docker buildx build 
  --platform linux/arm64/v8,linux/amd64,linux/arm/v6,linux/arm/v7 
  --build-arg NODE_VERSION=$NODE_VERSION 
  --build-arg NPM_VERSION=$NPM_VERSION 
  --build-arg SERVERLESS_VERSION=$SERVERLESS_VERSION 
  --tag $DOCKER_USERNAME/$DOCKER_IMAGE:$SEMAPHORE_GIT_TAG_NAME 
  --tag $DOCKER_USERNAME/$DOCKER_IMAGE:latest
  --push "."

I would migrate from QEMU method, cause for JS binaries is very slow, more than 23 hours (!) in some case.

2

Answers


  1. You have a single FROM in the Dockerfile:

    FROM --platform=$BUILDPLATFORM node:$NODE_VERSION-alpine3.19
    

    The --platform=$BUILDPLATFORM says to pull the image for your local build platform instead of the target platform of the image being created. That means all of the binaries in the image are for your local platform, and the output is for your local platform. Building multiple instances of that, without some kind of cross compiler being used, is duplicating the effort to create the same image multiple times, and then falsely sticking a different platform label on it.

    I would migrate from QEMU method, cause for JS binaries is very slow, more than 23 hours (!) in some case.

    In this case the slow version is the working version. Building a second amd64 image and putting an arm label on it isn’t going to have the desired result.

    The choices for multi-platform images are:

    1. Cross compiling, which depends on the compiler. The final stage should be for the target platform and only include COPY steps from the cross compiler output. I suspect npm doesn’t support this.
    2. Emulation, using a tool like QEMU’s binfmt_misc, which is included by default on Docker Desktop, and can be setup on Linux host.
    3. Native builders, where buildkit is given remote access to other build nodes of the requested platform. These could be SaaS provided nodes in the cloud like Docker’s recently announced build cloud.
    Login or Signup to reply.
  2. You may use

    QEMU's binfmt_misc Should be available as default on Windows (Docker Desktop), and You may set it up over Linux [https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/fs/binfmt_misc.c?h=v5.19.6] as well.

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