Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions 18.09-rc/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ COPY docker-entrypoint.sh /usr/local/bin/
# docker-entrypoint.sh uses DOCKER_TLS_CERTDIR for auto-setting DOCKER_TLS_VERIFY and DOCKER_CERT_PATH
# (For this to work, at least the "client" subdirectory of this path needs to be shared between the client and server containers via a volume, "docker cp", or other means of data sharing.)
ENV DOCKER_TLS_CERTDIR=
# also, ensure the directory pre-exists and has wide enough permissions for "dockerd-entrypoint.sh" to create subdirectories, even when run in "rootless" mode
RUN mkdir /certs /certs/client && chmod 1777 /certs /certs/client
# (doing both /certs and /certs/client so that if Docker does a "copy-up" into a volume defined on /certs/client, it will "do the right thing" by default in a way that still works for rootless users)

ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["sh"]
1 change: 1 addition & 0 deletions 18.09-rc/dind/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ RUN set -eux; \
e2fsprogs-extra \
iptables \
openssl \
shadow-uidmap \
xfsprogs \
xz \
# pigz: https://github.com/moby/moby/pull/35697 (faster gzip implementation)
Expand Down
59 changes: 56 additions & 3 deletions 18.09-rc/dind/dockerd-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,17 @@ _tls_generate_certs() {
# no arguments passed
# or first arg is `-f` or `--some-option`
if [ "$#" -eq 0 ] || [ "${1#-}" != "$1" ]; then
# set DOCKER_HOST to the default "--host" value (for both standard or rootless)
uid="$(id -u)"
if [ "$uid" = '0' ]; then
: "${DOCKER_HOST:=unix:///var/run/docker.sock}"
else
# if we're not root, we must be trying to run rootless
: "${XDG_RUNTIME_DIR:=/run/user/$uid}"
: "${DOCKER_HOST:=unix://$XDG_RUNTIME_DIR/docker.sock}"
fi
export DOCKER_HOST

# add our default arguments
if [ -n "${DOCKER_TLS_CERTDIR:-}" ] \
&& _tls_generate_certs "$DOCKER_TLS_CERTDIR" \
Expand All @@ -101,19 +112,21 @@ if [ "$#" -eq 0 ] || [ "${1#-}" != "$1" ]; then
; then
# generate certs and use TLS if requested/possible (default in 19.03+)
set -- dockerd \
--host=unix:///var/run/docker.sock \
--host="$DOCKER_HOST" \
--host=tcp://0.0.0.0:2376 \
--tlsverify \
--tlscacert "$DOCKER_TLS_CERTDIR/server/ca.pem" \
--tlscert "$DOCKER_TLS_CERTDIR/server/cert.pem" \
--tlskey "$DOCKER_TLS_CERTDIR/server/key.pem" \
"$@"
DOCKERD_ROOTLESS_ROOTLESSKIT_FLAGS="${DOCKERD_ROOTLESS_ROOTLESSKIT_FLAGS:-} -p 0.0.0.0:2376:2376/tcp"
else
# TLS disabled (-e DOCKER_TLS_CERTDIR='') or missing certs
set -- dockerd \
--host=unix:///var/run/docker.sock \
--host="$DOCKER_HOST" \
--host=tcp://0.0.0.0:2375 \
"$@"
DOCKERD_ROOTLESS_ROOTLESSKIT_FLAGS="${DOCKERD_ROOTLESS_ROOTLESSKIT_FLAGS:-} -p 0.0.0.0:2375:2375/tcp"
fi
fi

Expand All @@ -124,7 +137,47 @@ if [ "$1" = 'dockerd' ]; then
fi

# explicitly remove Docker's default PID file to ensure that it can start properly if it was stopped uncleanly (and thus didn't clean up the PID file)
find /run /var/run -iname 'docker*.pid' -delete
find /run /var/run -iname 'docker*.pid' -delete || :

uid="$(id -u)"
if [ "$uid" != '0' ]; then
# if we're not root, we must be trying to run rootless
if ! command -v rootlesskit > /dev/null; then
echo >&2 "error: attempting to run rootless dockerd but missing 'rootlesskit' (perhaps the 'docker:dind-rootless' image variant is intended?)"
exit 1
fi
user="$(id -un 2>/dev/null || :)"
if ! grep -qE "^($uid${user:+|$user}):" /etc/subuid || ! grep -qE "^($uid${user:+|$user}):" /etc/subgid; then
echo >&2 "error: attempting to run rootless dockerd but missing necessary entries in /etc/subuid and/or /etc/subgid for $uid"
exit 1
fi
: "${XDG_RUNTIME_DIR:=/run/user/$uid}"
export XDG_RUNTIME_DIR
if ! mkdir -p "$XDG_RUNTIME_DIR" || [ ! -w "$XDG_RUNTIME_DIR" ] || ! mkdir -p "$HOME/.local/share/docker" || [ ! -w "$HOME/.local/share/docker" ]; then
echo >&2 "error: attempting to run rootless dockerd but need writable HOME ($HOME) and XDG_RUNTIME_DIR ($XDG_RUNTIME_DIR) for user $uid"
exit 1
fi
if ! unprivClone="$(cat /proc/sys/kernel/unprivileged_userns_clone || :)" || [ "$unprivClone" != '1' ]; then
echo >&2 "error: attempting to run rootless dockerd but need 'kernel.unprivileged_userns_clone' (/proc/sys/kernel/unprivileged_userns_clone) set to 1"
exit 1
fi
if ! maxUserns="$(cat /proc/sys/user/max_user_namespaces || :)" || [ "$maxUserns" = '0' ]; then
echo >&2 "error: attempting to run rootless dockerd but need 'user.max_user_namespaces' (/proc/sys/user/max_user_namespaces) set to a sufficiently large value"
exit 1
fi
# TODO overlay support detection?
exec rootlesskit \
--net="${DOCKERD_ROOTLESS_ROOTLESSKIT_NET:-vpnkit}" \
--mtu="${DOCKERD_ROOTLESS_ROOTLESSKIT_MTU:-1500}" \
--disable-host-loopback \
--port-driver=builtin \
--copy-up=/etc --copy-up=/run \
${DOCKERD_ROOTLESS_ROOTLESSKIT_FLAGS:-} \
"$@" --userland-proxy-path=rootlesskit-docker-proxy
fi
else
# if it isn't `dockerd` we're trying to run, pass it through `docker-entrypoint.sh` so it gets `DOCKER_HOST` set appropriately too
set -- docker-entrypoint.sh "$@"
fi

exec "$@"
17 changes: 14 additions & 3 deletions 18.09-rc/docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,26 @@ _should_tls() {
&& [ -s "$DOCKER_TLS_CERTDIR/client/key.pem" ]
}

# if DOCKER_HOST isn't set and we don't have the default unix socket, let's set DOCKER_HOST to a sane remote value
if [ -z "${DOCKER_HOST:-}" ] && [ ! -S /var/run/docker.sock ]; then
# if we have no DOCKER_HOST but we do have the default Unix socket (standard or rootless), use it explicitly
if [ -z "${DOCKER_HOST:-}" ] && [ -S /var/run/docker.sock ]; then
export DOCKER_HOST=unix:///var/run/docker.sock
elif [ -z "${DOCKER_HOST:-}" ] && XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}" && [ -S "$XDG_RUNTIME_DIR/docker.sock" ]; then
export DOCKER_HOST="unix://$XDG_RUNTIME_DIR/docker.sock"
fi

