Move installable packages to pkg

Still leaves some intermediate repos in `base/`

See #1266

Signed-off-by: Justin Cormack <justin.cormack@docker.com>
This commit is contained in:
Justin Cormack
2017-03-22 12:33:11 +00:00
parent bd57bc034f
commit 1fb69b9bbf
36 changed files with 10 additions and 0 deletions

10
pkg/Makefile Normal file
View File

@@ -0,0 +1,10 @@
DIRS = $(shell find . -type d -depth 1)
.PHONY: clean dirs $(DIRS)
push: $(DIRS)
$(DIRS):
$(MAKE) -C $@
clean:
rm -f hash

4
pkg/binfmt/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
dev
proc
sys
usr

3
pkg/binfmt/Dockerfile Normal file
View File

@@ -0,0 +1,3 @@
FROM scratch
COPY . ./
CMD ["/usr/bin/binfmt", "-dir", "/etc/binfmt.d/", "-mount", "/binfmt_misc"]

52
pkg/binfmt/Makefile Normal file
View File

@@ -0,0 +1,52 @@
QEMU_IMAGE=mobylinux/qemu-user-static:da39a3ee5e6b4b0d3255bfef95601890afd80709@sha256:6c022f700dc6c263c9107c08aa29b4eae3b43b7b7594b7be3e421f69b51f53e5
QEMU_FILES=qemu-arm qemu-aarch64 qemu-ppc64le
QEMU_BINARIES=$(addprefix usr/bin/,$(QEMU_FILES))
GO_COMPILE=mobylinux/go-compile:3afebc59c5cde31024493c3f91e6102d584a30b9@sha256:e0786141ea7df8ba5735b63f2a24b4ade9eae5a02b0e04c4fca33b425ec69b0a
BINFMT_BINARY=usr/bin/binfmt
SHA_IMAGE=alpine:3.5@sha256:dfbd4a3a8ebca874ebd2474f044a0b33600d4523d03b0df76e5c5986cb02d7e8
IMAGE=binfmt
.PHONY: tag push clean container
default: push
$(QEMU_BINARIES):
mkdir -p $(dir $@)
docker run --rm --net=none $(QEMU_IMAGE) tar cf - $@ | tar xf -
$(BINFMT_BINARY): main.go
mkdir -p $(dir $@)
tar cf - $^ | docker run --rm --net=none --log-driver=none -i $(GO_COMPILE) -o $@ | tar xf -
DIRS=dev proc sys
$(DIRS):
mkdir -p $@
DEPS=$(DIRS) $(QEMU_BINARIES) $(BINFMT_BINARY) etc/binfmt.d/00_moby.conf
container: Dockerfile $(DEPS)
tar cf - $^ | docker build --no-cache -t $(IMAGE):build -
hash: Dockerfile $(DEPS)
find $^ -type f | xargs cat | docker run --rm -i $(SHA_IMAGE) sha1sum - | sed 's/ .*//' > hash
push: hash container
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 container
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 -rf hash $(DIRS) usr
.DELETE_ON_ERROR:

View File

@@ -0,0 +1,3 @@
: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\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\x00:/usr/bin/qemu-ppc64le:CF

93
pkg/binfmt/main.go Normal file
View File

@@ -0,0 +1,93 @@
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()
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
}
err = binfmt(line)
if err != nil {
log.Fatal(err)
}
}
}
}

38
pkg/docker-ce/Dockerfile Normal file
View File

