Search code examples
pythonpython-3.xdockerarmx86-64

Multi-arch docker build python arm64 Command '('lsb_release', '-a')' returned non-zero exit status 1


For sake of this question, I have a hello world python script called script.py.

def hello_world():
    print("hello world")


if __name__ == "__main__":
    hello_world()

And have a corresponding Dockerfile:

FROM python:3.8-alpine

WORKDIR /app

COPY requirements.txt requirements.txt

RUN python3 -m pip install --upgrade pip
RUN python3 -m pip install -r requirements.txt

COPY . .

CMD [ "python3", "script.py"]

Visual description of the question

Scenario #1 (amd64 as host machine):

When I build for amd64 architecture on this host I am successful doing so.

$ docker buildx build --platform linux/amd64 -t sntshk/cotu:latest .
WARN[0000] No output specified for docker-container driver. Build result will only remain in the build cache. To push result image into registry use --push or to load image into docker use --load 
[+] Building 2.6s (11/11) FINISHED                                                                                          
 => [internal] load build definition from Dockerfile                                                                   0.0s
 => => transferring dockerfile: 277B                                                                                   0.0s
 => [internal] load .dockerignore                                                                                      0.0s
 => => transferring context: 2B                                                                                        0.0s
 => [internal] load metadata for docker.io/library/python:3.8-alpine                                                   2.4s
 => [auth] library/python:pull token for registry-1.docker.io                                                          0.0s
 => [1/6] FROM docker.io/library/python:3.8-alpine@sha256:9b3ca9c8e9ec086ea825227ac6d819e46794c29590f04d775d517a48ef6  0.0s
 => => resolve docker.io/library/python:3.8-alpine@sha256:9b3ca9c8e9ec086ea825227ac6d819e46794c29590f04d775d517a48ef6  0.0s
 => [internal] load build context                                                                                      0.1s
 => => transferring context: 7.55kB                                                                                    0.1s
 => CACHED [2/6] WORKDIR /app                                                                                          0.0s
 => CACHED [3/6] COPY requirements.txt requirements.txt                                                                0.0s
 => CACHED [4/6] RUN python3 -m pip install --upgrade pip                                                              0.0s
 => CACHED [5/6] RUN python3 -m pip install -r requirements.txt                                                        0.0s
 => CACHED [6/6] COPY . .

But the build fails for arm64 architecture:

[..output trimmed...]
#8 12.03   File "/usr/local/lib/python3.8/site-packages/pip/_vendor/distro.py", line 125, in linux_distribution
#8 12.03     return _distro.linux_distribution(full_distribution_name)
#8 12.03   File "/usr/local/lib/python3.8/site-packages/pip/_vendor/distro.py", line 681, in linux_distribution
#8 12.03     self.version(),
#8 12.03   File "/usr/local/lib/python3.8/site-packages/pip/_vendor/distro.py", line 741, in version
#8 12.03     self.lsb_release_attr('release'),
#8 12.03   File "/usr/local/lib/python3.8/site-packages/pip/_vendor/distro.py", line 903, in lsb_release_attr
#8 12.03     return self._lsb_release_info.get(attribute, '')
#8 12.03   File "/usr/local/lib/python3.8/site-packages/pip/_vendor/distro.py", line 556, in __get__
#8 12.03     ret = obj.__dict__[self._fname] = self._f(obj)
#8 12.03   File "/usr/local/lib/python3.8/site-packages/pip/_vendor/distro.py", line 1014, in _lsb_release_info
#8 12.03     stdout = subprocess.check_output(cmd, stderr=devnull)
#8 12.03   File "/usr/local/lib/python3.8/subprocess.py", line 415, in check_output
#8 12.03     return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
#8 12.03   File "/usr/local/lib/python3.8/subprocess.py", line 516, in run
#8 12.03     raise CalledProcessError(retcode, process.args,
#8 12.03 subprocess.CalledProcessError: Command '('lsb_release', '-a')' returned non-zero exit status 1.
------
Dockerfile:9
--------------------
   7 |     COPY requirements.txt requirements.txt
   8 |     
   9 | >>> RUN python3 -m pip install --upgrade pip
  10 |     RUN python3 -m pip install -r requirements.txt
  11 |     
--------------------
error: failed to solve: process "/dev/.buildkit_qemu_emulator /bin/sh -c python3 -m pip install --upgrade pip" did not complete successfully: exit code: 1

Scenario #2 (arm64 as host machine):

I won't put much noise here, but on arm64, building arm64 image has no issue. But the same error is seen when I try to build amd64 image on arm64 host.


My final question is, how do I build amd64 on a arm64 host?

Update 1:

I am running the build on arm64 for both arm64 and amd64.

docker buildx build --push --platform linux/amd64,linux/arm64 -t me/myimage:latest .

The scenario now is that I can only run arm64 image on arm machine, but on amd64 machine, I see this error:

standard_init_linux.go:228: exec user process caused: exec format error

I saw this answer on SO which talks about problem with build. What is wrong at the moment?


Solution

  • I appreciate Corralien for his initial answer which was great to get out of the lsb_release error.

    Regarding the update in your question, please make sure the machine you are building on is capable of emulating the other type of architecture you are targeting.

    Best way to know that is to check it in buildx builder.

    $ docker buildx create --name multiarch
    $ docker buildx use multiarch
    $ docker buildx inspect --bootstrap
    Name:   multiarch
    Driver: docker-container
    
    Nodes:
    Name:      multiarch0
    Endpoint:  unix:///var/run/docker.sock
    Status:    running
    Platforms: linux/arm64, linux/arm/v7, linux/arm/v6
    

    Here you can see that Platforms listed are arm based only. And no matter whatever you pass --platform to buildx command, it won't yield a good result.

    The solution

    The package name might be different on different distros, but on Ubuntu it's called qemu-user-static.

    $ apt install -y qemu-user-static
    

    This will install QEMU emulators. If you check your builder now, you'd see more architectures.

    $ docker buildx inspect --bootstrap
    Name:   multiarch
    Driver: docker-container
    
    Nodes:
    Name:      multiarch0
    Endpoint:  unix:///var/run/docker.sock
    Status:    running
    Platforms: linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6
    

    As a side note, you might have to restart your docker service in order to take effect.

    I was able to rebuild and run amd64 on my amd64 machine.

    $ docker run --rm sntshk/cotu
    Unable to find image 'sntshk/cotu:latest' locally
    [...output trimmed...]
    Status: Downloaded newer image for sntshk/cotu:latest
    standard_init_linux.go:228: exec user process caused: exec format error
    
    $ docker rmi sntshk/cotu
    [...output trimmed...]
    Deleted: sha256:07d3c46c9599a88fa81c385391300ab877b98ef71b18cce942455025657edeb5
    
    $ docker run --rm sntshk/cotu
    Unable to find image 'sntshk/cotu:latest' locally
    latest: Pulling from sntshk/cotu
    [...output trimmed...]
    Status: Downloaded newer image for sntshk/cotu:latest
    hello world
    

    Also have a look at Building Multi-Architecture Docker Images With Buildx by Artur Klauser.