# if DOCKER_HOST isn't set (no custom setting, no default socket), let's set it to a sane remote value
if [ -z "${DOCKER_HOST:-}" ]; then
if _should_tls || [ -n "${DOCKER_TLS_VERIFY:-}" ]; then
export DOCKER_HOST='tcp://docker:2376'
else
export DOCKER_HOST='tcp://docker:2375'
fi
fi
if [ -n "${DOCKER_HOST:-}" ] && _should_tls; then
if [ "${DOCKER_HOST#tcp:}" != "$DOCKER_HOST" ] \
&& [ -z "${DOCKER_TLS_VERIFY:-}" ] \
&& [ -z "${DOCKER_CERT_PATH:-}" ] \
&& _should_tls \
; then
export DOCKER_TLS_VERIFY=1
export DOCKER_CERT_PATH="$DOCKER_TLS_CERTDIR/client"
fi
Expand Down
3 changes: 3 additions & 0 deletions 18.09/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ COPY docker-entrypoint.sh /usr/local/bin/
# docker-entrypoint.sh uses DOCKER_TLS_CERTDIR for auto-setting DOCKER_TLS_VERIFY and DOCKER_CERT_PATH
# (For this to work, at least the "client" subdirectory of this path needs to be shared between the client and server containers via a volume, "docker cp", or other means of data sharing.)
ENV DOCKER_TLS_CERTDIR=
# also, ensure the directory pre-exists and has wide enough permissions for "dockerd-entrypoint.sh" to create subdirectories, even when run in "rootless" mode
RUN mkdir /certs /certs/client && chmod 1777 /certs /certs/client
# (doing both /certs and /certs/client so that if Docker does a "copy-up" into a volume defined on /certs/client, it will "do the right thing" by default in a way that still works for rootless users)

ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["sh"]
1 change: 1 addition & 0 deletions 18.09/dind/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ RUN set -eux; \
e2fsprogs-extra \
iptables \
openssl \
shadow-uidmap \
xfsprogs \
xz \
# pigz: https://github.com/moby/moby/pull/35697 (faster gzip implementation)
Expand Down
59 changes: 56 additions & 3 deletions 18.09/dind/dockerd-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,17 @@ _tls_generate_certs() {
# no arguments passed
# or first arg is `-f` or `--some-option`
if [ "$#" -eq 0 ] || [ "${1#-}" != "$1" ]; then
# set DOCKER_HOST to the default "--host" value (for both standard or rootless)
uid="$(id -u)"
if [ "$uid" = '0' ]; then
: "${DOCKER_HOST:=unix:///var/run/docker.sock}"
else
# if we're not root, we must be trying to run rootless
: "${XDG_RUNTIME_DIR:=/run/user/$uid}"
: "${DOCKER_HOST:=unix://$XDG_RUNTIME_DIR/docker.sock}"
fi
export DOCKER_HOST

# add our default arguments
if [ -n "${DOCKER_TLS_CERTDIR:-}" ] \
&& _tls_generate_certs "$DOCKER_TLS_CERTDIR" \
Expand All @@ -101,19 +112,21 @@ if [ "$#" -eq 0 ] || [ "${1#-}" != "$1" ]; then
; then
# generate certs and use TLS if requested/possible (default in 19.03+)
set -- dockerd \
--host=unix:///var/run/docker.sock \
--host="$DOCKER_HOST" \
--host=tcp://0.0.0.0:2376 \
--tlsverify \
--tlscacert "$DOCKER_TLS_CERTDIR/server/ca.pem" \
--tlscert "$DOCKER_TLS_CERTDIR/server/cert.pem" \
--tlskey "$DOCKER_TLS_CERTDIR/server/key.pem" \
"$@"
DOCKERD_ROOTLESS_ROOTLESSKIT_FLAGS="${DOCKERD_ROOTLESS_ROOTLESSKIT_FLAGS:-} -p 0.0.0.0:2376:2376/tcp"
else
# TLS disabled (-e DOCKER_TLS_CERTDIR='') or missing certs
set -- dockerd \
--host=unix:///var/run/docker.sock \
--host="$DOCKER_HOST" \
--host=tcp://0.0.0.0:2375 \
"$@"
DOCKERD_ROOTLESS_ROOTLESSKIT_FLAGS="${DOCKERD_ROOTLESS_ROOTLESSKIT_FLAGS:-} -p 0.0.0.0:2375:2375/tcp"
fi
fi

Expand All @@ -124,7 +137,47 @@ if [ "$1" = 'dockerd' ]; then
fi

# explicitly remove Docker's default PID file to ensure that it can start properly if it was stopped uncleanly (and thus didn't clean up the PID file)
find /run /var/run -iname 'docker*.pid' -delete
find /run /var/run -iname 'docker*.pid' -delete || :

uid="$(id -u)"
if [ "$uid" != '0' ]; then
# if we're not root, we must be trying to run rootless
if ! command -v rootlesskit > /dev/null; then
echo >&2 "error: attempting to run rootless dockerd but missing 'rootlesskit' (perhaps the 'docker:dind-rootless' image variant is intended?)"
exit 1
fi
user="$(id -un 2>/dev/null || :)"
if ! grep -qE "^($uid${user:+|$user}):" /etc/subuid || ! grep -qE "^($uid${user:+|$user}):" /etc/subgid; then
echo >&2 "error: attempting to run rootless dockerd but missing necessary entries in /etc/subuid and/or /etc/subgid for $uid"
exit 1
fi
: "${XDG_RUNTIME_DIR:=/run/user/$uid}"
export XDG_RUNTIME_DIR
if ! mkdir -p "$XDG_RUNTIME_DIR" || [ ! -w "$XDG_RUNTIME_DIR" ] || ! mkdir -p "$HOME/.local/share/docker" || [ ! -w "$HOME/.local/share/docker" ]; then
echo >&2 "error: attempting to run rootless dockerd but need writable HOME ($HOME) and XDG_RUNTIME_DIR ($XDG_RUNTIME_DIR) for user $uid"
exit 1
fi
if ! unprivClone="$(cat /proc/sys/kernel/unprivileged_userns_clone || :)" || [ "$unprivClone" != '1' ]; then
echo >&2 "error: attempting to run rootless dockerd but need 'kernel.unprivileged_userns_clone' (/proc/sys/kernel/unprivileged_userns_clone) set to 1"
exit 1
fi
if ! maxUserns="$(cat /proc/sys/user/max_user_namespaces || :)" || [ "$maxUserns" = '0' ]; then
echo >&2 "error: attempting to run rootless dockerd but need 'user.max_user_namespaces' (/proc/sys/user/max_user_namespaces) set to a sufficiently large value"
exit 1
fi
# TODO overlay support detection?
exec rootlesskit \
--net="${DOCKERD_ROOTLESS_ROOTLESSKIT_NET:-vpnkit}" \
--mtu="${DOCKERD_ROOTLESS_ROOTLESSKIT_MTU:-1500}" \
--disable-host-loopback \
--port-driver=builtin \
--copy-up=/etc --copy-up=/run \
${DOCKERD_ROOTLESS_ROOTLESSKIT_FLAGS:-} \
"$@" --userland-proxy-path=rootlesskit-docker-proxy
fi
else
# if it isn't `dockerd` we're trying to run, pass it through `docker-entrypoint.sh` so it gets `DOCKER_HOST` set appropriately too
set -- docker-entrypoint.sh "$@"
fi

exec "$@"
17 changes: 14 additions & 3 deletions 18.09/docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,26 @@ _should_tls() {
&& [ -s "$DOCKER_TLS_CERTDIR/client/key.pem" ]
}

# if DOCKER_HOST isn't set and we don't have the default unix socket, let's set DOCKER_HOST to a sane remote value
if [ -z "${DOCKER_HOST:-}" ] && [ ! -S /var/run/docker.sock ]; then
# if we have no DOCKER_HOST but we do have the default Unix socket (standard or rootless), use it explicitly
if [ -z "${DOCKER_HOST:-}" ] && [ -S /var/run/docker.sock ]; then
export DOCKER_HOST=unix:///var/run/docker.sock
elif [ -z "${DOCKER_HOST:-}" ] && XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}" && [ -S "$XDG_RUNTIME_DIR/docker.sock" ]; then
export DOCKER_HOST="unix://$XDG_RUNTIME_DIR/docker.sock"
fi