@@ -0,0 +1,38 @@
FROM alpine:3.5
# Docker daemon only minimal Alpine install
# set up subuid/subgid so that "--userns-remap=default" works out-of-the-box
RUN set -x \
&& addgroup -S dockremap \
&& adduser -S -G dockremap dockremap \
&& echo 'dockremap:165536:65536' >> /etc/subuid \
&& echo 'dockremap:165536:65536' >> /etc/subgid
# https://github.com/docker/docker/blob/master/project/PACKAGERS.md#runtime-dependencies
RUN apk add --no-cache \
ca-certificates \
curl \
iptables \
xz
# removed xfsprogs e2fs btrfs as we do not support dm or btrfs yet
# removed openssl as I do not think server needs it
ENV DOCKER_BUCKET get.docker.com
ENV DOCKER_VERSION 17.03.0-ce
ENV DOCKER_SHA256 4a9766d99c6818b2d54dc302db3c9f7b352ad0a80a2dc179ec164a3ba29c2d3e
# we could avoid installing client here I suppose
RUN set -x \
&& curl -fSL "https://${DOCKER_BUCKET}/builds/Linux/x86_64/docker-${DOCKER_VERSION}.tgz" -o docker.tgz \
&& echo "${DOCKER_SHA256} *docker.tgz" | sha256sum -c - \
&& tar -xzvf docker.tgz \
&& mv docker/* /usr/bin/ \
&& rmdir docker \
&& rm docker.tgz \
&& docker -v
COPY . ./
ENTRYPOINT ["/usr/bin/docker-init", "/usr/bin/dockerd"]

29
pkg/docker-ce/Makefile Normal file
View File

@@ -0,0 +1,29 @@
.PHONY: tag push
BASE=alpine:3.5
IMAGE=docker-ce
default: push
hash: Dockerfile
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 $^ /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:

2
pkg/init/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
sbin/
usr/

12
pkg/init/Dockerfile Normal file
View File

@@ -0,0 +1,12 @@
FROM alpine:3.5
RUN \
apk --no-cache update && \
apk --no-cache upgrade -a && \
apk --no-cache add \
dhcpcd \
e2fsprogs \
e2fsprogs-extra \
&& rm -rf /var/cache/apk/*
COPY . ./

52
pkg/init/Makefile Normal file
View File

@@ -0,0 +1,52 @@
CONTAINERD_IMAGE=mobylinux/containerd:c9c8a069da6dccd2803ab476ee0d57a8768f0dcb@sha256:ff5aa0b1086e8c600d6e1508cfae4da31e4935d36ec40f0128aa73113b664e7f
CONTAINERD_BINARIES=usr/bin/containerd usr/bin/containerd-shim usr/bin/ctr usr/bin/dist
RUNC_IMAGE=mobylinux/runc:f1cee12a65e7b7de06a01aec24609dc3175e1542@sha256:ff1ead6aa4388418ee07f8e93304e5b2fa9b975fe2399474d408654a1411a44a
RUNC_BINARY=usr/bin/runc
C_COMPILE=mobylinux/c-compile:81a6bd8ff45d769b60a2ee1acdaccda11ab835c8@sha256:eac250997a3b9784d3285a03c0c8311d4ca6fb63dc75164c987411ba93006487
START_STOP_DAEMON=sbin/start-stop-daemon
default: push
$(RUNC_BINARY):
mkdir -p $(dir $@)
docker run --rm --net=none $(RUNC_IMAGE) tar cf - $@ | tar xf -
$(CONTAINERD_BINARIES):
mkdir -p $(dir $@)
docker run --rm --net=none $(CONTAINERD_IMAGE) tar cf - $@ | tar xf -
$(START_STOP_DAEMON): start-stop-daemon.c
mkdir -p $(dir $@)
tar cf - $^ | docker run --rm --net=none --log-driver=none -i $(C_COMPILE) -o $@ | tar xf -
.PHONY: tag push
BASE=alpine:3.5
IMAGE=init
ETC=$(shell find etc -type f)
hash: Dockerfile $(ETC) init $(RUNC_BINARY) $(CONTAINERD_BINARIES) $(START_STOP_DAEMON)
DOCKER_CONTENT_TRUST=1 docker pull $(BASE)
tar cf - $^ | docker build --no-cache -t $(IMAGE):build -
docker run --rm $(IMAGE):build sh -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 -rf hash sbin usr
.DELETE_ON_ERROR:

46
pkg/init/etc/dhcpcd.conf Normal file
View File

@@ -0,0 +1,46 @@
# Moby dhcpcd config
# Only configure standard external ethernet
allowinterfaces eth*
# Inform the DHCP server of our hostname for DDNS.
hostname
# Use the hardware address of the interface for the Client ID.
clientid
# or
# Use the same DUID + IAID as set in DHCPv6 for DHCPv4 ClientID as per RFC4361.
# Some non-RFC compliant DHCP servers do not reply with this set.
# In this case, comment out duid and enable clientid above.
#duid
# Persist interface configuration when dhcpcd exits.
persistent
# Rapid commit support.
# Safe to enable by default because it requires the equivalent option set
# on the server to actually work.
option rapid_commit
# A list of options to request from the DHCP server.
option domain_name_servers, domain_name, domain_search, host_name
option classless_static_routes
# Most distributions have NTP support.
option ntp_servers
# Respect the network MTU. This is applied to DHCP routes.
option interface_mtu
# A ServerID is required by RFC2131.
require dhcp_server_identifier
# Generate Stable Private IPv6 Addresses instead of hardware based ones
slaac private
# Do not wait
nodelay
# Do not arp to check IP
noarp
# Only fork when we have ipv4
# waitip 4

9
pkg/init/etc/init.d/containerd Executable file
View File

@@ -0,0 +1,9 @@
#!/bin/sh
# bring up containerd
ulimit -n 1048576
ulimit -p unlimited
printf "\nStarting containerd\n"
mkdir -p /var/log
/sbin/start-stop-daemon --start --exec /usr/bin/containerd

31
pkg/init/etc/init.d/containers Executable file
View File

@@ -0,0 +1,31 @@
#!/bin/sh
# TODO more robust
# while [ ! -S /run/containerd/containerd.sock ]; do sleep 1; done
# while ! ctr list 2> /dev/null; do sleep 1; done
# start system containers
# temporarily using runc not containerd
if [ -d /containers/system ]
then
for f in $(find /containers/system -mindepth 1 -maxdepth 1 | sort)
do
base="$(basename $f)"
/usr/bin/runc run --bundle "$f" "$(basename $f)"
printf " - $base\n"
done
fi
if [ -d /containers/daemon ]
then
for f in $(find /containers/daemon -mindepth 1 -maxdepth 1 | sort)
do
base="$(basename $f)"
log="/var/log/$base.log"
/sbin/start-stop-daemon --start --pidfile /run/$base.pid --exec /usr/bin/runc -- run --bundle "$f" --pid-file /run/$base.pid "$(basename $f)" </dev/null 2>$log >$log &
printf " - $base\n"
done
fi
wait

106
pkg/init/etc/init.d/rcS Executable file
View File

@@ -0,0 +1,106 @@
#!/bin/sh
# mount filesystems
mkdir -p -m 0755 /proc /run /tmp /sys /dev
mount -n -t proc proc /proc -o ndodev,nosuid,noexec,relatime
mount -n -t tmpfs tmpfs /run -o nodev,nosuid,noexec,relatime,size=10%,mode=755
mount -n -t tmpfs tmpfs /tmp -o nodev,nosuid,noexec,relatime,size=10%,mode=1777
# mount devfs
mount -n -t devtmpfs dev /dev -o nosuid,noexec,relatime,size=10m,nr_inodes=248418,mode=755
# devices
[ -c /dev/console ] || mknod -m 600 /dev/console c 5 1
[ -c /dev/tty1 ] || mknod -m 620 /dev/tty1 c 4 1
[ -c /dev/tty ] || mknod -m 666 /dev/tty c 5 0
[ -c /dev/null ] || mknod -m 666 /dev/null c 1 3
[ -c /dev/kmsg ] || mknod -m 660 /dev/kmsg c 1 11
# extra symbolic links not provided by default
[ -e /dev/fd ] || ln -snf /proc/self/fd /dev/fd
[ -e /dev/stdin ] || ln -snf /proc/self/fd/0 /dev/stdin
[ -e /dev/stdout ] || ln -snf /proc/self/fd/1 /dev/stdout
[ -e /dev/stderr ] || ln -snf /proc/self/fd/2 /dev/stderr
[ -e /proc/kcore ] && ln -snf /proc/kcore /dev/core
# devfs filesystems
mkdir -p -m 1777 /dev/mqueue
mkdir -p -m 1777 /dev/shm
mkdir -p -m 0755 /dev/pts
mount -n -t mqueue -o noexec,nosuid,nodev mqueue /dev/mqueue
mount -n -t tmpfs -o noexec,nosuid,nodev,mode=1777 shm /dev/shm
mount -n -t devpts -o noexec,nosuid,gid=5,mode=0620 devpts /dev/pts
# mount sysfs
sysfs_opts=nodev,noexec,nosuid
mount -n -t sysfs -o ${sysfs_opts} sysfs /sys
[ -d /sys/kernel/security ] && mount -n -t securityfs -o ${sysfs_opts} securityfs /sys/kernel/security
[ -d /sys/kernel/debug ] && mount -n -t debugfs -o ${sysfs_opts} debugfs /sys/kernel/debug
[ -d /sys/kernel/config ] && mount -n -t configfs -o ${sysfs_opts} configfs /sys/kernel/config
[ -d /sys/fs/fuse/connections ] && mount -n -t fusectl -o ${sysfs_opts} fusectl /sys/fs/fuse/connections
[ -d /sys/fs/selinux ] && mount -n -t selinuxfs -o nosuid,noexec selinuxfs /sys/fs/selinux
[ -d /sys/fs/pstore ] && mount -n -t pstore pstore -o ${sysfs_opts} /sys/fs/pstore
[ -d /sys/firmware/efi/efivars ] && mount -n -t efivarfs -o ro,${sysfs_opts} efivarfs /sys/firmware/efi/efivars
# misc /proc mounted fs
[ -d /proc/sys/fs/binfmt_misc ] && mount -t binfmt_misc -o nodev,noexec,nosuid binfmt_misc /proc/sys/fs/binfmt_misc
# mount cgroups
mount -n -t tmpfs -o nodev,noexec,nosuid,mode=755,size=10m cgroup_root /sys/fs/cgroup
while read name hier groups enabled rest
do
case "${enabled}" in
1) mkdir -p /sys/fs/cgroup/${name}
mount -n -t cgroup -o ${sysfs_opts},${name} ${name} /sys/fs/cgroup/${name}
;;
esac
done < /proc/cgroups
# for compatibility
mkdir -p /sys/fs/cgroup/systemd
mount -t cgroup -o none,name=systemd cgroup /sys/fs/cgroup/systemd
# set SELinux contexts
if [ -x /sbin/restorecon ]
then
restorecon -F /sys/devices/system/cpu/online >/dev/null 2>&1
restorecon -rF /sys/fs/cgroup >/dev/null 2>&1
restorecon -rF /dev >/dev/null 2>&1
fi
# start mdev for hotplug
echo "/sbin/mdev" > /proc/sys/kernel/hotplug
# mdev -s will not create /dev/usb[1-9] devices with recent kernels
# so we trigger hotplug events for usb for now
for i in $(find /sys/devices -name 'usb[0-9]*'); do
[ -e $i/uevent ] && echo add > $i/uevent
done
mdev -s
# set hostname
if [ -s /etc/hostname ]
then
hostname -F /etc/hostname
fi
if [ $(hostname) = "moby" -a -f /sys/class/net/eth0/address ]
then
mac=$(cat /sys/class/net/eth0/address)
hostname moby-$(echo $mac | sed 's/://g')
fi
# set system clock from hwclock
hwclock --hctosys --utc
# bring up loopback interface
ip addr add 127.0.0.1/8 dev lo brd + scope host
ip route add 127.0.0.0/8 dev lo scope host
ip link set lo up
# will be containerised
/sbin/dhcpcd

15
pkg/init/etc/inittab Normal file
View File

@@ -0,0 +1,15 @@
# /etc/inittab
::sysinit:/etc/init.d/rcS
::once:/etc/init.d/containerd
::once:/etc/init.d/containers
# Stuff to do for the 3-finger salute
::ctrlaltdel:/sbin/reboot
# Stuff to do before rebooting
::shutdown:/usr/sbin/killall5 -15
::shutdown:/bin/sleep 5
::shutdown:/usr/sbin/killall5 -9
::shutdown:/bin/echo "Unmounting filesystems"
::shutdown:/bin/umount -a -r

12
pkg/init/etc/issue Normal file
View File

@@ -0,0 +1,12 @@
Welcome to Moby
## .
## ## ## ==
## ## ## ## ## ===
/"""""""""""""""""\___/ ===
~~~ {~~ ~~~~ ~~~ ~~~~ ~~~ ~ / ===- ~~~
\______ o __/
\ \ __/
\____\_______/

44
pkg/init/init Executable file
View File

@@ -0,0 +1,44 @@
#!/bin/sh
setup_console() {
tty=${1%,*}
speed=${1#*,}
inittab="$2"
securetty="$3"
line=
term="linux"
[ "$speed" = "$1" ] && speed=115200
case "$tty" in
ttyS*|ttyAMA*|ttyUSB*|ttyMFD*)
line="-L"
term="vt100"
;;
tty0)
# skip current console
return 0
;;
esac
# skip consoles already in inittab
grep -q "^$tty:" "$inittab" && return
echo "$tty::once:cat /etc/issue" >> "$inittab"
echo "$tty::respawn:/sbin/getty -n -l /bin/sh $line $speed $tty $term" >> "$inittab"
if ! grep -q -w "$tty" "$securetty"; then
echo "$tty" >> "$securetty"
fi
}
/bin/mount -t tmpfs tmpfs /mnt
/bin/cp -a / /mnt 2>/dev/null
/bin/mount -t proc -o noexec,nosuid,nodev proc /proc
for opt in $(cat /proc/cmdline); do
case "$opt" in
console=*)
setup_console ${opt#console=} /mnt/etc/inittab /mnt/etc/securetty;;
esac
done
exec /bin/busybox switch_root /mnt /sbin/init

1054
pkg/init/start-stop-daemon.c Normal file

File diff suppressed because it is too large Load Diff

4
pkg/metadata-gcp/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
dev
proc
sys
usr

View File

@@ -0,0 +1,3 @@
FROM scratch
COPY . ./
CMD ["/usr/bin/metadata-gcp"]

44
pkg/metadata-gcp/Makefile Normal file
View File

@@ -0,0 +1,44 @@
GO_COMPILE=mobylinux/go-compile:3afebc59c5cde31024493c3f91e6102d584a30b9@sha256:e0786141ea7df8ba5735b63f2a24b4ade9eae5a02b0e04c4fca33b425ec69b0a
SHA_IMAGE=alpine:3.5@sha256:dfbd4a3a8ebca874ebd2474f044a0b33600d4523d03b0df76e5c5986cb02d7e8
METADATA_BINARY=usr/bin/metadata-gcp
IMAGE=metadata-gcp
.PHONY: tag push clean container
default: push
$(METADATA_BINARY): gcp.go
mkdir -p $(dir $@)
tar cf - $^ | docker run --rm --net=none --log-driver=none -i $(GO_COMPILE) -o $@ | tar xf -
DIRS=dev proc sys
$(DIRS):
mkdir -p $@
DEPS=$(DIRS) $(METADATA_BINARY)
container: Dockerfile $(DEPS)
tar cf - $^ | docker build --no-cache -t $(IMAGE):build -
hash: Dockerfile $(DEPS)
find $^ -type f | xargs cat | docker run --rm -i $(SHA_IMAGE) sha1sum - | sed 's/ .*//' > hash
push: hash container
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 container
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 -rf hash $(DIRS) usr
.DELETE_ON_ERROR:

75
pkg/metadata-gcp/gcp.go Normal file
View File

@@ -0,0 +1,75 @@
package main
import (
"io/ioutil"
"log"
"net/http"
"strings"
"syscall"
"time"
)
const (
project = "http://metadata.google.internal/computeMetadata/v1/project/"
instance = "http://metadata.google.internal/computeMetadata/v1/instance/"
)
// If optional not set, will panic. Optional will allow 404
// We assume most failure cases are that this code is included in a non Google Cloud
// environment, which should generally be ok, so just fail fast.
func metadata(url string, optional bool) []byte {
var client = &http.Client{
Timeout: time.Second * 2,
}
req, err := http.NewRequest("", url, nil)
if err != nil {
log.Fatalf("http NewRequest failed: %v", err)
}
req.Header.Set("Metadata-Flavor", "Google")
resp, err := client.Do(req)
if err != nil {
// Probably not running on Google Cloud but this package included
log.Fatalf("Could not contact Google Cloud Metadata service: %v", err)
}
if optional && resp.StatusCode == 404 {
return []byte{}
}
if resp.StatusCode != 200 {
// Probably not running on Google Cloud but this package included
log.Fatalf("Google Cloud Metadata Server http error: %s", resp.Status)
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatalf("Failed to read http response: %v", err)
}
return body
}
func main() {
hostname := metadata(instance+"hostname", false)
err := syscall.Sethostname(hostname)
if err != nil {
log.Printf("Failed to set hostname: %v", err)
}
sshKeys := metadata(project+"attributes/sshKeys", true)
// TODO also retrieve the instance keys and respect block project keys see https://cloud.google.com/compute/docs/instances/ssh-keys
// the keys have usernames attached, but as a simplification we are going to add them all to one root file
// TODO split them into individual user files and make the ssh container construct those users
rootKeys := ""
for _, line := range strings.Split(string(sshKeys), "\n") {
parts := strings.SplitN(line, ":", 2)
// ignoring username for now
if len(parts) == 2 {
rootKeys = rootKeys + parts[1] + "\n"
}
}
err = ioutil.WriteFile("/etc/ssh/authorized_keys", []byte(rootKeys), 0600)
if err != nil {
log.Printf("Failed to write ssh keys: %v", err)
}
}

