Merge pull request #73 from justincormack/docker

Add an output format for running images with Docker
This commit is contained in:
Justin Cormack 2017-06-07 16:38:14 +01:00 committed by GitHub
commit d906292096
10 changed files with 192 additions and 4 deletions

View File

@ -35,7 +35,37 @@ func (o *outputList) Set(value string) error {
} }
var streamable = map[string]bool{ var streamable = map[string]bool{
"tar": true, "docker": true,
"tar": true,
}
type addFun func(*tar.Writer) error
const dockerfile = `
FROM scratch
COPY . ./
RUN rm -f Dockerfile
ENTRYPOINT ["/sbin/tini", "--", "/bin/rc.init"]
`
var additions = map[string]addFun{
"docker": func(tw *tar.Writer) error {
log.Infof(" Adding Dockerfile")
hdr := &tar.Header{
Name: "Dockerfile",
Mode: 0644,
Size: int64(len(dockerfile)),
}
if err := tw.WriteHeader(hdr); err != nil {
return err
}
if _, err := tw.Write([]byte(dockerfile)); err != nil {
return err
}
return nil
},
} }
// Process the build arguments and execute build // Process the build arguments and execute build
@ -127,6 +157,7 @@ func build(args []string) {
} }
var outputFile *os.File var outputFile *os.File
var addition addFun
if *buildOutputFile != "" { if *buildOutputFile != "" {
if len(buildOut) > 1 { if len(buildOut) > 1 {
log.Fatal("The -output option can only be specified when generating a single output format") log.Fatal("The -output option can only be specified when generating a single output format")
@ -150,6 +181,7 @@ func build(args []string) {
} }
defer outputFile.Close() defer outputFile.Close()
} }
addition = additions[buildOut[0]]
} }
size, err := getDiskSizeMB(*buildSize) size, err := getDiskSizeMB(*buildSize)
@ -194,7 +226,7 @@ func build(args []string) {
buf = new(bytes.Buffer) buf = new(bytes.Buffer)
w = buf w = buf
} }
buildInternal(moby, w, *buildPull) buildInternal(moby, w, *buildPull, addition)
if outputFile == nil { if outputFile == nil {
image := buf.Bytes() image := buf.Bytes()
@ -272,7 +304,7 @@ func enforceContentTrust(fullImageName string, config *TrustConfig) bool {
// Perform the actual build process // Perform the actual build process
// TODO return error not panic // TODO return error not panic
func buildInternal(m Moby, w io.Writer, pull bool) { func buildInternal(m Moby, w io.Writer, pull bool, addition addFun) {
iw := tar.NewWriter(w) iw := tar.NewWriter(w)
if m.Kernel.Image != "" { if m.Kernel.Image != "" {
@ -341,6 +373,15 @@ func buildInternal(m Moby, w io.Writer, pull bool) {
if err != nil { if err != nil {
log.Fatalf("failed to add filesystem parts: %v", err) log.Fatalf("failed to add filesystem parts: %v", err)
} }
// add anything additional for this output type
if addition != nil {
err = addition(iw)
if err != nil {
log.Fatalf("Failed to add additional files")
}
}
err = iw.Close() err = iw.Close()
if err != nil { if err != nil {
log.Fatalf("initrd close error: %v", err) log.Fatalf("initrd close error: %v", err)

View File

@ -60,7 +60,7 @@ func ensureLinuxkitImage(name string) error {
} }
// TODO pass through --pull to here // TODO pass through --pull to here
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
buildInternal(m, buf, false) buildInternal(m, buf, false, nil)
image := buf.Bytes() image := buf.Bytes()
kernel, initrd, cmdline, err := tarToInitrd(image) kernel, initrd, cmdline, err := tarToInitrd(image)
if err != nil { if err != nil {

23
examples/README.md Normal file
View File

@ -0,0 +1,23 @@
Examples of building an image to run on LinuxKit or on a host
Currently the `moby` tool can output formats suitable for LinuxKit to boot on
a VM, and also some formats for running natively.
The `docker` format adds a `Dockerfile` to the tarball and expects a similar
file structure to `LinuxKit` but with the low level system setup pieces removed
as this will already be set up in a container.
The `mobytest/init-container` image in this repository has an example setup that
initialises `containerd` in exactly the same way as it runs in LinuxKit, which will
then start the `onboot` and `service` containers. The example below shows how you
can run `nginx` on either of these base configs.
```
moby build -output docker -o - docker.yml nginx.yml | docker build -t dockertest -
docker run -d -p 80:80 --privileged dockertest
moby build -output kernel+initrd linuxkit.yml nginx.yml
linuxkit run nginx
```
Both of these will run the same `nginx` either in a VM or a container.

9
examples/docker.yml Normal file
View File

@ -0,0 +1,9 @@
init:
- mobytest/init-container:b5de246b2790d74d53bae583a95c87869ca003e6
- linuxkit/runc:3a4e6cbf15470f62501b019b55e1caac5ee7689f
- linuxkit/containerd:5749f2e9e65395cc6635229e8da0e0d484320ddf
- linuxkit/ca-certificates:75cf419fb58770884c3464eb687ec8dfc704169d
trust:
org:
- linuxkit
- mobytest

18
examples/linuxkit.yml Normal file
View File

@ -0,0 +1,18 @@
kernel:
image: "linuxkit/kernel:4.9.x"
cmdline: "console=ttyS0"
init:
- linuxkit/init:1b8a7e394d2ec2f1fdb4d67645829d1b5bdca037
- linuxkit/runc:3a4e6cbf15470f62501b019b55e1caac5ee7689f
- linuxkit/containerd:5749f2e9e65395cc6635229e8da0e0d484320ddf
- linuxkit/ca-certificates:75cf419fb58770884c3464eb687ec8dfc704169d
onboot:
- name: dhcpcd
image: "linuxkit/dhcpcd:7d2b8aaaf20c24ad7d11a5ea2ea5b4a80dc966f1"
command: ["/sbin/dhcpcd", "--nobackground", "-f", "/dhcpcd.conf", "-1"]
services:
- name: rngd
image: "linuxkit/rngd:1fa4de44c961bb5075647181891a3e7e7ba51c31"
trust:
org:
- linuxkit

12
examples/nginx.yml Normal file
View File

@ -0,0 +1,12 @@
services:
- name: nginx
image: "nginx:alpine"
capabilities:
- CAP_NET_BIND_SERVICE
- CAP_CHOWN
- CAP_SETUID
- CAP_SETGID
- CAP_DAC_OVERRIDE
trust:
org:
- library

View File

@ -0,0 +1,14 @@
FROM linuxkit/alpine:630ee558e4869672fae230c78364e367b8ea67a9 AS mirror
RUN mkdir -p /out/etc/apk && cp -r /etc/apk/* /out/etc/apk/
RUN apk add --no-cache --initdb -p /out alpine-baselayout busybox musl tini
# Remove apk residuals. We have a read-only rootfs, so apk is of no use.
RUN rm -rf /out/etc/apk /out/lib/apk /out/var/cache
FROM scratch
ENTRYPOINT []
CMD []
WORKDIR /
COPY --from=mirror /out/ /
COPY etc etc/
COPY bin bin/

View File

@ -0,0 +1,15 @@
.PHONY: tag push
default: push
ORG?=mobytest
IMAGE=init-container
DEPS=Dockerfile $(wildcard etc/init.d/*) $(wildcard bin/*)
HASH?=$(shell git ls-tree HEAD -- ../$(notdir $(CURDIR)) | awk '{print $$3}')
tag: $(DEPS)
docker build --no-cache --network=none -t $(ORG)/$(IMAGE):$(HASH) .
push: tag
DOCKER_CONTENT_TRUST=1 docker pull $(ORG)/$(IMAGE):$(HASH) || \
DOCKER_CONTENT_TRUST=1 docker push $(ORG)/$(IMAGE):$(HASH)

10
pkg/init-container/bin/rc.init Executable file
View File

@ -0,0 +1,10 @@
#!/bin/sh
# execute other init processes
INITS="$(find /etc/init.d -type f | sort)"
for f in $INITS
do
$f &
done
wait

View File

@ -0,0 +1,46 @@
#!/bin/sh
# set global ulimits TODO move to /etc/limits.conf
ulimit -n 1048576
ulimit -p unlimited
# bring up containerd
printf "\nStarting containerd\n"
/usr/bin/containerd &
# wait for socket to be there
while [ ! -S /run/containerd/containerd.sock ]
do
sleep 0.1
done
# start onboot containers, run to completion
if [ -d /containers/onboot ]
then
for f in $(find /containers/onboot -mindepth 1 -maxdepth 1 | sort)
do
base="$(basename $f)"
#/bin/mount --bind "$f/rootfs" "$f/rootfs"
#mount -o remount,rw "$f/rootfs"
/usr/bin/runc run --bundle "$f" "$(basename $f)"
printf " - $base\n"
done
fi
# start service containers
if [ -d /containers/services ]
then
for f in $(find /containers/services -mindepth 1 -maxdepth 1 | sort)
do
base="$(basename $f)"
#/bin/mount --bind "$f/rootfs" "$f/rootfs"
#mount -o remount,rw "$f/rootfs"
log="/var/log/$base.log"
ctr run --runtime-config "$f/config.json" --rootfs "$f/rootfs" --id "$(basename $f)" </dev/null 2>$log >$log &
printf " - $base\n"
done
fi
wait