# if DOCKER_HOST isn't set (no custom setting, no default socket), let's set it to a sane remote value
if [ -z "${DOCKER_HOST:-}" ]; then
if _should_tls || [ -n "${DOCKER_TLS_VERIFY:-}" ]; then
export DOCKER_HOST='tcp://docker:2376'
else
export DOCKER_HOST='tcp://docker:2375'
fi
fi
if [ -n "${DOCKER_HOST:-}" ] && _should_tls; then
if [ "${DOCKER_HOST#tcp:}" != "$DOCKER_HOST" ] \
&& [ -z "${DOCKER_TLS_VERIFY:-}" ] \
&& [ -z "${DOCKER_CERT_PATH:-}" ] \
&& _should_tls \
; then
export DOCKER_TLS_VERIFY=1
export DOCKER_CERT_PATH="$DOCKER_TLS_CERTDIR/client"
fi
Expand Down
3 changes: 3 additions & 0 deletions 19.03-rc/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ COPY docker-entrypoint.sh /usr/local/bin/
# docker-entrypoint.sh uses DOCKER_TLS_CERTDIR for auto-setting DOCKER_TLS_VERIFY and DOCKER_CERT_PATH
# (For this to work, at least the "client" subdirectory of this path needs to be shared between the client and server containers via a volume, "docker cp", or other means of data sharing.)
ENV DOCKER_TLS_CERTDIR=/certs
# also, ensure the directory pre-exists and has wide enough permissions for "dockerd-entrypoint.sh" to create subdirectories, even when run in "rootless" mode
RUN mkdir /certs /certs/client && chmod 1777 /certs /certs/client
# (doing both /certs and /certs/client so that if Docker does a "copy-up" into a volume defined on /certs/client, it will "do the right thing" by default in a way that still works for rootless users)

ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["sh"]
73 changes: 73 additions & 0 deletions 19.03-rc/dind-rootless/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
FROM docker:19.03-rc-dind