5
pkg/rngd/.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
bin
dev
proc
sys
usr

3
pkg/rngd/Dockerfile Normal file
View File

@@ -0,0 +1,3 @@
FROM scratch
COPY . ./
CMD ["/bin/tini", "/usr/sbin/rngd", "-f"]

50
pkg/rngd/Makefile Normal file
View File

@@ -0,0 +1,50 @@
RNG_TOOLS_IMAGE=mobylinux/rng-tools:b6aed437bad8f1f4471b11f1affe3420eaf5d42f@sha256:8e74e6a39b072ebee65ee4b83ebf224787afb473ea250c897dd24fa43b387d06
RNGD_BINARY=usr/sbin/rngd
TINI_IMAGE=mobylinux/tini:6b25b62f4d893de8721fd2581411039b17e8a253@sha256:39b4a459018ffc155a9fcbbf952fa625c77f5a8d7599b326eade529d3dc723fc
TINI_BINARY=bin/tini
.PHONY: tag push clean container
default: push
$(TINI_BINARY):
mkdir -p $(dir $@)
docker run --rm --net=none $(TINI_IMAGE) tar cf - $@ | tar xf -
$(RNGD_BINARY):
mkdir -p $(dir $@)
docker run --rm --net=none $(RNG_TOOLS_IMAGE) tar cf - $@ | tar xf -
SHA_IMAGE=alpine:3.5@sha256:dfbd4a3a8ebca874ebd2474f044a0b33600d4523d03b0df76e5c5986cb02d7e8
IMAGE=rngd
DIRS=dev proc sys
$(DIRS):
mkdir -p $@
DEPS=$(DIRS) $(TINI_BINARY) $(RNGD_BINARY)
container: Dockerfile $(DEPS)
tar cf - $^ | docker build --no-cache -t $(IMAGE):build -
hash: Dockerfile $(DEPS)
find $^ -type f | xargs cat | docker run --rm -i $(SHA_IMAGE) sha1sum - | sed 's/ .*//' > hash
push: hash container
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 container
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 -rf hash $(DIRS) usr bin
.DELETE_ON_ERROR:

