How do I build a Docker image for an ARM device? - docker

I'm noticing exec user process caused "exec format error" when trying to run a Docker image on a Raspberry Pi 4.
First I'm bewildered that a Docker image is pulled that won't run on the platform to begin with. Nonetheless I am keen to make it work, but I don't know how.
Here's the project: https://github.com/kaihendry/sla How can I build ARM compatible images?

The FROM golang line will pull the appropriate architecture; they have arm v6 (older pi / pi 0 running raspbian) + arm v7 (newer pi running raspbian) and arm64 (newer pi running ubuntu) as part of a multi-arch docker image https://hub.docker.com/_/golang?tab=tags
Your problem with exec format error (i.e. it is the wrong binary format) appears to just be the line https://github.com/kaihendry/sla/blob/a22d983340f3df794696e5c8e31cf3b89f7edd89/Dockerfile#L14 where your architecture is wrong for a pi; it should be GOARCH=arm (32 bit, non-ubuntu) or GOARCH=arm64 (ubuntu), additionally for 32 bit ARM (v6 and v7) you would also need to specify GOARM=6 or GOARM=7 per https://github.com/golang/go/wiki/GoArm
I have tested your code with a swap to to GOARCH=arm64 (and no GOARM required) and had it build and run on my pi3b+ running ubuntu.
Noting for future reference I suspect my answer may change if/when raspbian switches to 64 bit.

Related

Building Python wheels in Docker for Raspberry Pi Zero on x86_64 machine

I'm hoping this is an appropriate venue for my question. There's a lot of pieces to this puzzle.
I'm building a container using Docker that is destined to run on a Raspberry Pi Zero. The RPi Zero has an ARMv6 hard-float processor. The container will run a Python program that includes some dependencies that must be compiled (uses binary libraries). I am able to build and run the container on the RPi Zero itself, but building the container literally takes hours. I'm hoping to 1) speed up the process of building and 2) allow this to happen in a CI environment.
The approach I've taken in the past to build minimal Python containers that have dependencies requiring compilation is to use a multistage Docker build. I first startup a container with a full toolchain, then run pip wheel to compile all requirements into .whl files. I then copy the .whl files to the final container, install any binary libraries using the typical package manager, and then point pip install at this cache (--find-links=/wheels) for the installation of Python dependencies. This approach also works just fine on the Pi, but as I said it takes forever.
I've considered a few different approaches I could take:
Figure out how to get the Docker engine on my main dev machine (also in CI) to run and build an ARM image using qemu-arm-static while running docker build, and then somehow tag the resulting image as ARMv6 and upload it to my registry somehow. (I could just use a tag or a different repo name) I haven't honestly dug too deep into this, but my main concern is that every example I've seen of qemu-arm seems to indicate that it runs ARMv7 emulation. The RPi Zero can't actually even run many Docker containers that are made available for ARM due to this (exit 139). The arm32v6 "user" does provide working base images that run fine on the RPi Zero, which is what I'm using as the source images to build on my Pi itself.
Emulate an entire RasPi using qemu-system-arm. Again though, it looks like this emulates ARMv7, meaning the compiled wheels might not be able to run on the Pi zero.
Setup a cross-compiling toolchain for ARMv6. A few problems: I wouldn't know how to make sure pip uses that toolchain when compiling, and also I'd need to get and compile any other dependent library (even possibly all the way down to glibc?) so the header files will resolve.
It looks like this is easy to do if you want to do it for ARMv7 (which I believe the RPi 2 uses) or later, but I'm specifically using a Zero for my project, so I don't have that option.
TL;dr: How do I build binary Python wheels for ARMv6 using Docker without having to do it on a slow, single-core Raspberry Pi Zero?

binary gets "illegal instruction" on one machine but not another with same docker image

I have built a docker image with several packages loaded for a development environment.
I plan to use the image to make porting the environment to various machines simple.
In a container of the image, I can build my binary (using cmake & g++) on any of the machines I have loaded the docker image to. The binary has executed well within such containers on most machines.
But, on one machine executing the binary in the container results in a core dump with "illegal instruction" reported.
The crash happens on a machine with Intel Xeon CPUs. But it runs fine on another Xeon machine. It also runs fine on an AMD Ryzen machine.
I haven't tried executing the binary outside the container because the environment is so hard to set up.. why I'm using docker.
I just wonder if anyone's seen this happen much and how to start trying to resolve?
If it helps & anyone is familiar it, the base image I pulled from docker hub, to add other packages to, is floopcz/tensorflow_cc:ubuntu-shared. It is a Ubuntu image with the Tensorflow C++ API built for CPU use only (not CUDA).
The binary that's crashing does attempt to open a Tensorflow session before doing anything else.
I'm running Docker 19.03 on Ubuntu 16.04 and 18.04. The image has Ubuntu 18.04 loaded.

Can Docker work targeting any arch with Windows 10 ARM?

I'd like to know if I'll be able to run Docker on ARM (Windows) machine and still have the same versatility?
I didn't see a lot of readings about this, as ARM PCs are quite new.

How to install 32-bit docker container

I'm trying to create a 32-bit docker image with Ubuntu 14.04 and, any time that I run uname, I see that it is x86_64 instead of i386. Could anyone tell me why this is happening?
docker run talex5/lucid32 uname -m
The weird thing is when I look up the architecture type a different way, it says 32-bit:
docker run i386/ubuntu:14.04 file /sbin/init
/sbin/init: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=c394677bccc720a3bb4f4c42a48e008ff33e39b1, stripped`
This happens consistently whenever I download different docker images that say they are 32-bit and even when I create my own docker image using debootstrap.
Thanks!
uname reports the version and OS details of the kernel, but Docker containers always use the host system's kernel, and if it's a 64-bit kernel it will report x86_64.
You should see the same results running this with a mixed 32-/64-bit OS install (in Ubuntu land installing packages like libc6:i686); with a 32-bit filesystem tree in a chroot; and in a Docker container; which are all the same case of running 32-bit binaries on a system with a 64-bit kernel.
This is possible these days, with just a simple script. You could use https://github.com/docker-32bit/ubuntu.

Installing and using docker on 32 bit machine

I know that the official support is only for 64-bit but I can see from a few people have tried to custom build the docker binaries for 32-bit and succeeded (32-bit version of docker maybe a little unstable but it is fine for my use-case).
However, most of those blogs are old and do not work. Is there anyone who has done this recently?
I'm trying to build docker on 2 machines (i686) running with debian - wheezy and stretch (with kernel > 3.10; the minimum required). Has at-least 2GB of RAM and sufficient disk space.
There's 32bit docker on 32bit ARM machines, i think i've seen it done on RPis and ODROIDs at least.
On 32bit x86... i doubt you'll find much. It's not that it's impossible (if there's 32bit ARM docker, there can be 32bit x86 docker), but nobody cares enough. You can run 32bit docker images (in fact i've done it recently) on a 64bit system, but docker itself...

Resources