# busybox "ip" is insufficient:
# [rootlesskit:child ] error: executing [[ip tuntap add name tap0 mode tap] [ip link set tap0 address 02:50:00:00:00:01]]: exit status 1
RUN apk add --no-cache iproute2

# "/run/user/UID" will be used by default as the value of XDG_RUNTIME_DIR
RUN mkdir /run/user && chmod 1777 /run/user

# create a default user preconfigured for running rootless dockerd
RUN set -eux; \
adduser -h /home/rootless -g 'Rootless' -D -u 1000 rootless; \
echo 'rootless:100000:65536' >> /etc/subuid; \
echo 'rootless:100000:65536' >> /etc/subgid

RUN set -eux; \
\
# this "case" statement is generated via "update.sh"
apkArch="$(apk --print-arch)"; \
case "$apkArch" in \
# amd64
x86_64) dockerArch='x86_64' ;; \
# arm32v6
armhf) dockerArch='armel' ;; \
# arm32v7
armv7) dockerArch='armhf' ;; \
# arm64v8
aarch64) dockerArch='aarch64' ;; \
*) echo >&2 "error: unsupported architecture ($apkArch)"; exit 1 ;;\
esac; \
\
if ! wget -O rootless.tgz "https://download.docker.com/linux/static/${DOCKER_CHANNEL}/${dockerArch}/docker-rootless-extras-${DOCKER_VERSION}.tgz"; then \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: If you don't like the VPNKit binary footprint, https://github.com/rootless-containers/slirp4netns can be used instead of VPNKit.