14
pkg/sshd/Dockerfile Normal file
View File

@@ -0,0 +1,14 @@
FROM alpine:edge
RUN \
apk update && apk upgrade && \
apk add --no-cache \
openssh-server \
tini \
&& true
COPY . .
RUN mkdir -p /etc/ssh /root/.ssh && chmod 0700 /root/.ssh
CMD ["/sbin/tini", "/usr/bin/ssh.sh"]

29
pkg/sshd/Makefile Normal file
View File

@@ -0,0 +1,29 @@
.PHONY: tag push
BASE=alpine:edge
IMAGE=sshd
default: push
hash: Dockerfile etc/ssh/sshd_config usr/bin/ssh.sh etc/motd
DOCKER_CONTENT_TRUST=1 docker pull $(BASE)
tar cf - $^ | docker build --no-cache -t $(IMAGE):build -
docker run --rm $(IMAGE):build sh -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:

1
pkg/sshd/etc/motd Normal file
View File

@@ -0,0 +1 @@
Welcome to Moby

View File

@@ -0,0 +1,144 @@
# $OpenBSD: sshd_config,v 1.98 2016/02/17 05:29:04 djm Exp $
# This is the sshd server system-wide configuration file. See
# sshd_config(5) for more information.
# This sshd was compiled with PATH=/bin:/usr/bin:/sbin:/usr/sbin
# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented. Uncommented options override the
# default value.
#Port 22
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::
# The default requires explicit activation of protocol 1
#Protocol 2
# HostKey for protocol version 1
#HostKey /etc/ssh/ssh_host_key
# HostKeys for protocol version 2
#HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_dsa_key
#HostKey /etc/ssh/ssh_host_ecdsa_key
#HostKey /etc/ssh/ssh_host_ed25519_key
# Lifetime and size of ephemeral version 1 server key
#KeyRegenerationInterval 1h
#ServerKeyBits 1024
# Ciphers and keying
#RekeyLimit default none
# Logging
# obsoletes QuietMode and FascistLogging
#SyslogFacility AUTH
#LogLevel INFO
# Authentication:
#LoginGraceTime 2m
#PermitRootLogin prohibit-password
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10
#RSAAuthentication yes
#PubkeyAuthentication yes
# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
# but this is overridden so installations will only check .ssh/authorized_keys
AuthorizedKeysFile .ssh/authorized_keys
#AuthorizedPrincipalsFile none
#AuthorizedKeysCommand none
#AuthorizedKeysCommandUser nobody
# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
#RhostsRSAAuthentication no
# similar for protocol version 2
#HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
# RhostsRSAAuthentication and HostbasedAuthentication
#IgnoreUserKnownHosts no
# Don't read the user's ~/.rhosts and ~/.shosts files
#IgnoreRhosts yes
# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication no
#PermitEmptyPasswords no
# Change to no to disable s/key passwords
ChallengeResponseAuthentication no
# Kerberos options
#KerberosAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
#KerberosGetAFSToken no
# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes
# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the ChallengeResponseAuthentication and
# PasswordAuthentication. Depending on your PAM configuration,
# PAM authentication via ChallengeResponseAuthentication may bypass
# the setting of "PermitRootLogin without-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
#UsePAM no
#AllowAgentForwarding yes
#AllowTcpForwarding yes
#GatewayPorts no
#X11Forwarding no
#X11DisplayOffset 10
#X11UseLocalhost yes
#PermitTTY yes
#PrintMotd yes
#PrintLastLog yes
#TCPKeepAlive yes
#UseLogin no
#UsePrivilegeSeparation sandbox
#PermitUserEnvironment no
#Compression delayed
#ClientAliveInterval 0
#ClientAliveCountMax 3
#UseDNS no
#PidFile /run/sshd.pid
#MaxStartups 10:30:100
#PermitTunnel no
#ChrootDirectory none
#VersionAddendum none
# no default banner path
#Banner none
# Default of no subsystems
#Subsystem sftp /usr/lib/ssh/sftp-server
# the following are HPN related configuration options
# tcp receive buffer polling. disable in non autotuning kernels
#TcpRcvBufPoll yes
# disable hpn performance boosts
#HPNDisabled no
# buffer size for hpn to non-hpn connections
#HPNBufferSize 2048
# Example of overriding settings on a per-user basis
#Match User anoncvs
# X11Forwarding no
# AllowTcpForwarding no
# PermitTTY no
# ForceCommand cvs server

