Rework container creation

- simplify the process by having the riddler container build the rootfs and config
- output tarred up rootfs and config.json as otherwise file ownership not preserved
- allow easy build of a collection of container tarballs with another conversion script

This makes it easy to choose which container images you want and just convert any
set to a initrd image
```
tar cf - container1.tar container2.tar | docker run -i tartar2initrd > initrd.img
```

Next stage will use a manifest to select the ones to add for each edition.

Signed-off-by: Justin Cormack <justin.cormack@docker.com>
This commit is contained in:
Justin Cormack 2017-01-25 22:48:27 +00:00
parent 7c9450cf48
commit 7d14547e87
14 changed files with 148 additions and 54 deletions

1
alpine/.gitignore vendored
View File

@ -2,6 +2,7 @@
*.tag
*.iso
*.vhd
*.tar
*.tar.gz
/mobylinux-boot.vhdx
/mobylinux.efi

View File

@ -22,6 +22,9 @@ PAD4_IMAGE=mobylinux/pad4@sha256:1ad26970698670373ee0bf374a06900f712a61b8038255e
# Tag: d5711601eb5b89de0f052d87365e18388ff3f1b5
TAR2INITRD_IMAGE=mobylinux/tar2initrd@sha256:58d377e65845f91400e173ce9fca93462f2f237947eef2b0d2c17bb4f2da5ee8
# Tag: d56cde1558e3080e59a32e3cd7c7141baa601811
TARTAR2INITRD_IMAGE=mobylinux/tartar2initrd@sha256:e1ad4522ff906d339da5f250b9ef6bffa5a70b4dec7d2cf7f7dbd0447b79352f
# Tag: 77bc577875fb3a80ac2d14b70d1daa885bbf199c
GCE_IMAGE=mobylinux/mkimage-gce@sha256:f9abf2eae20984b7dd3c1afb700b2c9c41e39e6e7c688c78348a51d0780d74cc
@ -63,12 +66,12 @@ moby.img: Dockerfile mkinitrd.sh init $(ETCFILES)
container.img:
$(MAKE) -j -C containers
tar cf - containers/*/rootfs containers/*/config.json | \
docker run --rm --read-only --net=none --log-driver=none --tmpfs /tmp -i $(TAR2INITRD_IMAGE) > $@
tar cf - $$(find containers -name container.tar) | \
docker run --rm --read-only --net=none --log-driver=none --tmpfs /tmp -i $(TARTAR2INITRD_IMAGE) > $@
test.img:
$(MAKE) -j -C test
tar cf - test/rootfs test/config.json | \
cat test/container.tar | \
docker run --rm --read-only --net=none --log-driver=none --tmpfs /tmp -i $(TAR2INITRD_IMAGE) > $@
initrd.img: moby.img container.img

View File

@ -1,2 +0,0 @@
rootfs
config.json

View File

@ -1,20 +1,16 @@
# Tag: 893c93bf54bc037f6952886330d5ba58746ace37
RIDDLER=mobylinux/riddler@sha256:3d4a61555110be4b6e8ff6bcdcf5f8aa24d64564eb4162ea4e580d8916d083cc
# Tag: c3312201a71982a820067a521e457a8c29aa7397
BINFMT_IMAGE=mobylinux/binfmt@sha256:2d08969710368376d927b0fc51796a2c30c67070421d4eb1973a08a83f98181f
default: config.json
default: container.tar
EXCLUDE=--exclude .dockerenv --exclude Dockerfile \
--exclude dev/console --exclude dev/pts --exclude dev/shm \
--exclude etc/hostname --exclude etc/hosts --exclude etc/mtab --exclude etc/resolv.conf
config.json:
mkdir -p rootfs
CONTAINER=$$( docker create $(BINFMT_IMAGE) /dev/null ) && \
docker export $$CONTAINER | tar -xf - -C rootfs $(EXCLUDE) && \
docker rm $$CONTAINER && \
../riddler.sh --cap-drop all --read-only -v /proc/sys/fs/binfmt_misc:/binfmt_misc $(BINFMT_IMAGE) /usr/bin/binfmt -dir /etc/binfmt.d/ -mount /binfmt_misc >$@
container.tar:
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock $(RIDDLER) \
$(BINFMT_IMAGE) /containers/binfmt --cap-drop all --read-only -v /proc/sys/fs/binfmt_misc:/binfmt_misc $(BINFMT_IMAGE) /usr/bin/binfmt -dir /etc/binfmt.d/ -mount /binfmt_misc >$@
clean:
rm -rf rootfs config.json
rm -f container.tar
.DELETE_ON_ERROR:

View File

@ -1,6 +0,0 @@
#!/bin/sh
# tag: 801f33408e43e6a22985aa994ab0bcba41659ec6
RIDDLER=mobylinux/riddler@sha256:2dda30eb24ac531a9f2164e9592a21538b5841f2ca8459b0c190da46ea7dfafd
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock $RIDDLER "$@"