slirp4netns is licensed under GPL2 and not included in the docker-rootless-extras.tgz because they didn't want to include GPL2 binary in the same tgz, but probably it doesn't hurt to put slirp4netns in Docker images.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't mind the footprint (or vpnkit in general -- I understand it's been used in Docker Desktop for a pretty respectable amount of time now, so it's "tested, tried, and true" so to speak) -- the issue I've got is with the need to pull this extra bundle which we then have to wait for a new Docker release to get an update to if there happens to be some issue that's resolved in a newer release of vpnkit, so it'd be really neat to get some official binary releases there, but I think that's a pretty minor issue at this point (vpnkit is pretty provably solid, as noted).

echo >&2 "error: failed to download 'docker-rootless-extras-${DOCKER_VERSION}' from '${DOCKER_CHANNEL}' for '${dockerArch}'"; \
exit 1; \
fi; \
\
tar --extract \
--file rootless.tgz \
--strip-components 1 \
--directory /usr/local/bin/ \
'docker-rootless-extras/vpnkit' \
; \
rm rootless.tgz; \
\
# we download/build rootlesskit separately to get a newer release
# rootlesskit --version; \
vpnkit --version

# https://github.com/rootless-containers/rootlesskit/releases
ENV ROOTLESSKIT_VERSION 0.6.0

RUN set -eux; \
apk add --no-cache --virtual .rootlesskit-build-deps \
go \
libc-dev \
; \
wget -O rootlesskit.tgz "https://github.com/rootless-containers/rootlesskit/archive/v${ROOTLESSKIT_VERSION}.tar.gz"; \
export GOPATH='/go'; mkdir "$GOPATH"; \
mkdir -p "$GOPATH/src/github.com/rootless-containers/rootlesskit"; \
tar --extract --file rootlesskit.tgz --directory "$GOPATH/src/github.com/rootless-containers/rootlesskit" --strip-components 1; \
rm rootlesskit.tgz; \
go build -o /usr/local/bin/rootlesskit github.com/rootless-containers/rootlesskit/cmd/rootlesskit; \
go build -o /usr/local/bin/rootlesskit-docker-proxy github.com/rootless-containers/rootlesskit/cmd/rootlesskit-docker-proxy; \
rm -rf "$GOPATH"; \
apk del --no-network .rootlesskit-build-deps; \
rootlesskit --version

# pre-create "/var/lib/docker" for our rootless user
RUN set -eux; \
mkdir -p /home/rootless/.local/share/docker; \
chown -R rootless:rootless /home/rootless/.local/share/docker
VOLUME /home/rootless/.local/share/docker
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer setting ENV XDG_RUNTIME_DIR here so that it is visible to docker exec processes

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and also DOCKER_HOST for docker exec docker

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The expected usage there would be either docker exec -it docker-entrypoint.sh sh or docker exec docker-entrypoint.sh version, etc (using the same functionality as docker run docker ... does to set those same variables automatically/appropriately). Along those lines, I'm also going to update dockerd-entrypoint.sh to pass not only docker ... through to docker-entrypoint.sh, but any command that isn't dockerd (which should help with this as well).

USER rootless
1 change: 1 addition & 0 deletions 19.03-rc/dind/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ RUN set -eux; \
e2fsprogs-extra \
iptables \
openssl \
shadow-uidmap \
xfsprogs \
xz \
# pigz: https://github.com/moby/moby/pull/35697 (faster gzip implementation)
Expand Down
Loading