Skip to content

Commit

Permalink
Build docker/binfmt v3.1.0
Browse files Browse the repository at this point in the history
Signed-off-by: Stefan Scherer <stefan.scherer@docker.com>
  • Loading branch information
StefanScherer committed May 13, 2019
0 parents commit 597e038
Show file tree
Hide file tree
Showing 9 changed files with 271 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bin/*
31 changes: 31 additions & 0 deletions Jenkinsfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
pipeline {
agent {
label 'linux && amd64 && docker'
}
parameters {
booleanParam(name: "push", defaultValue: false)
}
options {
timeout(time: 1, unit: 'HOURS')
timestamps()
ansiColor('xterm')
}
stages {
stage('build') {
steps {
sh 'make build'
}
}
stage('push') {
when {
beforeAgent true
expression { params.push }
}
steps {
withDockerRegistry([credentialsId: 'fb721cc7-c508-4691-b6a4-403337e42ecc', url: "https://index.docker.io/v1/"]) {
sh 'make push'
}
}
}
}
}
14 changes: 14 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
ALL: build

bin/linuxkit:
curl -Lo bin/linuxkit https://github.com/linuxkit/linuxkit/releases/download/v0.7/linuxkit-linux-amd64
chmod +x bin/linuxkit

build: bin/linuxkit
bin/linuxkit pkg build -org docker binfmt

push: bin/linuxkit
bin/linuxkit pkg push -org docker binfmt

clean:
rm -f bin/*
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# docker/binfmt

Build and push the `docker/binfmt` image.

## Build

make

This builds the `docker/binfmt` image with QEMU static binaries from `moby/qemu`
and branch `moby/v3.1.0`.

## Push

make push

This pushes the image to Docker Hub.

## Test manually

make

Builds a docker/binfmt image - note the image ID.

docker run --rm --privileged imageid

This registers the new QEMU binaries in the host kernel. Test all different architectures

docker run --rm aarch64/alpine uname -a
docker run --rm arm32v7/alpine uname -a
docker run --rm ppc64le/alpine uname -a
docker run --rm s390x/alpine uname -a
Empty file added bin/.gitignore
Empty file.
74 changes: 74 additions & 0 deletions binfmt/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
FROM debian@sha256:75f7d0590b45561bfa443abad0b3e0f86e2811b1fc176f786cd30eb078d1846f AS qemu
RUN apt-get update && \
apt-get install -y \
build-essential \
git \
libtool \
libpixman-1-dev \
libglib2.0-dev \
pkg-config \
python

RUN git clone -b moby/v3.1.0 https://github.com/moby/qemu && \
cd qemu && scripts/git-submodule.sh update \
ui/keycodemapdb \
tests/fp/berkeley-testfloat-3 \
tests/fp/berkeley-softfloat-3 \
dtc

WORKDIR /qemu

RUN ./configure \
--prefix=/usr \
--enable-linux-user \
--disable-system \
--static \
--disable-blobs \
--disable-bluez \
--disable-brlapi \
--disable-cap-ng \
--disable-capstone \
--disable-curl \
--disable-curses \
--disable-docs \
--disable-gcrypt \
--disable-gnutls \
--disable-gtk \
--disable-guest-agent \
--disable-guest-agent-msi \
--disable-libiscsi \
--disable-libnfs \
--disable-mpath \
--disable-nettle \
--disable-opengl \
--disable-sdl \
--disable-spice \
--disable-tools \
--disable-vte \
--target-list="aarch64-linux-user arm-linux-user ppc64le-linux-user s390x-linux-user"

RUN make -j "$(getconf _NPROCESSORS_ONLN)"

RUN mkdir /binaries && \
cp aarch64-linux-user/qemu-aarch64 /binaries && \
cp arm-linux-user/qemu-arm /binaries && \
cp ppc64le-linux-user/qemu-ppc64le /binaries && \
cp s390x-linux-user/qemu-s390x /binaries

RUN make install

FROM linuxkit/alpine:518c2ed0f398c5508969ac5e033607201fb419ed AS mirror

RUN apk add --no-cache go musl-dev
ENV GOPATH=/go PATH=$PATH:/go/bin

COPY main.go /go/src/binfmt/
RUN go-compile.sh /go/src/binfmt

FROM scratch
ENTRYPOINT []
WORKDIR /
COPY --from=qemu usr/bin/qemu-* usr/bin/
COPY --from=mirror /go/bin/binfmt usr/bin/binfmt
COPY etc/binfmt.d/00_linuxkit.conf etc/binfmt.d/00_linuxkit.conf
CMD ["/usr/bin/binfmt"]
10 changes: 10 additions & 0 deletions binfmt/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
image: binfmt
network: true
arches:
- amd64
config:
capabilities:
- CAP_SYS_ADMIN
readonly: true
net: new
ipc: new
8 changes: 8 additions & 0 deletions binfmt/etc/binfmt.d/00_linuxkit.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Register other architecture binary formats https://www.kernel.org/doc/html/latest/admin-guide/binfmt-misc.html
# Architecture masks and magics can be found here
# https://github.com/qemu/qemu/blob/master/scripts/qemu-binfmt-conf.sh
# Replace ELF with `\x45\x4c\x46`
:qemu-aarch64:M:0:\x7f\x45\x4c\x46\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-aarch64:CF
:qemu-arm:M:0:\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-arm:CF
:qemu-ppc64le:M:0:\x7f\x45\x4c\x46\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x15\x00:\xff\xff\xff\xff\xff\xff\xff\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\x00:/usr/bin/qemu-ppc64le:CF
:qemu-s390x:M:0:\x7f\x45\x4c\x46\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x16:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-s390x:CF
102 changes: 102 additions & 0 deletions binfmt/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package main

import (
"bytes"
"flag"
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"syscall"
)

var (
dir string
mount string
)

func init() {
flag.StringVar(&dir, "dir", "/etc/binfmt.d", "directory with config files")
flag.StringVar(&mount, "mount", "/proc/sys/fs/binfmt_misc", "binfmt_misc mount point")
}

func binfmt(line []byte) error {
register := filepath.Join(mount, "register")
file, err := os.OpenFile(register, os.O_WRONLY, 0)
if err != nil {
e, ok := err.(*os.PathError)
if ok && e.Err == syscall.ENOENT {
return fmt.Errorf("ENOENT opening %s is it mounted?", register)
}
if ok && e.Err == syscall.EPERM {
return fmt.Errorf("EPERM opening %s check permissions?", register)
}
return fmt.Errorf("Cannot open %s: %s", register, err)
}
defer file.Close()
// short writes should not occur on sysfs, cannot usefully recover
_, err = file.Write(line)
if err != nil {
e, ok := err.(*os.PathError)
if ok && e.Err == syscall.EEXIST {
// clear existing entry
split := bytes.SplitN(line[1:], []byte(":"), 2)
if len(split) == 0 {
return fmt.Errorf("Cannot determine arch from: %s", line)
}
arch := filepath.Join(mount, string(split[0]))
clear, err := os.OpenFile(arch, os.O_WRONLY, 0)
if err != nil {
return fmt.Errorf("Cannot open %s: %s", arch, err)
}
defer clear.Close()
_, err = clear.Write([]byte("-1"))
if err != nil {
return fmt.Errorf("Cannot write to %s: %s", arch, err)
}
_, err = file.Write(line)
if err != nil {
return fmt.Errorf("Cannot write to %s: %s", register, err)
}
return nil
}
return fmt.Errorf("Cannot write to %s: %s", register, err)
}
return nil
}

func main() {
flag.Parse()

if err := syscall.Mount("binfmt_misc", mount, "binfmt_misc", 0, ""); err != nil {
log.Fatalf("Cannot mount binfmt_misc filesystem at %s: %v", mount, err)
}
defer syscall.Unmount(mount, 0)

files, err := ioutil.ReadDir(dir)
if err != nil {
log.Fatalf("Cannot read directory %s: %s", dir, err)
}

for _, file := range files {
contents, err := ioutil.ReadFile(filepath.Join(dir, file.Name()))
if err != nil {
log.Fatalf("Cannot read file %s: %s", file.Name(), err)
}
lines := bytes.Split(contents, []byte("\n"))
for _, line := range lines {
if len(line) == 0 {
continue
}
// ignore comments
if line[0] == '#' {
continue
}
err = binfmt(line)
if err != nil {
log.Fatal(err)
}
}
}
}

0 comments on commit 597e038

Please sign in to comment.