View File

@ -1,20 +1,16 @@
# Tag: 893c93bf54bc037f6952886330d5ba58746ace37
RIDDLER=mobylinux/riddler@sha256:3d4a61555110be4b6e8ff6bcdcf5f8aa24d64564eb4162ea4e580d8916d083cc
# Tag: 3dad6dd43270fa632ac031e99d1947f20b22eec9
RNGD_IMAGE=mobylinux/rngd@sha256:1c93c1db7196f6f71f8e300bc1d15f0376dd18e8891c8789d77c8ff19f3a9a92
default: config.json
default: container.tar
EXCLUDE=--exclude .dockerenv --exclude Dockerfile \
--exclude dev/console --exclude dev/pts --exclude dev/shm \
--exclude etc/hostname --exclude etc/hosts --exclude etc/mtab --exclude etc/resolv.conf
config.json:
mkdir -p rootfs
CONTAINER=$$( docker create $(RNGD_IMAGE) /dev/null ) && \
docker export $$CONTAINER | tar -xf - -C rootfs $(EXCLUDE) && \
docker rm $$CONTAINER && \
../riddler.sh --cap-drop all --cap-add SYS_ADMIN --read-only --oom-score-adj -800 $(RNGD_IMAGE) /bin/tini /usr/sbin/rngd -f >$@
container.tar:
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock $(RIDDLER) \
$(RNGD_IMAGE) /containers/rngd --cap-drop all --cap-add SYS_ADMIN --read-only --oom-score-adj -800 $(RNGD_IMAGE) /bin/tini /usr/sbin/rngd -f >$@
clean:
rm -rf rootfs config.json
rm -f container.tar
.DELETE_ON_ERROR:

View File

@ -1,2 +0,0 @@
rootfs
config.json

View File

@ -1,20 +1,20 @@
# Tag: 893c93bf54bc037f6952886330d5ba58746ace37
RIDDLER=mobylinux/riddler@sha256:3d4a61555110be4b6e8ff6bcdcf5f8aa24d64564eb4162ea4e580d8916d083cc
# Tag: e79cbcc45b715cea7047a802944b478a7b5a906a
TEST_IMAGE=mobylinux/test@sha256:bc9403a9fc7aa5298f92c83d1e3423e804097f08dbba623e076c1728666f6b73
default: config.json
default: container.tar
EXCLUDE=--exclude .dockerenv --exclude Dockerfile \
--exclude dev/console --exclude dev/pts --exclude dev/shm \
--exclude etc/hostname --exclude etc/hosts --exclude etc/mtab --exclude etc/resolv.conf
config.json:
mkdir -p rootfs
CONTAINER=$$( docker create $(TEST_IMAGE) /dev/null ) && \
docker export $$CONTAINER | tar -xf - -C rootfs $(EXCLUDE) && \
docker rm $$CONTAINER && \
../containers/riddler.sh --cap-drop all --cap-add SYS_ADMIN -e HOME=/tmp -v /tmp:/tmp -v /var/run/docker.sock:/var/run/docker.sock:ro -v /usr/bin/docker:/usr/bin/docker:ro -v /etc/resolv.conf:/etc/resolv.conf:ro --net host --read-only $(TEST_IMAGE) /bin/sh /bin/test.sh >$@
container.tar:
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock $(RIDDLER) \
$(TEST_IMAGE) /test --cap-drop all --cap-add SYS_ADMIN -e HOME=/tmp \
-v /tmp:/tmp -v /var/run/docker.sock:/var/run/docker.sock:ro \
-v /usr/bin/docker:/usr/bin/docker:ro \
-v /etc/resolv.conf:/etc/resolv.conf:ro \
--net host --read-only $(TEST_IMAGE) /bin/sh /bin/test.sh >$@
clean:
rm -rf rootfs config.json
rm -f container.tar
.DELETE_ON_ERROR:

View File

@ -9,6 +9,7 @@ RUN \
jq \
linux-headers \
musl-dev \
tar \
&& true
COPY Dockerfile /

View File

