From 502621d289ad883948f852512be503f52cafb20e Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Wed, 15 May 2024 12:04:34 +0000 Subject: [PATCH 1/4] chore: add docs re docker inside envbuiler-built-envs --- README.md | 5 + docs/docker.md | 109 ++++++++++++++++++ examples/docker/01_dood/Dockerfile | 2 + examples/docker/01_dood/devcontainer.json | 5 + examples/docker/02_dind/Dockerfile | 6 + examples/docker/02_dind/devcontainer.json | 5 + examples/docker/02_dind/entrypoint.sh | 7 ++ examples/docker/03_dind_rootless/Dockerfile | 22 ++++ .../docker/03_dind_rootless/devcontainer.json | 5 + .../docker/03_dind_rootless/entrypoint.sh | 8 ++ 10 files changed, 174 insertions(+) create mode 100644 docs/docker.md create mode 100644 examples/docker/01_dood/Dockerfile create mode 100644 examples/docker/01_dood/devcontainer.json create mode 100644 examples/docker/02_dind/Dockerfile create mode 100644 examples/docker/02_dind/devcontainer.json create mode 100755 examples/docker/02_dind/entrypoint.sh create mode 100644 examples/docker/03_dind_rootless/Dockerfile create mode 100644 examples/docker/03_dind_rootless/devcontainer.json create mode 100755 examples/docker/03_dind_rootless/entrypoint.sh diff --git a/README.md b/README.md index 7b09215b..9a1a008f 100644 --- a/README.md +++ b/README.md @@ -134,6 +134,11 @@ Provide the encoded JSON config to envbuilder: DOCKER_CONFIG_BASE64=ewoJImF1dGhzIjogewoJCSJodHRwczovL2luZGV4LmRvY2tlci5pby92MS8iOiB7CgkJCSJhdXRoIjogImJhc2U2NCBlbmNvZGVkIHRva2VuIgoJCX0KCX0KfQo= ``` +### Docker-in-Docker + +See [here](./docs/docker.md) for instructions on running Docker containers inside +environments built by Envbuilder. + ## Git Authentication Two methods of authentication are supported: diff --git a/docs/docker.md b/docs/docker.md new file mode 100644 index 00000000..84e8a174 --- /dev/null +++ b/docs/docker.md @@ -0,0 +1,109 @@ +# Docker inside Envbuilder + +There are a number of approaches you can use to have access to a Docker daemon +from inside Envbuilder: + +## Docker Outside of Docker (DooD) + +**Security:** None +**Convenience:** High + +This approach re-uses the host Docker socket and passes it inside the container. +It is the simplest approach, but offers **no security** -- any process inside the +container that can connect to the Docker socket will have access to the +underlying host. +Only use it if you are the only person using the Docker socket (for example, if +you are experimenting on your own workstation). + +Example: + +```shell +docker run -it --rm \ + -v /tmp/envbuilder:/workspaces \ + -e ENVBUILDER_GIT_URL=https://github.com/coder/envbuilder \ + -e ENVBUILDER_DEVCONTAINER_DIR=/workspaces/envbuilder/examples/docker/01_dood \ + -e ENVBUILDER_INIT_SCRIPT=bash \ + ghcr.io/coder/envbuilder:latest +``` + + +## Docker-in-Docker (DinD) + +**Security:** Low +**Convenience:** High + +This approach entails running a Docker daemon inside the container. +This requires a privileged container to run, and therefore has a wide potential +attack surface. + +Example: + +> Note that due to a lack of init system, the Docker daemon +> needs to be started separately inside the container. In this example, we +> create a custom entrypoint to start the Docker daemon in the background and +> call this entrypoint via `ENVBUILDER_INIT_SCRIPT`. + +```shell +docker run -it --rm \ + --privileged \ + -v /tmp/envbuilder:/workspaces \ + -e ENVBUILDER_GIT_URL=https://github.com/coder/envbuilder \ + -e ENVBUILDER_DEVCONTAINER_DIR=/workspaces/envbuilder/examples/docker/02_dind \ + -e ENVBUILDER_INIT_SCRIPT=/entrypoint.sh \ + ghcr.io/coder/envbuilder:latest +``` + +This can also be accomplished using the [`docker-in-docker` Devcontainer feature](https://github.com/devcontainers/features/tree/main/src/docker-in-docker). + +## Rootless DinD + +**Security:** Medium +**Convenience:** Medium + +This approach runs a Docker daemon in *rootless* mode. +While this still requires a privileged container, this allows you to restrict +usage of the `root` user inside the container, as the Docker daemon will be run +under a "fake" root user (via `rootlesskit`). The user inside the workspace can +then be a 'regular' user without root permissions. + +> Note: Once again, we use a custom entrypoint via `ENVBUILDER_INIT_SCRIPT` to +> start the Docker daemon via `rootlesskit`. + +Example: + +``` +docker run -it --rm \ + --privileged \ + -v /tmp/envbuilder:/workspaces \ + -e ENVBUILDER_GIT_URL=https://github.com/coder/envbuilder \ + -e ENVBUILDER_DEVCONTAINER_DIR=/workspaces/envbuilder/examples/docker/03_dind_rootless \ + -e ENVBUILDER_INIT_SCRIPT=/entrypoint.sh \ + ghcr.io/coder/envbuilder:latest +``` + +## Docker-in-Docker using Sysbox + +**Security:** High +**Convenience:** Low for infra admins, high for users + +This approach requires installing the [`sysbox-runc` container +runtime](https://github.com/nestybox/sysbox/blob/master/docs/user-guide/install-package.md). +This is an alternative container runtime that provides additional benefits, +including transparently enabling Docker inside workspaces. Most notably, it +**does not require a privileged container**, so you can allow developers root +access inside their workspaces, if required. + +Example: +``` +docker run -it --rm \ + --privileged \ + -v /tmp/envbuilder:/workspaces \ + -e ENVBUILDER_GIT_URL=https://github.com/coder/envbuilder \ + -e ENVBUILDER_DEVCONTAINER_DIR=/workspaces/envbuilder/examples/docker/02_dind \ + -e ENVBUILDER_INIT_SCRIPT=/entrypoint.sh \ + --runtime sysbox-runc \ + ghcr.io/coder/envbuilder:latest +``` + +For further information on Sysbox, please consult the [Sysbox +Documentation](https://github.com/nestybox/sysbox/blob/master/docs/user-guide/README.md). diff --git a/examples/docker/01_dood/Dockerfile b/examples/docker/01_dood/Dockerfile new file mode 100644 index 00000000..8834c342 --- /dev/null +++ b/examples/docker/01_dood/Dockerfile @@ -0,0 +1,2 @@ +FROM ubuntu:latest +RUN apt-get update && apt-get install -y docker.io \ No newline at end of file diff --git a/examples/docker/01_dood/devcontainer.json b/examples/docker/01_dood/devcontainer.json new file mode 100644 index 00000000..1933fd86 --- /dev/null +++ b/examples/docker/01_dood/devcontainer.json @@ -0,0 +1,5 @@ +{ + "build": { + "dockerfile": "Dockerfile" + } +} \ No newline at end of file diff --git a/examples/docker/02_dind/Dockerfile b/examples/docker/02_dind/Dockerfile new file mode 100644 index 00000000..283dca7e --- /dev/null +++ b/examples/docker/02_dind/Dockerfile @@ -0,0 +1,6 @@ +FROM ubuntu:latest +RUN apt-get update && \ + apt-get install -y curl apt-transport-https && \ + curl -fsSL https://get.docker.com/ | sh -s - +ADD entrypoint.sh /entrypoint.sh +ENTRYPOINT ["/entrypoint.sh"] \ No newline at end of file diff --git a/examples/docker/02_dind/devcontainer.json b/examples/docker/02_dind/devcontainer.json new file mode 100644 index 00000000..1933fd86 --- /dev/null +++ b/examples/docker/02_dind/devcontainer.json @@ -0,0 +1,5 @@ +{ + "build": { + "dockerfile": "Dockerfile" + } +} \ No newline at end of file diff --git a/examples/docker/02_dind/entrypoint.sh b/examples/docker/02_dind/entrypoint.sh new file mode 100755 index 00000000..38ac3318 --- /dev/null +++ b/examples/docker/02_dind/entrypoint.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +set -euo pipefail + +nohup dockerd > /var/log/docker.log 2>&1 & + +exec bash --login \ No newline at end of file diff --git a/examples/docker/03_dind_rootless/Dockerfile b/examples/docker/03_dind_rootless/Dockerfile new file mode 100644 index 00000000..36f1788f --- /dev/null +++ b/examples/docker/03_dind_rootless/Dockerfile @@ -0,0 +1,22 @@ +FROM ubuntu:latest +## Install prerequisites +RUN apt-get update && \ + apt-get install -y apt-transport-https curl iproute2 uidmap +# Install Docker daemon +RUN curl -fsSL https://get.docker.com/ | sh -s - +# Add the ubuntu user to the Docker group +RUN usermod -aG docker ubuntu +# Add our custom entrypoint +ADD entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh +# Create the XDG_RUNTIME_DIR for our user and set DOCKER_HOST +ENV XDG_RUNTIME_DIR /run/user/1000 +RUN mkdir -p ${XDG_RUNTIME_DIR} && chown ubuntu:ubuntu ${XDG_RUNTIME_DIR} +ENV DOCKER_HOST unix:///${XDG_RUNTIME_DIR}/docker.sock +# Setup rootless mode as the ubuntu user. +USER ubuntu +RUN dockerd-rootless-setuptool.sh install +# Switch the ubuntu user to use the rootless docker context +RUN docker context use rootless +RUN mkdir -p /home/ubuntu/.local/share/docker +ENTRYPOINT ["/entrypoint.sh"] \ No newline at end of file diff --git a/examples/docker/03_dind_rootless/devcontainer.json b/examples/docker/03_dind_rootless/devcontainer.json new file mode 100644 index 00000000..1933fd86 --- /dev/null +++ b/examples/docker/03_dind_rootless/devcontainer.json @@ -0,0 +1,5 @@ +{ + "build": { + "dockerfile": "Dockerfile" + } +} \ No newline at end of file diff --git a/examples/docker/03_dind_rootless/entrypoint.sh b/examples/docker/03_dind_rootless/entrypoint.sh new file mode 100755 index 00000000..6c8a6260 --- /dev/null +++ b/examples/docker/03_dind_rootless/entrypoint.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# Start the rootless docker daemon as a non-root user +nohup rootlesskit --net=slirp4netns --mtu=1500 --disable-host-loopback --port-driver=builtin --copy-up=/etc --copy-up=/run dockerd > "/tmp/dockerd-rootless.log" 2>&1 & + +exec bash --login \ No newline at end of file From 9cda27e07abdb9e10c573f32a6879231d20d8a51 Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Wed, 15 May 2024 12:06:49 +0000 Subject: [PATCH 2/4] fixup! chore: add docs re docker inside envbuiler-built-envs --- docs/docker.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/docker.md b/docs/docker.md index 84e8a174..665ab7e5 100644 --- a/docs/docker.md +++ b/docs/docker.md @@ -96,7 +96,6 @@ access inside their workspaces, if required. Example: ``` docker run -it --rm \ - --privileged \ -v /tmp/envbuilder:/workspaces \ -e ENVBUILDER_GIT_URL=https://github.com/coder/envbuilder \ -e ENVBUILDER_DEVCONTAINER_DIR=/workspaces/envbuilder/examples/docker/02_dind \ From df2827a3eff27d885f397f21aa7411b0bf864a66 Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Wed, 15 May 2024 13:30:39 +0000 Subject: [PATCH 3/4] address PR comments --- docs/docker.md | 29 +++++++++++++++---- examples/docker/01_dood/Dockerfile | 2 +- examples/docker/02_dind/Dockerfile | 2 +- examples/docker/03_dind_feature/Dockerfile | 3 ++ .../docker/03_dind_feature/devcontainer.json | 8 +++++ examples/docker/03_dind_feature/entrypoint.sh | 7 +++++ examples/docker/03_dind_rootless/Dockerfile | 22 -------------- examples/docker/04_dind_rootless/Dockerfile | 24 +++++++++++++++ .../devcontainer.json | 0 .../entrypoint.sh | 0 10 files changed, 68 insertions(+), 29 deletions(-) create mode 100644 examples/docker/03_dind_feature/Dockerfile create mode 100644 examples/docker/03_dind_feature/devcontainer.json create mode 100755 examples/docker/03_dind_feature/entrypoint.sh delete mode 100644 examples/docker/03_dind_rootless/Dockerfile create mode 100644 examples/docker/04_dind_rootless/Dockerfile rename examples/docker/{03_dind_rootless => 04_dind_rootless}/devcontainer.json (100%) rename examples/docker/{03_dind_rootless => 04_dind_rootless}/entrypoint.sh (100%) diff --git a/docs/docker.md b/docs/docker.md index 665ab7e5..f42e7af8 100644 --- a/docs/docker.md +++ b/docs/docker.md @@ -17,12 +17,13 @@ you are experimenting on your own workstation). Example: -```shell +```console docker run -it --rm \ -v /tmp/envbuilder:/workspaces \ -e ENVBUILDER_GIT_URL=https://github.com/coder/envbuilder \ -e ENVBUILDER_DEVCONTAINER_DIR=/workspaces/envbuilder/examples/docker/01_dood \ -e ENVBUILDER_INIT_SCRIPT=bash \ + -v /var/run/docker.socket:/var/run/docker.socket \ ghcr.io/coder/envbuilder:latest ``` @@ -43,7 +44,7 @@ Example: > create a custom entrypoint to start the Docker daemon in the background and > call this entrypoint via `ENVBUILDER_INIT_SCRIPT`. -```shell +```console docker run -it --rm \ --privileged \ -v /tmp/envbuilder:/workspaces \ @@ -53,7 +54,25 @@ docker run -it --rm \ ghcr.io/coder/envbuilder:latest ``` -This can also be accomplished using the [`docker-in-docker` Devcontainer feature](https://github.com/devcontainers/features/tree/main/src/docker-in-docker). +### DinD via Devcontainer Feature + +The above can also be accomplished using the [`docker-in-docker` Devcontainer +feature](https://github.com/devcontainers/features/tree/main/src/docker-in-docker). + +> Note: we still need the custom entrypoint to start the docker startup script. +> See https://github.com/devcontainers/features/blob/main/src/docker-in-docker/devcontainer-feature.json#L60 + +Example: + +```console +docker run -it --rm \ + --privileged \ + -v /tmp/envbuilder:/workspaces \ + -e ENVBUILDER_GIT_URL=https://github.com/coder/envbuilder \ + -e ENVBUILDER_DEVCONTAINER_DIR=/workspaces/envbuilder/examples/docker/03_dind_feature \ + -e ENVBUILDER_INIT_SCRIPT=/entrypoint.sh \ + ghcr.io/coder/envbuilder:latest +``` ## Rootless DinD @@ -71,7 +90,7 @@ then be a 'regular' user without root permissions. Example: -``` +```console docker run -it --rm \ --privileged \ -v /tmp/envbuilder:/workspaces \ @@ -94,7 +113,7 @@ including transparently enabling Docker inside workspaces. Most notably, it access inside their workspaces, if required. Example: -``` +```console docker run -it --rm \ -v /tmp/envbuilder:/workspaces \ -e ENVBUILDER_GIT_URL=https://github.com/coder/envbuilder \ diff --git a/examples/docker/01_dood/Dockerfile b/examples/docker/01_dood/Dockerfile index 8834c342..edc8d18f 100644 --- a/examples/docker/01_dood/Dockerfile +++ b/examples/docker/01_dood/Dockerfile @@ -1,2 +1,2 @@ -FROM ubuntu:latest +FROM ubuntu:noble RUN apt-get update && apt-get install -y docker.io \ No newline at end of file diff --git a/examples/docker/02_dind/Dockerfile b/examples/docker/02_dind/Dockerfile index 283dca7e..70a215b0 100644 --- a/examples/docker/02_dind/Dockerfile +++ b/examples/docker/02_dind/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:latest +FROM ubuntu:noble RUN apt-get update && \ apt-get install -y curl apt-transport-https && \ curl -fsSL https://get.docker.com/ | sh -s - diff --git a/examples/docker/03_dind_feature/Dockerfile b/examples/docker/03_dind_feature/Dockerfile new file mode 100644 index 00000000..12f1c1a0 --- /dev/null +++ b/examples/docker/03_dind_feature/Dockerfile @@ -0,0 +1,3 @@ +FROM ubuntu:noble +ADD entrypoint.sh /entrypoint.sh +ENTRYPOINT ["/entrypoint.sh"] \ No newline at end of file diff --git a/examples/docker/03_dind_feature/devcontainer.json b/examples/docker/03_dind_feature/devcontainer.json new file mode 100644 index 00000000..e1b5a18a --- /dev/null +++ b/examples/docker/03_dind_feature/devcontainer.json @@ -0,0 +1,8 @@ +{ + "build": { + "dockerfile": "Dockerfile" + }, + "features": { + "ghcr.io/devcontainers/features/docker-in-docker:2": {} + } +} \ No newline at end of file diff --git a/examples/docker/03_dind_feature/entrypoint.sh b/examples/docker/03_dind_feature/entrypoint.sh new file mode 100755 index 00000000..d18fb7dd --- /dev/null +++ b/examples/docker/03_dind_feature/entrypoint.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +set -euo pipefail + +/usr/local/share/docker-init.sh + +exec bash --login \ No newline at end of file diff --git a/examples/docker/03_dind_rootless/Dockerfile b/examples/docker/03_dind_rootless/Dockerfile deleted file mode 100644 index 36f1788f..00000000 --- a/examples/docker/03_dind_rootless/Dockerfile +++ /dev/null @@ -1,22 +0,0 @@ -FROM ubuntu:latest -## Install prerequisites -RUN apt-get update && \ - apt-get install -y apt-transport-https curl iproute2 uidmap -# Install Docker daemon -RUN curl -fsSL https://get.docker.com/ | sh -s - -# Add the ubuntu user to the Docker group -RUN usermod -aG docker ubuntu -# Add our custom entrypoint -ADD entrypoint.sh /entrypoint.sh -RUN chmod +x /entrypoint.sh -# Create the XDG_RUNTIME_DIR for our user and set DOCKER_HOST -ENV XDG_RUNTIME_DIR /run/user/1000 -RUN mkdir -p ${XDG_RUNTIME_DIR} && chown ubuntu:ubuntu ${XDG_RUNTIME_DIR} -ENV DOCKER_HOST unix:///${XDG_RUNTIME_DIR}/docker.sock -# Setup rootless mode as the ubuntu user. -USER ubuntu -RUN dockerd-rootless-setuptool.sh install -# Switch the ubuntu user to use the rootless docker context -RUN docker context use rootless -RUN mkdir -p /home/ubuntu/.local/share/docker -ENTRYPOINT ["/entrypoint.sh"] \ No newline at end of file diff --git a/examples/docker/04_dind_rootless/Dockerfile b/examples/docker/04_dind_rootless/Dockerfile new file mode 100644 index 00000000..5358ce60 --- /dev/null +++ b/examples/docker/04_dind_rootless/Dockerfile @@ -0,0 +1,24 @@ +FROM ubuntu:noble +# Based on UID of ubuntu user in container. +ENV XDG_RUNTIME_DIR /run/user/1000 +ENV DOCKER_HOST unix:///${XDG_RUNTIME_DIR}/docker.sock +# Setup as root +RUN apt-get update && \ + # Install prerequisites + apt-get install -y apt-transport-https curl iproute2 uidmap && \ + # Install Docker + curl -fsSL https://get.docker.com/ | sh -s - && \ + # Add ubuntu user to docker group + usermod -aG docker ubuntu && \ + # Create the XDG_RUNTIME_DIR for our user and set DOCKER_HOST + mkdir -p ${XDG_RUNTIME_DIR} && \ + chown ubuntu:ubuntu ${XDG_RUNTIME_DIR} + +# Setup rootless mode as the ubuntu user. +USER ubuntu +RUN dockerd-rootless-setuptool.sh install && \ + docker context use rootless && \ + mkdir -p /home/ubuntu/.local/share/docker +# Add our custom entrypoint +ADD entrypoint.sh /entrypoint.sh +ENTRYPOINT ["/entrypoint.sh"] \ No newline at end of file diff --git a/examples/docker/03_dind_rootless/devcontainer.json b/examples/docker/04_dind_rootless/devcontainer.json similarity index 100% rename from examples/docker/03_dind_rootless/devcontainer.json rename to examples/docker/04_dind_rootless/devcontainer.json diff --git a/examples/docker/03_dind_rootless/entrypoint.sh b/examples/docker/04_dind_rootless/entrypoint.sh similarity index 100% rename from examples/docker/03_dind_rootless/entrypoint.sh rename to examples/docker/04_dind_rootless/entrypoint.sh From fb0d7b9db2db5abd11a62ebace28db2359e9a9c8 Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Wed, 15 May 2024 13:35:00 +0000 Subject: [PATCH 4/4] fixup! address PR comments --- docs/docker.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docker.md b/docs/docker.md index f42e7af8..d11eb4d3 100644 --- a/docs/docker.md +++ b/docs/docker.md @@ -95,7 +95,7 @@ docker run -it --rm \ --privileged \ -v /tmp/envbuilder:/workspaces \ -e ENVBUILDER_GIT_URL=https://github.com/coder/envbuilder \ - -e ENVBUILDER_DEVCONTAINER_DIR=/workspaces/envbuilder/examples/docker/03_dind_rootless \ + -e ENVBUILDER_DEVCONTAINER_DIR=/workspaces/envbuilder/examples/docker/04_dind_rootless \ -e ENVBUILDER_INIT_SCRIPT=/entrypoint.sh \ ghcr.io/coder/envbuilder:latest ```