├── .gitignore ├── LICENSE ├── README.md ├── bin ├── docker-wrapper ├── dockerd-wrapper └── help ├── build-static-bins.sh ├── patches ├── snappy-aa-profile-reload.patch ├── snappy-apparmor-tweaks.patch ├── snappy-docker-certs-d.patch ├── snappy-etc-apparmor-d.patch ├── snappy-etc-docker.patch ├── snappy-real-chroot.patch └── snappy-socket-group.patch ├── prep-docker-build.sh ├── registry-example.md └── snap ├── plugins ├── x-gobuild.py ├── x-gobuild.yaml └── x-shell.py └── snapcraft.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | *.snap 2 | /parts 3 | /prime 4 | /stage 5 | /snap/plugins/__pycache__/ 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Canonical Ltd. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included 12 | in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Docker Snap 2 | 3 | :lock: This repository has been archived. 4 | 5 | > *NOTE:* The Docker Snap is no longer maintained by Docker, Inc. The last 6 | > release version was 17.06.2. The future of the Docker Snap is unclear, but it 7 | > won't be developed here going forward. The source at 8 | > https://code.launchpad.net/~docker/+git/snap appears to be where new 9 | > development efforts are taking place, and the Snapcraft forums 10 | > (https://forum.snapcraft.io/) are probably your best bet to reach the new 11 | > maintainers. 12 | 13 | --- 14 | 15 | This repository contains the source for the `docker` snap package. The package provides a distribution of Docker Community Edition (CE) for Ubuntu Core 16 (and other snap-compatible) systems. It is built from an upstream Docker CE release tag with some patches to fit the snap format and is available on `armhf`, `arm64`, `amd64`, `i386`, and `ppc64el` architectures. The rest of this page describes installation, usage, and development. 16 | 17 | ## Installation 18 | 19 | To install the latest stable release of Docker CE using `snap`: 20 | 21 | $ sudo snap install docker 22 | 23 | 24 | If you are using Ubuntu Core 16, 25 | 26 | * Connect the `docker:home` plug as it's not auto-connected by default: 27 | 28 | $ sudo snap connect docker:home 29 | 30 | If you are using an alternative snap-compatible Linux distribution ("classic" in snap lingo), and would like to run `docker` as a normal user: 31 | 32 | * Create and join the `docker` group. 33 | 34 | $ sudo addgroup --system docker 35 | $ sudo adduser $USER docker 36 | $ newgrp docker 37 | 38 | * You will also need to disable and re-enable the `docker` snap if you added the group while it was running. 39 | 40 | $ sudo snap disable docker 41 | $ sudo snap enable docker 42 | 43 | ## Usage 44 | 45 | Docker should function normally, with the following caveats: 46 | 47 | * All files that `docker` needs access to should live within your `$HOME` folder. 48 | 49 | * If you are using Ubuntu Core 16, you'll need to work within a subfolder of `$HOME` that is readable by root. https://github.com/docker/docker-snap/issues/8 50 | 51 | * `docker-compose` is available as `docker.compose` due to snap naming restrictions. 52 | * Additional certificates used by the Docker daemon to authenticate with registries need to be located in `/var/snap/docker/common/etc/certs.d` instead of `/etc/docker/certs.d`. 53 | 54 | ### Examples 55 | 56 | * [Setup a secure private registry](registry-example.md) 57 | 58 | ## Development 59 | 60 | Developing the `docker` snap package is typically performed on a "classic" Ubuntu distribution. The instructions here are written for Ubuntu 16.04 "Xenial". 61 | 62 | * Install the snap tooling (requires `snapd>2.21` and `snapcraft>=2.26`): 63 | 64 | $ sudo apt-get install snapd snapcraft 65 | $ sudo snap install core 66 | 67 | * Checkout this repository and build the `docker` snap package: 68 | 69 | $ git clone https://github.com/docker/docker-snap 70 | $ cd docker-snap 71 | $ sudo snapcraft 72 | 73 | * Install the newly-created snap package: 74 | 75 | $ sudo snap install --dangerous docker_[VER]_[ARCH].snap 76 | 77 | * Manually connect the relevant plugs and slots which are not auto-connected: 78 | 79 | $ sudo snap connect docker:privileged :docker-support 80 | $ sudo snap connect docker:support :docker-support 81 | $ sudo snap connect docker:firewall-control :firewall-control 82 | $ sudo snap connect docker:docker-cli docker:docker-daemon 83 | $ sudo snap disable docker 84 | $ sudo snap enable docker 85 | 86 | You should end up with output similar to: 87 | 88 | $ sudo snap interfaces docker 89 | Slot Plug 90 | :docker-support docker:privileged,docker:support 91 | :firewall-control docker 92 | :home docker 93 | :network docker 94 | :network-bind docker 95 | docker:docker-daemon docker:docker-cli 96 | -------------------------------------------------------------------------------- /bin/docker-wrapper: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | # TODO ditch this special casing 5 | # "plugin: python2" is setting /usr/bin/docker-compose's shebang thus: 6 | # #!/build/docker/parts/compose/install/usr/bin/python2 7 | # https://github.com/snapcore/snapcraft/pull/680 8 | if [ "$1" = 'docker-compose' ]; then 9 | cmd="$1" 10 | shift 11 | set -- python2 "$(which "$cmd")" "$@" 12 | fi 13 | 14 | exec "$@" 15 | -------------------------------------------------------------------------------- /bin/dockerd-wrapper: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | default_socket_group=docker 5 | 6 | aa_profile_reloaded="$SNAP_COMMON/profile_reloaded" 7 | 8 | workaround_apparmor_profile_reload() { 9 | #https://github.com/docker/docker-snap/issues/4 10 | if [ ! -f "$aa_profile_refreshed" ]; then 11 | if [ "$(grep -c 'docker-default (enforce)' /sys/kernel/security/apparmor/profiles)" -ge 1 ]; then 12 | export DOCKER_AA_RELOAD=1 13 | touch $aa_profile_reloaded 14 | fi 15 | fi 16 | } 17 | 18 | workaround_lp1626019() { 19 | t=`egrep '/snap\.\w+_snap\.docker.dockerd_\w+/tmp ' /proc/self/mountinfo | cut -d ' ' -f 5` 20 | if [ -n "$t" ] && [ ! -e "$t" ]; then 21 | mkdir -p "$t" 22 | ln -s /sys "$t"/sys 23 | fi 24 | } 25 | 26 | workaround_lp1606510() { 27 | # ensure there's at least one member in the group. 28 | if [ $(getent group docker-snap | awk -F':' '{print $NF}') ]; then 29 | default_socket_group=docker-snap 30 | fi 31 | } 32 | 33 | yolo() { 34 | "$@" > /dev/null 2>&1 || : 35 | } 36 | 37 | force_umount() { 38 | yolo umount "$@" 39 | yolo umount -f "$@" 40 | yolo umount -l "$@" 41 | } 42 | 43 | dir="$(mktemp -d)" 44 | trap "force_umount --no-mtab '$dir'; rm -rf '$dir'" EXIT 45 | # try mounting a few FS types to force the kernel to try loading modules 46 | for t in aufs overlay zfs; do 47 | yolo mount --no-mtab -t "$t" /dev/null "$dir" 48 | force_umount --no-mtab "$dir" 49 | done 50 | # inside our snap, we can't "modprobe" for whatever reason (probably no access to the .ko files) 51 | # so this forces the kernel itself to "modprobe" for these filesystems so that the modules we need are available to Docker 52 | rm -rf "$dir" 53 | trap - EXIT 54 | 55 | # use SNAP_DATA for most "data" bits 56 | mkdir -p \ 57 | "$SNAP_DATA/run" \ 58 | "$SNAP_DATA/run/docker" \ 59 | "$SNAP_COMMON/var-lib-docker" 60 | set -- \ 61 | --debug \ 62 | --log-level=debug \ 63 | \ 64 | --exec-root="$SNAP_DATA/run/docker" \ 65 | --graph="$SNAP_COMMON/var-lib-docker" \ 66 | --pidfile="$SNAP_DATA/run/docker.pid" \ 67 | \ 68 | "$@" 69 | 70 | workaround_lp1626019 71 | 72 | workaround_lp1606510 73 | 74 | workaround_apparmor_profile_reload 75 | 76 | exec dockerd -G $default_socket_group "$@" 77 | -------------------------------------------------------------------------------- /bin/help: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cat <<'EOF' 4 | Docker snap: Docker Linux container runtime. 5 | 6 | Due to the confinement issues on snappy, it requires some manual setup to make docker-snap works on your machine. 7 | We'll take you through the steps needed to set up docker snap work for you on ubuntu core and ubuntu classic. 8 | 9 | On Ubuntu classic, before installing the docker snap, 10 | please run the following command to add the login user into docker group. 11 | sudo addgroup --system docker 12 | sudo adduser $USER docker 13 | newgrp docker 14 | 15 | On Ubuntu Core 16, after installing the docker snap from store, 16 | you need to connect the home interface as it's not auto-connected by default. 17 | sudo snap connect docker:home :home 18 | 19 | Then have fun with docker in snappy. 20 | 21 | EOF 22 | -------------------------------------------------------------------------------- /build-static-bins.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | cd "$(dirname "$(readlink -f "$BASH_SOURCE")")" 5 | 6 | targetDir="$PWD/static-bins" 7 | 8 | # usage: $0 part [part ...] 9 | # ie: $0 docker 10 | if [ "$#" -lt 1 ]; then 11 | set -- docker containerd runc compose 12 | rm -rf "$targetDir" # if we're building all three, let's do it clean 13 | fi 14 | parts=( "$@" ) 15 | 16 | mkdir -p "$targetDir" 17 | 18 | # make an easy lookup table 19 | declare -A wantPart=() 20 | for part; do 21 | wantPart[$part]=1 22 | done 23 | 24 | [ -z "${wantPart[docker]}" ] || ( set -x && snapcraft clean --step pull docker ) 25 | ( set -x && snapcraft pull "${parts[@]}" ) 26 | 27 | export SNAPDIR="$PWD" 28 | 29 | if [ "${wantPart[docker]}" ]; then 30 | ( 31 | cd parts/docker/src 32 | 33 | source "$SNAPDIR/prep-docker-build.sh" 34 | 35 | # devicemapper and static builds don't get along well 36 | export DOCKER_BUILDTAGS="$DOCKER_BUILDTAGS exclude_graphdriver_devicemapper" 37 | ( set -x && ./hack/make.sh binary ) 38 | 39 | dockerBin='bundles/latest/binary/docker' 40 | ( set -x && "$dockerBin" -v ) 41 | "$dockerBin" -v | grep -q "$DOCKER_GITCOMMIT" 42 | 43 | install -T "$(readlink -f "$dockerBin")" "$targetDir/docker" 44 | ) 45 | fi 46 | 47 | if [ "${wantPart[containerd]}" ]; then 48 | ( 49 | cd parts/containerd/src 50 | 51 | mkdir -p .gopath/src/github.com/docker 52 | ln -sfT "$PWD" .gopath/src/github.com/docker/containerd 53 | export GOPATH="$PWD/.gopath" 54 | 55 | ( set -x && make static GIT_COMMIT= GIT_BRANCH= LDFLAGS= ) 56 | 57 | ( set -x && bin/containerd -v ) 58 | 59 | install -T bin/containerd "$targetDir/docker-containerd" 60 | install -T bin/containerd-shim "$targetDir/docker-containerd-shim" 61 | install -T bin/ctr "$targetDir/docker-containerd-ctr" 62 | ) 63 | fi 64 | 65 | if [ "${wantPart[runc]}" ]; then 66 | ( 67 | cd parts/runc/src 68 | 69 | mkdir -p .gopath/src/github.com/opencontainers 70 | ln -sfT "$PWD" .gopath/src/github.com/opencontainers/runc 71 | export GOPATH="$PWD/.gopath" 72 | 73 | ( set -x && make static BUILDTAGS='seccomp apparmor selinux' COMMIT= ) 74 | 75 | ( set -x && ./runc -v ) 76 | 77 | install -T runc "$targetDir/docker-runc" 78 | ) 79 | fi 80 | 81 | if [ "${wantPart[compose]}" ]; then 82 | ( 83 | cd parts/compose/src 84 | 85 | baseImage='python:2.7-slim' 86 | case "$(dpkg --print-architecture)" in 87 | armhf) baseImage="armhf/$baseImage" ;; 88 | amd64) ;; 89 | *) echo >&2 "error: unknown architecture"; exit 1 ;; 90 | esac 91 | 92 | composeBuild='docker-snap' 93 | if git rev-parse &> /dev/null; then 94 | composeBuild+="-$(git rev-parse --short HEAD)" 95 | fi 96 | 97 | # && pip install pyinstaller \ 98 | # we have to pull pyinstaller from a newer commit than 3.2 so that it both builds our bootloader on armhf and doesn't run into https://github.com/pyinstaller/pyinstaller/issues/1976 99 | cat > Dockerfile.static <<-EOF 100 | FROM $baseImage 101 | 102 | WORKDIR /usr/src/compose 103 | 104 | #COPY requirements-build.txt ./ 105 | #RUN pip install -r requirements-build.txt 106 | RUN set -ex \ 107 | && buildDeps=' \ 108 | gcc \ 109 | libc6-dev \ 110 | zlib1g-dev \ 111 | ' \ 112 | && runDeps=' \ 113 | binutils \ 114 | upx-ucl \ 115 | ' \ 116 | && apt-get update \ 117 | && apt-get install -y --no-install-recommends \$buildDeps \$runDeps \ 118 | && rm -rf /var/lib/apt/lists/* \ 119 | && pip install https://github.com/pyinstaller/pyinstaller/archive/501ad40fd22b2fca8cfee7652791323f5fd1754d.tar.gz \ 120 | && apt-get purge -y --auto-remove \$buildDeps 121 | 122 | COPY requirements.txt ./ 123 | RUN pip install -r requirements.txt 124 | 125 | COPY . . 126 | RUN pip install --no-deps . 127 | 128 | RUN echo '$composeBuild' > compose/GITSHA 129 | RUN pyinstaller docker-compose.spec 130 | EOF 131 | 132 | docker build -t snap-docker:static-compose -f Dockerfile.static . 133 | docker run -i --rm snap-docker:static-compose cat dist/docker-compose > "$targetDir/docker-compose" 134 | chmod +x "$targetDir/docker-compose" 135 | 136 | "$targetDir/docker-compose" --version 137 | ) 138 | fi 139 | -------------------------------------------------------------------------------- /patches/snappy-aa-profile-reload.patch: -------------------------------------------------------------------------------- 1 | diff --git a/daemon/apparmor_default.go b/daemon/apparmor_default.go 2 | index 2a418b2..278f320 100644 3 | --- a/daemon/apparmor_default.go 4 | +++ b/daemon/apparmor_default.go 5 | @@ -4,6 +4,7 @@ package daemon 6 | 7 | import ( 8 | "fmt" 9 | + "os" 10 | 11 | aaprofile "github.com/docker/docker/profiles/apparmor" 12 | "github.com/opencontainers/runc/libcontainer/apparmor" 13 | @@ -22,7 +23,7 @@ func ensureDefaultAppArmorProfile() error { 14 | } 15 | 16 | // Nothing to do. 17 | - if loaded { 18 | + if loaded && (os.Getenv("DOCKER_AA_RELOAD") == "" || os.Getenv("DOCKER_AA_RELOAD") == "0") { 19 | return nil 20 | } 21 | 22 | -------------------------------------------------------------------------------- /patches/snappy-apparmor-tweaks.patch: -------------------------------------------------------------------------------- 1 | diff --git a/profiles/apparmor/template.go b/profiles/apparmor/template.go 2 | index ada33bf..39d3525 100644 3 | --- a/profiles/apparmor/template.go 4 | +++ b/profiles/apparmor/template.go 5 | @@ -42,5 +42,16 @@ profile {{.Name}} flags=(attach_disconnected,mediate_deleted) { 6 | # suppress ptrace denials when using 'docker ps' or using 'ps' inside a container 7 | ptrace (trace,read) peer=docker-default, 8 | {{end}} 9 | + 10 | + # Ubuntu Snappy 15.04 tweaks 11 | + # Allow the daemon to trace/signal containers 12 | + ptrace (readby, tracedby) peer="docker_docker{,-daemon}_*", 13 | + signal (receive) peer="docker_docker{,-daemon}_*", 14 | + # Ubuntu Snappy 16-series tweaks 15 | + # Allow the daemon to trace/signal containers 16 | + ptrace (readby, tracedby) peer="snap.docker.dockerd", 17 | + signal (receive) peer="snap.docker.dockerd", 18 | + # Allow container processes to signal other container processes 19 | + signal (send, receive) peer=docker-default, 20 | } 21 | ` 22 | -------------------------------------------------------------------------------- /patches/snappy-docker-certs-d.patch: -------------------------------------------------------------------------------- 1 | diff --git a/registry/config_unix.go b/registry/config_unix.go 2 | index d692e8e..5219c1d 100644 3 | --- a/registry/config_unix.go 4 | +++ b/registry/config_unix.go 5 | @@ -3,14 +3,29 @@ 6 | package registry 7 | 8 | import ( 9 | + "os" 10 | + 11 | "github.com/spf13/pflag" 12 | ) 13 | 14 | var ( 15 | // CertsDir is the directory where certificates are stored 16 | - CertsDir = "/etc/docker/certs.d" 17 | + CertsDir = defaultCertificatesDirectory() 18 | ) 19 | 20 | +func defaultCertificatesDirectory() string { 21 | + // Ubuntu Snappy has read-only /etc 22 | + if snapCommon := os.Getenv("SNAP_COMMON"); snapCommon != "" { 23 | + // Ubuntu Snappy 16.04+ 24 | + return snapCommon + "/etc/certs.d" 25 | + } else if snapAppDataPath := os.Getenv("SNAP_APP_DATA_PATH"); snapAppDataPath != "" { 26 | + // Ubuntu Snappy 15.04 27 | + return snapAppDataPath + "/etc/certs.d" 28 | + } 29 | + 30 | + return "/etc/docker/certs.d" 31 | +} 32 | + 33 | // cleanPath is used to ensure that a directory name is valid on the target 34 | // platform. It will be passed in something *similar* to a URL such as 35 | // https:/index.docker.io/v1. Not all platforms support directory names 36 | -------------------------------------------------------------------------------- /patches/snappy-etc-apparmor-d.patch: -------------------------------------------------------------------------------- 1 | diff --git a/profiles/apparmor/apparmor.go b/profiles/apparmor/apparmor.go 2 | index 51dfa5c..4def938 100644 3 | --- a/profiles/apparmor/apparmor.go 4 | +++ b/profiles/apparmor/apparmor.go 5 | @@ -16,11 +16,23 @@ import ( 6 | 7 | var ( 8 | // profileDirectory is the file store for apparmor profiles and macros. 9 | - profileDirectory = "/etc/apparmor.d" 10 | + profileDirectory = defaultProfileDirectory() 11 | ) 12 | 13 | +func defaultProfileDirectory() string { 14 | + // Ubuntu Snappy has read-only /etc/apparmor.d 15 | + if snapData := os.Getenv("SNAP_DATA"); snapData != "" { 16 | + // Ubuntu Snappy 16.04+ 17 | + return snapData + "/etc/apparmor.d" 18 | + } else if os.Getenv("SNAP_APP_DATA_PATH") != "" { 19 | + // Ubuntu Snappy 15.04+ 20 | + return "/var/lib/apparmor/profiles" 21 | + } 22 | + return "/etc/apparmor.d" 23 | +} 24 | + 25 | // profileData holds information about the given profile for generation. 26 | type profileData struct { 27 | // Name is profile name. 28 | -------------------------------------------------------------------------------- /patches/snappy-etc-docker.patch: -------------------------------------------------------------------------------- 1 | diff --git a/cmd/dockerd/daemon_unix.go b/cmd/dockerd/daemon_unix.go 2 | index b65eb1f..7a70612 100644 3 | --- a/cmd/dockerd/daemon_unix.go 4 | +++ b/cmd/dockerd/daemon_unix.go 5 | @@ -44,6 +44,13 @@ func setDefaultUmask() error { 6 | } 7 | 8 | func getDaemonConfDir(_ string) string { 9 | + if snapData := os.Getenv("SNAP_DATA"); snapData != "" { 10 | + // Ubuntu Snappy 16.04+ 11 | + return snapData + "/etc/docker" 12 | + } else if snapAppDataPath := os.Getenv("SNAP_APP_DATA_PATH"); snapAppDataPath != "" { 13 | + // Ubuntu Snappy 15.04 14 | + return snapAppDataPath + "/etc/docker" 15 | + } 16 | return "/etc/docker" 17 | } 18 | 19 | -------------------------------------------------------------------------------- /patches/snappy-real-chroot.patch: -------------------------------------------------------------------------------- 1 | diff --git a/pkg/chrootarchive/archive_unix.go b/pkg/chrootarchive/archive_unix.go 2 | index f2325ab..84672cd 100644 3 | --- a/pkg/chrootarchive/archive_unix.go 4 | +++ b/pkg/chrootarchive/archive_unix.go 5 | @@ -30,7 +30,7 @@ func untar() { 6 | fatal(err) 7 | } 8 | 9 | - if err := chroot(flag.Arg(0)); err != nil { 10 | + if err := realChroot(flag.Arg(0)); err != nil { 11 | fatal(err) 12 | } 13 | 14 | -------------------------------------------------------------------------------- /patches/snappy-socket-group.patch: -------------------------------------------------------------------------------- 1 | diff --git a/vendor/github.com/docker/go-connections/sockets/unix_socket.go b/vendor/github.com/docker/go-connections/sockets/unix_socket.go 2 | index d162734..92fe0ac 100644 3 | --- a/vendor/github.com/docker/go-connections/sockets/unix_socket.go 4 | +++ b/vendor/github.com/docker/go-connections/sockets/unix_socket.go 5 | @@ -13,6 +13,10 @@ import ( 6 | "github.com/opencontainers/runc/libcontainer/user" 7 | ) 8 | 9 | +const ( 10 | + unixExtrausersPath = "/var/lib/extrausers/group" 11 | +) 12 | + 13 | // NewUnixSocket creates a unix socket with the specified path and group. 14 | func NewUnixSocket(path, group string) (net.Listener, error) { 15 | if err := syscall.Unlink(path); err != nil && !os.IsNotExist(err) { 16 | @@ -49,19 +53,22 @@ func setSocketGroup(path, group string) error { 17 | } 18 | 19 | func changeGroup(path string, nameOrGid string) error { 20 | - gid, err := lookupGidByName(nameOrGid) 21 | + groupFile, err := user.GetGroupPath() 22 | if err != nil { 23 | return err 24 | } 25 | + gid, err := lookupGidByName(nameOrGid, groupFile) 26 | + if err != nil { 27 | + gid, err = lookupGidByName(nameOrGid, unixExtrausersPath) 28 | + if err != nil { 29 | + return err 30 | + } 31 | + } 32 | logrus.Debugf("%s group found. gid: %d", nameOrGid, gid) 33 | return os.Chown(path, 0, gid) 34 | } 35 | 36 | -func lookupGidByName(nameOrGid string) (int, error) { 37 | - groupFile, err := user.GetGroupPath() 38 | - if err != nil { 39 | - return -1, err 40 | - } 41 | +func lookupGidByName(nameOrGid string, groupFile string) (int, error) { 42 | groups, err := user.ParseGroupFileFilter(groupFile, func(g user.Group) bool { 43 | return g.Name == nameOrGid || strconv.Itoa(g.Gid) == nameOrGid 44 | }) 45 | -------------------------------------------------------------------------------- /prep-docker-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # should be sourced from snapcraft.yaml while building Docker 4 | # current working directory should be the Docker source directory 5 | # SNAPDIR should be set to the root of this Git repo 6 | # (the directory of snapcraft.yml) 7 | 8 | for patch in "$SNAPDIR"/patches/*.patch; do 9 | echo "Applying $(basename "$patch") ..." 10 | patch \ 11 | --batch \ 12 | --forward \ 13 | --strip 1 \ 14 | --input "$patch" 15 | echo 16 | done 17 | 18 | # aww, can't use "git ls-remote" on launchpad: 19 | # fatal: unable to access 'https://github.com/docker/docker.git/': Could not resolve host: github.com 20 | # Loïc: you can, but only during the pull phase 21 | DOCKER_GITCOMMIT="$( 22 | git ls-remote --tags \ 23 | https://github.com/docker/docker.git \ 24 | "refs/tags/v$(< VERSION)^{}" \ 25 | | cut -b1-7 \ 26 | || echo "v$(< VERSION)" 27 | )-snap" 28 | if git rev-parse &> /dev/null; then 29 | DOCKER_GITCOMMIT+="-$(git rev-parse --short HEAD)" 30 | fi 31 | export DOCKER_GITCOMMIT 32 | export BUILDTIME="$( 33 | date --rfc-3339 ns 2>/dev/null | sed -e 's/ /T/' \ 34 | || date -u 35 | )" 36 | 37 | export DOCKER_BUILDTAGS=' 38 | apparmor 39 | seccomp 40 | selinux 41 | ' 42 | # pkcs11 43 | 44 | export AUTO_GOPATH=1 45 | -------------------------------------------------------------------------------- /registry-example.md: -------------------------------------------------------------------------------- 1 | ## Example: Setup a secure private registry 2 | 3 | These instructions are intended to get you started quickly using the open source registry in a secure manner. There are many configuration and deployment options not covered here (see [https://docs.docker.com/registry/](https://docs.docker.com/registry/) for more details). 4 | 5 | * Install the `docker` snap on all systems. 6 | * On the server node, 7 | 8 | * Generate a self-signed certificate replacing "mydockerhub.com" below with your fully qualified domain name: 9 | 10 | $ cd $HOME && mkdir certs 11 | $ openssl req -newkey rsa:2048 -nodes -sha256 \ 12 | -subj "/CN=mydockerhub.com" \ 13 | -x509 -days 3650 -out certs/domain.crt \ 14 | -keyout certs/domain.key 15 | 16 | * Create an `htpasswd` file, replacing "reguser" and "regpass" below with your desired credentials: 17 | 18 | $ cd $HOME && mkdir auth 19 | $ sudo docker run --entrypoint htpasswd registry:2 -Bbn reguser regpass > auth/htpasswd 20 | 21 | * Launch a basic authentication enabled registry server: 22 | 23 | $ sudo docker run -d -p 5000:5000 \ 24 | --restart=always \ 25 | --name registry \ 26 | -v `pwd`/auth:/auth \ 27 | -e "REGISTRY_AUTH=htpasswd" \ 28 | -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \ 29 | -e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd" \ 30 | -v `pwd`/registry:/tmp/registry \ 31 | -v `pwd`/certs:/certs \ 32 | -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \ 33 | -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \ 34 | registry:2 35 | 36 | * On the client nodes, 37 | 38 | * If the server node is not resolvable by it's FQDN, add an override to `/etc/hosts`. 39 | * Copy the the certificate from the registry server to your client machine. 40 | 41 | $ scp user@registry_server_ip:/home/user/certs/domain.crt ./ 42 | $ sudo mkdir -p /var/snap/docker/common/etc/certs.d/mydockerhub.com:5000 43 | $ sudo cp ./domain.crt /var/snap/docker/common/etc/certs.d/mydockerhub.com:5000/ca.crt 44 | 45 | > Note the special location `/var/snap/docker/common/etc/certs.d` instead of `/etc/docker/certs.d` mentioned in the [upstream documentation](https://docs.docker.com/engine/security/certificates/#understanding-the-configuration). 46 | 47 | * Login to the registry server: 48 | 49 | $ sudo docker login mydockerhub.com:5000 50 | 51 | * Validate functionality: 52 | 53 | $ sudo docker pull ubuntu 54 | $ sudo docker tag ubuntu mydockerhub.com:5000/ubuntu 55 | $ sudo docker push mydockerhub.com:5000/ubuntu 56 | $ sudo docker pull mydockerhub.com:5000/ubuntu 57 | -------------------------------------------------------------------------------- /snap/plugins/x-gobuild.py: -------------------------------------------------------------------------------- 1 | import os 2 | import subprocess 3 | import sys 4 | 5 | import snapcraft 6 | 7 | 8 | def list_executables(dir): 9 | """Return a list of the executable files under `dir`.""" 10 | output = subprocess.check_output( 11 | ['find', dir, '-executable', '-type', 'f']) 12 | r = set() 13 | for line in output.splitlines(): 14 | r.add(line.decode(sys.getfilesystemencoding())) 15 | return r 16 | 17 | 18 | def is_dynamic_executable(path): 19 | """Is `path` a dynamic executable?""" 20 | from elftools.elf.elffile import ELFFile 21 | from elftools.common.exceptions import ELFError 22 | # This way of answering the question is perhaps a bit OTT. But it works. 23 | try: 24 | e = ELFFile(open(path, 'rb')) 25 | return 'PT_DYNAMIC' in [s.header.p_type for s in e.iter_segments()] 26 | except ELFError as e: 27 | print("ELFFile({}) failed {}".format(path, e)) 28 | return False 29 | 30 | 31 | class XGobuildPlugin(snapcraft.BasePlugin): 32 | def build(self): 33 | env = os.environ.copy() 34 | 35 | # Bootstrap with the go that is on the PATH. 36 | goroot_bootstrap = subprocess.check_output(['go', 'env', 'GOROOT']) 37 | env['GOROOT_BOOTSTRAP'] = goroot_bootstrap.decode(sys.getfilesystemencoding()).rstrip('\n') 38 | # Set GOROOT_FINAL to something that should work (we don't 39 | # know the actual GOROOT until the package is uploaded to the 40 | # store, sadly). 41 | env['GOROOT_FINAL'] = '/snap/go/current' 42 | # But set GOROOT for now so that things continue to work. 43 | env['GOROOT'] = self.builddir 44 | arch = os.popen('dpkg --print-architecture').read().strip() 45 | if arch == 'amd64' or arch == 'i386': 46 | # Mystical incantation so that the C object files that end 47 | # up in e.g. runtime/cgo.a can be processed by the system 48 | # linker on trusty. 49 | env['CGO_CFLAGS'] = "-Wa,-mrelax-relocations=no" 50 | 51 | # All dynamic executables in a classic snap must be linked 52 | # with special flags. The Go linker does not support 53 | # equivalents of all these flags, so we need to link all 54 | # dynamic executables with the system linker. Unfortunately 55 | # GO_LDFLAGS='-linkmode=external' ./make.bash doesn't actually 56 | # work correctly on all platforms (the cgo stuff does not get 57 | # built early enough) so we bootstrap normally then relink 58 | # any dynamic binaries with the right flags. 59 | 60 | binaries_before = list_executables(self.builddir) 61 | self.run(['./make.bash'], cwd=os.path.join(self.builddir, 'src'), env=env) 62 | self.run(['rm', '-rf', 'pkg/bootstrap'], cwd=self.builddir) 63 | new_binaries = list_executables(self.builddir) - binaries_before 64 | 65 | # For extra fun, the special flags we need to link with are 66 | # not easily available from here -- they are exported as 67 | # $LDFLAGS inside self.run. But the go tool doesn't care about 68 | # $LDFLAGS, so we create a wrapper that does and tell the go 69 | # tool to invoke that instead. 70 | 71 | builtgo = os.path.join(self.builddir, 'bin', 'go') 72 | mycc = os.path.join(self.builddir, 'mycc') 73 | with open(mycc, 'w') as script: 74 | os.chmod(script.fileno(), 0o755) 75 | script.write('#!/bin/bash\n') 76 | script.write('set -ex\n') 77 | script.write('exec gcc $LDFLAGS "$@"\n') 78 | 79 | try: 80 | ldflags = '-linkmode=external -extld={}'.format(mycc) 81 | # Find any newly created dynamic binaries and rebuild them. 82 | for binary in new_binaries: 83 | if not is_dynamic_executable(binary): 84 | continue 85 | bn = os.path.basename(binary) 86 | pkg = 'cmd/' + bn 87 | self.run( 88 | [builtgo, 'build', '-v', '-ldflags', ldflags, pkg], 89 | cwd=self.builddir, env=env) 90 | os.rename(os.path.join(self.builddir, bn), binary) 91 | finally: 92 | # Remove our gcc wrapper. 93 | os.unlink(mycc) 94 | 95 | # Just ship the whole tree. 96 | self.run(['rsync', '-a', '--exclude', '.git', self.builddir + '/', self.installdir]) 97 | 98 | # And finally, create a wrapper that sets $GOROOT based on $SNAP. 99 | with open(os.path.join(self.installdir, 'gowrapper'), 'w') as script: 100 | os.chmod(script.fileno(), 0o755) 101 | script.write('#!/bin/bash\n') 102 | script.write('export GOROOT="$SNAP"\n') 103 | script.write('exec $SNAP/bin/go "$@"\n') 104 | -------------------------------------------------------------------------------- /snap/plugins/x-gobuild.yaml: -------------------------------------------------------------------------------- 1 | options: 2 | source: 3 | required: true 4 | source-type: 5 | source-tag: 6 | source-branch: 7 | -------------------------------------------------------------------------------- /snap/plugins/x-shell.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import snapcraft 4 | 5 | class ShellPlugin(snapcraft.BasePlugin): 6 | @classmethod 7 | def schema(cls): 8 | schema = super().schema() 9 | 10 | schema['required'] = [] 11 | 12 | schema['properties']['shell'] = { 13 | 'type': 'string', 14 | 'default': '/bin/sh', 15 | } 16 | schema['required'].append('shell') 17 | 18 | schema['properties']['shell-flags'] = { 19 | 'type': 'array', 20 | 'items': { 21 | 'type': 'string', 22 | }, 23 | 'default': [], 24 | } 25 | 26 | schema['properties']['shell-command'] = { 27 | 'type': 'string', 28 | } 29 | schema['required'].append('shell-command') 30 | 31 | return schema 32 | 33 | def env(self, root): 34 | return super().env(root) + [ 35 | 'SNAPDIR=' + os.getcwd(), 36 | ] 37 | 38 | def build(self): 39 | super().build() 40 | 41 | return self.run([ 42 | self.options.shell, 43 | ] + self.options.shell_flags + [ 44 | '-c', self.options.shell_command, 45 | ]) 46 | 47 | # vim:set ts=4 noet: 48 | -------------------------------------------------------------------------------- /snap/snapcraft.yaml: -------------------------------------------------------------------------------- 1 | name: docker 2 | version: 17.03.2-ce-1 3 | summary: Docker Linux container runtime 4 | description: Docker complements kernel namespacing with a high-level API which operates at the process level. It runs unix processes with strong guarantees of isolation and repeatability across servers. 5 | 6 | confinement: strict 7 | grade: stable 8 | 9 | plugs: 10 | support: 11 | interface: docker-support 12 | privileged: 13 | interface: docker-support 14 | privileged-containers: true 15 | docker-cli: 16 | interface: docker 17 | slots: 18 | docker-daemon: 19 | interface: docker 20 | docker-executables: 21 | content: docker-executables 22 | interface: content 23 | read: 24 | - . 25 | 26 | apps: 27 | docker: 28 | command: docker-wrapper docker 29 | plugs: 30 | - docker-cli 31 | - network 32 | - home 33 | 34 | dockerd: 35 | command: dockerd-wrapper 36 | daemon: simple 37 | plugs: 38 | - network-bind 39 | - firewall-control 40 | - support 41 | - privileged 42 | - home 43 | slots: 44 | - docker-daemon 45 | 46 | # TODO determine if we can "provide" a "docker-compose" in PATH directly (since this'll show up as "docker.compose" in the user PATH) 47 | compose: 48 | command: docker-wrapper docker-compose 49 | plugs: 50 | - docker-cli 51 | - network 52 | - home 53 | machine: 54 | command: docker-wrapper docker-machine 55 | plugs: 56 | - docker-cli 57 | - network 58 | - home 59 | - network-bind 60 | help: 61 | command: help 62 | 63 | parts: 64 | snappy-bins: 65 | plugin: shell 66 | shell: bash 67 | shell-flags: ['-ex'] 68 | shell-command: | 69 | install -d "$SNAPCRAFT_PART_INSTALL/bin" 70 | install -t "$SNAPCRAFT_PART_INSTALL/bin" "$SNAPDIR"/bin/* 71 | stage-packages: 72 | - mount 73 | 74 | go: 75 | plugin: gobuild 76 | source: https://storage.googleapis.com/golang/go1.8.3.src.tar.gz 77 | source-type: tar 78 | snap: 79 | - -* 80 | build-packages: 81 | - golang-go 82 | - rsync 83 | - build-essential 84 | - netbase 85 | - python3-pyelftools 86 | 87 | docker: 88 | plugin: shell 89 | source: https://github.com/docker/docker/archive/v17.03.2-ce.tar.gz 90 | source-type: tar 91 | shell: bash 92 | shell-flags: ['-eux', '-o', 'pipefail'] 93 | shell-command: | 94 | export GOROOT="$SNAPDIR/parts/go/install" 95 | export PATH="$GOROOT/bin:$PATH" 96 | go version 97 | 98 | source "$SNAPDIR/prep-docker-build.sh" 99 | 100 | ./hack/make.sh dynbinary 101 | 102 | ls -l bundles/latest/*/ 103 | 104 | clientBin='bundles/latest/dynbinary-client/docker' 105 | daemonBin='bundles/latest/dynbinary-daemon/dockerd' 106 | "$clientBin" -v 107 | "$daemonBin" -v 108 | "$clientBin" -v | grep -q -- "$DOCKER_GITCOMMIT" 109 | "$daemonBin" -v | grep -q -- "$DOCKER_GITCOMMIT" 110 | 111 | install -d "$SNAPCRAFT_PART_INSTALL/bin" 112 | install -T "$(readlink -f "$clientBin")" "$SNAPCRAFT_PART_INSTALL/bin/docker" 113 | install -T "$(readlink -f "$daemonBin")" "$SNAPCRAFT_PART_INSTALL/bin/dockerd" 114 | after: 115 | - go 116 | build-packages: 117 | - btrfs-tools 118 | - gcc 119 | - libc6-dev 120 | - libdevmapper-dev 121 | - libltdl-dev 122 | - patch 123 | - git 124 | - pkg-config 125 | stage-packages: 126 | - aufs-tools 127 | 128 | containerd: 129 | plugin: shell 130 | # from https://github.com/moby/moby/blob/v17.03.2-ce/hack/dockerfile/binaries-commits#L7 131 | source: https://github.com/docker/containerd/archive/4ab9917febca54791c5f071a9d1f404867857fcc.tar.gz 132 | source-type: tar 133 | shell: bash 134 | shell-flags: ['-ex'] 135 | shell-command: | 136 | export GOROOT="$SNAPDIR/parts/go/install" 137 | export PATH="$GOROOT/bin:$PATH" 138 | go version 139 | 140 | mkdir -p .gopath/src/github.com/docker 141 | ln -sfT "$PWD" .gopath/src/github.com/docker/containerd 142 | export GOPATH="$PWD/.gopath" 143 | 144 | make GIT_COMMIT= GIT_BRANCH= LDFLAGS= 145 | 146 | install -d "$SNAPCRAFT_PART_INSTALL/bin" 147 | install -T bin/containerd "$SNAPCRAFT_PART_INSTALL/bin/docker-containerd" 148 | install -T bin/containerd-shim "$SNAPCRAFT_PART_INSTALL/bin/docker-containerd-shim" 149 | install -T bin/ctr "$SNAPCRAFT_PART_INSTALL/bin/docker-containerd-ctr" 150 | after: 151 | - go 152 | build-packages: 153 | - make 154 | 155 | runc: 156 | plugin: shell 157 | # from https://github.com/moby/moby/blob/v17.03.2-ce/hack/dockerfile/binaries-commits#L6 158 | source: https://github.com/opencontainers/runc/archive/54296cf40ad8143b62dbcaa1d90e520a2136ddfe.tar.gz 159 | source-type: tar 160 | shell: bash 161 | shell-flags: ['-ex'] 162 | shell-command: | 163 | export GOROOT="$SNAPDIR/parts/go/install" 164 | export PATH="$GOROOT/bin:$PATH" 165 | go version 166 | 167 | mkdir -p .gopath/src/github.com/opencontainers 168 | ln -sfT "$PWD" .gopath/src/github.com/opencontainers/runc 169 | export GOPATH="$PWD/.gopath" 170 | 171 | make BUILDTAGS='seccomp apparmor selinux' COMMIT= 172 | 173 | install -d "$SNAPCRAFT_PART_INSTALL/bin" 174 | install -T runc "$SNAPCRAFT_PART_INSTALL/bin/docker-runc" 175 | after: 176 | - go 177 | build-packages: 178 | - libapparmor-dev 179 | - libseccomp-dev 180 | - make 181 | 182 | libnetwork: 183 | plugin: shell 184 | # from https://github.com/docker/docker/blob/v17.03.2-ce/hack/dockerfile/binaries-commits#L9 185 | source: https://github.com/docker/libnetwork/archive/0f534354b813003a754606689722fe253101bc4e.tar.gz 186 | source-type: tar 187 | shell: bash 188 | shell-flags: ['-ex'] 189 | shell-command: | 190 | export GOROOT="$SNAPDIR/parts/go/install" 191 | export PATH="$GOROOT/bin:$PATH" 192 | go version 193 | 194 | mkdir -p .gopath/src/github.com/docker 195 | ln -sfT "$PWD" .gopath/src/github.com/docker/libnetwork 196 | export GOPATH="$PWD/.gopath" 197 | 198 | go get github.com/tools/godep 199 | export PATH="$GOPATH/bin/:$PATH" 200 | godep version 201 | 202 | make build-local 203 | 204 | install -d "$SNAPCRAFT_PART_INSTALL/bin" 205 | install -T bin/docker-proxy "$SNAPCRAFT_PART_INSTALL/bin/docker-proxy" 206 | install -T bin/dnet "$SNAPCRAFT_PART_INSTALL/bin/dnet" 207 | after: 208 | - go 209 | build-packages: 210 | - iptables 211 | - make 212 | 213 | tini: 214 | plugin: cmake 215 | source: https://github.com/krallin/tini.git 216 | source-type: git 217 | # from https://github.com/moby/moby/blob/v17.03.2-ce/hack/dockerfile/binaries-commits#L8 218 | source-commit: 949e6facb77383876aeff8a6944dde66b3089574 219 | organize: 220 | 'bin/tini-static': bin/docker-init 221 | prime: 222 | - -bin/tini 223 | 224 | compose: 225 | plugin: python 226 | python-version: python2 227 | source: https://github.com/docker/compose/archive/1.14.0.tar.gz 228 | source-type: tar 229 | 230 | machine: 231 | plugin: shell 232 | source: https://github.com/docker/machine/archive/v0.12.0.tar.gz 233 | source-type: tar 234 | shell: bash 235 | shell-flags: ['-eux', '-o', 'pipefail'] 236 | shell-command: | 237 | export GOROOT="$SNAPDIR/parts/go/install" 238 | export PATH="$GOROOT/bin:$PATH" 239 | go version 240 | 241 | mkdir -p .gopath/src/github.com/docker 242 | ln -sfT "$PWD" .gopath/src/github.com/docker/machine 243 | export GOPATH="$PWD/.gopath" 244 | 245 | pushd .gopath/src/github.com/docker/machine 246 | make build 247 | popd 248 | 249 | install -d "$SNAPCRAFT_PART_INSTALL/bin" 250 | install -T bin/docker-machine "$SNAPCRAFT_PART_INSTALL/bin/docker-machine" 251 | after: 252 | - go 253 | 254 | # vim:set et ts=2 sw=2: 255 | --------------------------------------------------------------------------------