@ -8,11 +8,11 @@ default: push
hash: Dockerfile riddler.sh
DOCKER_CONTENT_TRUST=1 docker pull $(BASE)
tar cf - $^ | docker build --no-cache -t $(IMAGE):build -
docker run --entrypoint=/bin/sh --rm $(IMAGE):build -c 'cat /Dockerfile /usr/bin/riddler.sh /lib/apk/db/installed | sha1sum' | sed 's/ .*//' > hash
docker run --entrypoint=/bin/sh --rm $(IMAGE):build -c 'cat /Dockerfile /usr/bin/riddler.sh /lib/apk/db/installed | sha1sum' | sed 's/ .*//' > $@
push: hash
docker pull mobylinux/$(IMAGE):$(shell cat hash) || \
(docker tag $(IMAGE):build mobylinux/$(IMAGE):latest && \
(docker tag $(IMAGE):build mobylinux/$(IMAGE):$(shell cat hash) && \
docker push mobylinux/$(IMAGE):$(shell cat hash))
docker rmi $(IMAGE):build
rm -f hash

View File

@ -2,6 +2,17 @@
set -e
# arguments are image name, prefix, then arguments passed to Docker
# eg ./riddler.sh alpine:3.4 / --read-only alpine:3.4 ls
# This script will output a tarball under prefix/ with rootfs and config.json
IMAGE="$1"; shift
PREFIX="$1"; shift
cd /tmp
mkdir -p /tmp/$PREFIX
cd /tmp/$PREFIX
# riddler always adds the apparmor options if this is not present
EXTRA_OPTIONS="--security-opt apparmor=unconfined"
@ -20,9 +31,24 @@ docker rm $CONTAINER > /dev/null
# --read-only sets /dev ro
# /sysfs ro unless privileged - cannot detect so will do if grant all caps
#
cat config.json | \
mv config.json config.json.orig
cat config.json.orig | \
jq 'del(.process.rlimits)' | \
jq 'del (.linux.resources.memory.swappiness)' | \
jq 'del(.linux.uidMappings) | del(.linux.gidMappings) | .linux.namespaces = (.linux.namespaces|map(select(.type!="user")))' | \
jq 'if .root.readonly==true then .mounts = (.mounts|map(if .destination=="/dev" then .options |= .+ ["ro"] else . end)) else . end' | \
jq '.mounts = if .process.capabilities | length != 38 then (.mounts|map(if .destination=="/sys" then .options |= .+ ["ro"] else . end)) else . end'
jq '.mounts = if .process.capabilities | length != 38 then (.mounts|map(if .destination=="/sys" then .options |= .+ ["ro"] else . end)) else . end' \
> config.json
rm config.json.orig
# extract rootfs
EXCLUDE="--exclude .dockerenv --exclude Dockerfile \
--exclude dev/console --exclude dev/pts --exclude dev/shm \
--exclude etc/hostname --exclude etc/hosts --exclude etc/mtab --exclude etc/resolv.conf"
mkdir -p rootfs
CONTAINER="$(docker create $IMAGE /dev/null)"
docker export "$CONTAINER" | tar -xf - -C rootfs $EXCLUDE
docker rm "$CONTAINER" > /dev/null
cd /tmp
tar cf - .

View File

@ -0,0 +1,12 @@
FROM alpine:3.5
RUN \
apk update && apk upgrade -a && \
apk add --no-cache \
libarchive-tools \
&& true
COPY . /
ENTRYPOINT ["/bin/sh", "-c"]
CMD ["/tartar2initrd.sh"]

View File

@ -0,0 +1,29 @@
.PHONY: tag push
BASE=alpine:3.5
IMAGE=tartar2initrd
default: push
hash: Dockerfile tartar2initrd.sh
DOCKER_CONTENT_TRUST=1 docker pull $(BASE)
tar cf - $^ | docker build --no-cache -t $(IMAGE):build -
docker run --rm --entrypoint=/bin/sh $(IMAGE):build -c "cat $^ /lib/apk/db/installed | sha1sum" | sed 's/ .*//' > $@
push: hash
docker pull mobylinux/$(IMAGE):$(shell cat hash) || \
(docker tag $(IMAGE):build mobylinux/$(IMAGE):$(shell cat hash) && \
docker push mobylinux/$(IMAGE):$(shell cat hash))
docker rmi $(IMAGE):build
rm -f hash
tag: hash
docker pull mobylinux/$(IMAGE):$(shell cat hash) || \
docker tag $(IMAGE):build mobylinux/$(IMAGE):$(shell cat hash)
docker rmi $(IMAGE):build
rm -f hash
clean:
rm -f hash
.DELETE_ON_ERROR:

View File

@ -0,0 +1,40 @@
#!/bin/sh
set -e
mkdir -p /tmp/input0 /tmp/input
cd /tmp/input0
# outer tarball
bsdtar xf -
cd /tmp/input
# inner tarballs
find /tmp/input0 \( -name '*.tar' -or -name '*.tgz' -or -name '*.tar.gz' \) -exec bsdtar xf '{}' \;
find . | cpio -H newc -o | gzip -9 > ../initrd.img
cd /tmp
SIZE=$(stat -c "%s" initrd.img)
SIZE4=$(( $SIZE / 4 \* 4 ))
DIFF=$(( $SIZE - $SIZE4 ))
[ $DIFF -ne 0 ] && DIFF=$(( 4 - $DIFF ))
dd if=/dev/zero bs=1 count=$DIFF of=zeropad 2>/dev/null
cat zeropad >> initrd.img
SIZE=$(stat -c "%s" initrd.img)
SIZE4=$(( $SIZE / 4 \* 4 ))
DIFF=$(( $SIZE - $SIZE4 ))
if [ $DIFF -ne 0 ]
then
echo "Bad alignment" >2
exit 1
fi
cat initrd.img