6
pkg/sshd/usr/bin/ssh.sh Executable file
View File

@@ -0,0 +1,6 @@
#!/bin/sh
KEYS=$(find /etc/ssh -name 'ssh_host_*_key')
[ -z "$KEYS" ] && ssh-keygen -A >/dev/null 2>/dev/null
exec /usr/sbin/sshd -D -e

4
pkg/sysctl/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
dev
proc
sys
usr

3
pkg/sysctl/Dockerfile Normal file
View File

@@ -0,0 +1,3 @@
FROM scratch
COPY . ./
CMD ["/usr/bin/sysctl"]

44
pkg/sysctl/Makefile Normal file
View File

@@ -0,0 +1,44 @@
GO_COMPILE=mobylinux/go-compile:3afebc59c5cde31024493c3f91e6102d584a30b9@sha256:e0786141ea7df8ba5735b63f2a24b4ade9eae5a02b0e04c4fca33b425ec69b0a
SHA_IMAGE=alpine:3.5@sha256:dfbd4a3a8ebca874ebd2474f044a0b33600d4523d03b0df76e5c5986cb02d7e8
SYSCTL_BINARY=usr/bin/sysctl
IMAGE=sysctl
.PHONY: tag push clean container
default: push
$(SYSCTL_BINARY): main.go
mkdir -p $(dir $@)
tar cf - $^ | docker run --rm --net=none --log-driver=none -i $(GO_COMPILE) -o $@ | tar xf -
DIRS=dev proc sys
$(DIRS):
mkdir -p $@
DEPS=$(DIRS) $(SYSCTL_BINARY) etc/sysctl.d/00-moby.conf
container: Dockerfile $(DEPS)
tar cf - $^ | docker build --no-cache -t $(IMAGE):build -
hash: Dockerfile $(DEPS)
find $^ -type f | xargs cat | docker run --rm -i $(SHA_IMAGE) sha1sum - | sed 's/ .*//' > hash
push: hash container
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 container
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 -rf hash $(DIRS) usr
.DELETE_ON_ERROR:

View File

@@ -0,0 +1,27 @@
# from Alpine defaults
net.ipv4.tcp_syncookies = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.ping_group_range=999 59999
# general limits
vm.max_map_count = 262144
vm.overcommit_memory = 1
net.core.somaxconn = 1024
net.ipv4.neigh.default.gc_thresh1 = 30000
net.ipv4.neigh.default.gc_thresh2 = 32000
net.ipv4.neigh.default.gc_thresh3 = 32768
fs.aio-max-nr = 1048576
fs.inotify.max_user_watches = 524288
fs.file-max = 524288
# for rngd
kernel.random.write_wakeup_threshold = 3072
# security restrictions
kernel.kptr_restrict = 2
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0
kernel.perf_event_paranoid = 3
fs.protected_hardlinks = 1
fs.protected_symlinks = 1

72
pkg/sysctl/main.go Normal file
View File

@@ -0,0 +1,72 @@
package main
import (
"bytes"
"flag"
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
)
var (
configDir string
sysctlDir string
)
func init() {
flag.StringVar(&configDir, "configDir", "/etc/sysctl.d", "directory with config files")
flag.StringVar(&sysctlDir, "sysctlDir", "/proc/sys", "mount point for sysctls")
}
func sysctl(line []byte) error {
// parse line into a string of expected form X.Y.Z=VALUE
sysctlLineKV := strings.Split(string(line[:]), "=")
if len(sysctlLineKV) != 2 {
if len(sysctlLineKV) >= 1 && len(sysctlLineKV[0]) >= 1 && strings.Trim(sysctlLineKV[0], " ")[:1] == "#" {
return nil
}
return fmt.Errorf("Cannot parse %s", string(line))
}
// trim any extra whitespace
sysctlSetting, sysctlValue := strings.Trim(sysctlLineKV[0], " "), strings.Trim(sysctlLineKV[1], " ")
sysctlFile := filepath.Join(sysctlDir, filepath.Join(strings.Split(sysctlSetting, ".")...))
file, err := os.OpenFile(sysctlFile, os.O_WRONLY, 0)
if err != nil {
return fmt.Errorf("Cannot open %s: %s", sysctlFile, err)
}
defer file.Close()
_, err = file.Write([]byte(sysctlValue))
if err != nil {
return fmt.Errorf("Cannot write to %s: %s", sysctlFile, err)
}
return nil
}
func main() {
flag.Parse()
files, err := ioutil.ReadDir(configDir)
if err != nil {
log.Fatalf("Cannot read directory %s: %s", configDir, err)
}
for _, file := range files {
contents, err := ioutil.ReadFile(filepath.Join(configDir, 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
}
err = sysctl(line)
if err != nil {
log.Fatal(err)
}
}
}
}