<p>You can either:</p>
<ol>
<li>cross compile the image</li>
<li>perform the build within an emulator like qemu using binfmt_misc</li>
<li>run the build on each platform</li>
</ol>
<p>I've done a fair bit of cross compiling in Go, pretty sure there's the ability to do that in gcc. Just note that you'll need to include all the libraries for those other platforms too, which may get complicated. Therefore a statically compiled binary my be easiest. Doing this, I then have a multi-stage build where the last stage is for the target platform and only includes copy commands to copy in the cross compiled binary. For controlling the platform on each stage, there's a <code>FROM --platform</code> option.</p>
<p>With binfmt_misc, that needs to be installed with the <code>--fix-binary</code> option that will show a <code>F</code> flag in the <code>/proc/sys/fs/binfmt_misc/*</code>. If it's not installed with this option, trying to run a container for another platform will output a &quot;file not found&quot; error as binfmt searches for the interpreter inside the container filesystem rather than the host filesystem. Note that this is already setup on Docker Desktop.</p>
<p>Once built, you can push the resulting image to the registry as a multi-platform image, and the appropriate image will pulled under the same name based on the platform performing the pull. The easiest way I've found to create multi-platform images is to use <a href="https://github.com/docker/buildx" rel="nofollow noreferrer">buildx</a> which comes bundled into recent versions of docker.</p>
<p>I demonstrate each of these options in <a href="https://sudo-bmitch.github.io/presentations/docker-build/presentation.html#cross-platform" rel="nofollow noreferrer">this presentation</a>.</p>

CC BY-SA 4.0
2020-12-04T15:57:47.997Z
2020-12-04T15:57:47.997Z
BMitch
<p>I've not tried this myself, but it seems that you can use docker <code>buildx</code> to build for multiple architectures: <a href="https://www.docker.com/blog/multi-arch-images/" rel="nofollow noreferrer">https://www.docker.com/blog/multi-arch-images/</a>.</p>

CC BY-SA 4.0
2020-12-04T15:43:50.613Z
2020-12-04T15:43:50.613Z
migueldavid
<p>I have built on an x86-based Windows laptop a Docker image to be run as a container on an ARM-based architecture (Raspberry Pi 4).</p>
<p>Due to ending up with an x86 executable when this is built in the Dockerfile, as much as possible, including the library and app build, is deferred until the container actually runs on the Pi.</p>
<p>However, this seems absurd in that the build must be done each time the container runs (which it may on many Pis). No doubt it also needlessly increases the container's size (which is less important, but still annoyingly sub-optimal)</p>
<p>So in summary, I wonder if there is a way to run gcc in the Dockerfile and indicate that the target architecture is ARM and not the laptop on which the docker build is running.</p>
<p>My Dockerfile currently comprises :</p>
<pre><code>FROM arm32v7/ubuntu:latest

# Defined only while image is being built
ARG DEBIAN_FRONTEND=noninteractive

# Set in container
ENV TZ=Europe/London

ADD ./src /app
WORKDIR /app

# Development only :
#
#   vim
#
RUN apt-get -y update \
 &amp;&amp; apt-get -y upgrade \
 &amp;&amp; apt-get -t install apt-utils \
 &amp;&amp; apt-get -y install tzdata \
 &amp;&amp; apt-get -y install dh-autoreconf \
 &amp;&amp; apt-get -y install libcurl4-gnutls-dev \
 &amp;&amp; apt-get -y install libexpat1-dev \
 &amp;&amp; apt-get -y install make \
 &amp;&amp; apt-get -y install gettext \
 &amp;&amp; apt-get -y install libz-dev \
 &amp;&amp; apt-get -y install libssl-dev \
 &amp;&amp; apt-get -y install libghc-zlib-dev \
 &amp;&amp; apt-get -y install git \
 &amp;&amp; apt-get -y install build-essential \
 &amp;&amp; apt-get -y install vim \
 &amp;&amp; git clone https://github.com/eclipse/paho.mqtt.c.git

CMD [&quot;/bin/bash&quot;, &quot;myapp.sh&quot;]
</code></pre>
<p>and myapp.sh comprises :</p>
<pre><code>#!/bin/bash

# Build Paho MQTT library
#
cd /app/paho.mqtt.c
make

# Build the experiment app
#
cd /app

gcc -L/experiment/paho.mqtt.c/build/output -o myapp -lpaho-mqtt3a main.c

./myapp
</code></pre>
<p>I would have thought the first line &quot;FROM arm32v7/ubuntu:latest&quot; in the Dockerfile would tell gcc that the target architecture was ARM, but evidently not!</p>
<p>P.S. I know I could manually build the app outside Docker on a Pi, and simply copy the ARM executable into the Docker image. But I would rather the the app build is included as part of the image build if possible.</p>

<docker><dockerfile>
Can I build docker image containing ARM executable when running docker build on non-ARM architecture?
John Ramsden
# Can I build docker image containing ARM executable when running docker build on non-ARM architecture?

(Asked by: username_0 on 2020-12-02)

I have built on an x86-based Windows laptop a Docker image to be run as a container on an ARM-based architecture (Raspberry Pi 4).
Due to ending up with an x86 executable when this is built in the Dockerfile, as much as possible, including the library and app build, is deferred until the container actually runs on the Pi.
However, this seems absurd in that the build must be done each time the container runs (which it may on many Pis). No doubt it also needlessly increases the container's size (which is less important, but still annoyingly sub-optimal)
So in summary, I wonder if there is a way to run gcc in the Dockerfile and indicate that the target architecture is ARM and not the laptop on which the docker build is running.
My Dockerfile currently comprises :
FROM arm32v7/ubuntu:latest

# Defined only while image is being built
ARG DEBIAN_FRONTEND=noninteractive

# Set in container
ENV TZ=Europe/London

ADD ./src /app
WORKDIR /app

# Development only :
#
#   vim
#
RUN apt-get -y update \
 && apt-get -y upgrade \
 && apt-get -t install apt-utils \
 && apt-get -y install tzdata \
 && apt-get -y install dh-autoreconf \
 && apt-get -y install libcurl4-gnutls-dev \
 && apt-get -y install libexpat1-dev \
 && apt-get -y install make \
 && apt-get -y install gettext \
 && apt-get -y install libz-dev \
 && apt-get -y install libssl-dev \
 && apt-get -y install libghc-zlib-dev \
 && apt-get -y install git \
 && apt-get -y install build-essential \
 && apt-get -y install vim \
 && git clone https://github.com/eclipse/paho.mqtt.c.git

CMD ["/bin/bash", "myapp.sh"]

and myapp.sh comprises :
#!/bin/bash

# Build Paho MQTT library
#
cd /app/paho.mqtt.c
make

# Build the experiment app
#
cd /app

gcc -L/experiment/paho.mqtt.c/build/output -o myapp -lpaho-mqtt3a main.c

./myapp

I would have thought the first line "FROM arm32v7/ubuntu:latest" in the Dockerfile would tell gcc that the target architecture was ARM, but evidently not!
P.S. I know I could manually build the app outside Docker on a Pi, and simply copy the ARM executable into the Docker image. But I would rather the the app build is included as part of the image build if possible.

**Tags:** docker, dockerfile


---

## 2 answers

### Answer by username_1 on 2020-12-04. Score: 1

You can either:

1. cross compile the image
2. perform the build within an emulator like qemu using binfmt\_misc
3. run the build on each platform

I've done a fair bit of cross compiling in Go, pretty sure there's the ability to do that in gcc. Just note that you'll need to include all the libraries for those other platforms too, which may get complicated. Therefore a statically compiled binary my be easiest. Doing this, I then have a multi-stage build where the last stage is for the target platform and only includes copy commands to copy in the cross compiled binary. For controlling the platform on each stage, there's a `FROM --platform` option.

With binfmt\_misc, that needs to be installed with the `--fix-binary` option that will show a `F` flag in the `/proc/sys/fs/binfmt_misc/*`. If it's not installed with this option, trying to run a container for another platform will output a "file not found" error as binfmt searches for the interpreter inside the container filesystem rather than the host filesystem. Note that this is already setup on Docker Desktop.

Once built, you can push the resulting image to the registry as a multi-platform image, and the appropriate image will pulled under the same name based on the platform performing the pull. The easiest way I've found to create multi-platform images is to use [buildx](https://github.com/docker/buildx) which comes bundled into recent versions of docker.

I demonstrate each of these options in [this presentation](https://sudo-bmitch.github.io/presentations/docker-build/presentation.html#cross-platform).


---

### Answer by username_2 on 2020-12-04. Score: 1

I've not tried this myself, but it seems that you can use docker `buildx` to build for multiple architectures: <https://www.docker.com/blog/multi-arch-images/>.


---

