Skip to content

Commit e4a8e4b

Browse files
johnstcnmafredri
authored andcommitted
chore: update dind examples to use onCreateCommand (#350)
(cherry picked from commit 7c8e6a4)
1 parent 6ffa021 commit e4a8e4b

File tree

12 files changed

+115
-40
lines changed

12 files changed

+115
-40
lines changed

docs/docker.md

+16-9
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ from inside Envbuilder.
99
> you may need to instead add the relevant content of the init script to your
1010
> agent startup script in your template.
1111
> For example:
12-
> ```
12+
>
13+
> ```terraform
1314
> resource "coder_agent" "dev" {
1415
> ...
1516
> startup_script = <<-EOT
@@ -43,7 +44,6 @@ docker run -it --rm \
4344
ghcr.io/coder/envbuilder:latest
4445
```
4546
46-
4747
## Docker-in-Docker (DinD)
4848

4949
**Security:** Low
@@ -57,16 +57,16 @@ Example:
5757

5858
> Note that due to a lack of init system, the Docker daemon
5959
> needs to be started separately inside the container. In this example, we
60-
> create a custom entrypoint to start the Docker daemon in the background and
61-
> call this entrypoint via `ENVBUILDER_INIT_SCRIPT`.
60+
> create a custom script to start the Docker daemon in the background and
61+
> call this entrypoint via the Devcontainer `onCreateCommand` lifecycle hook.
6262
6363
```console
6464
docker run -it --rm \
6565
--privileged \
6666
-v /tmp/envbuilder:/workspaces \
6767
-e ENVBUILDER_GIT_URL=https://github.com/coder/envbuilder \
6868
-e ENVBUILDER_DEVCONTAINER_DIR=/workspaces/envbuilder/examples/docker/02_dind \
69-
-e ENVBUILDER_INIT_SCRIPT=/entrypoint.sh \
69+
-e ENVBUILDER_INIT_SCRIPT=bash \
7070
ghcr.io/coder/envbuilder:latest
7171
```
7272

@@ -75,8 +75,14 @@ docker run -it --rm \
7575
The above can also be accomplished using the [`docker-in-docker` Devcontainer
7676
feature](https://github.com/devcontainers/features/tree/main/src/docker-in-docker).
7777

78-
> Note: we still need the custom entrypoint to start the docker startup script.
79-
> See https://github.com/devcontainers/features/blob/main/src/docker-in-docker/devcontainer-feature.json#L60
78+
> Note: we still need the `onCreateCommand` to start Docker.
79+
> See
80+
> [here](https://github.com/devcontainers/features/blob/main/src/docker-in-docker/devcontainer-feature.json#L65)
81+
> for more details.
82+
>
83+
> Known issue: `/run` does not get symlinked correctly to `/var/run`.
84+
> To work around this, we create the symlink manually before running
85+
> the script to start the Docker daemon.
8086
8187
Example:
8288

@@ -86,7 +92,7 @@ docker run -it --rm \
8692
-v /tmp/envbuilder:/workspaces \
8793
-e ENVBUILDER_GIT_URL=https://github.com/coder/envbuilder \
8894
-e ENVBUILDER_DEVCONTAINER_DIR=/workspaces/envbuilder/examples/docker/03_dind_feature \
89-
-e ENVBUILDER_INIT_SCRIPT=/entrypoint.sh \
95+
-e ENVBUILDER_INIT_SCRIPT=bash \
9096
ghcr.io/coder/envbuilder:latest
9197
```
9298

@@ -95,7 +101,7 @@ docker run -it --rm \
95101
**Security:** Medium
96102
**Convenience:** Medium
97103

98-
This approach runs a Docker daemon in *rootless* mode.
104+
This approach runs a Docker daemon in _rootless_ mode.
99105
While this still requires a privileged container, this allows you to restrict
100106
usage of the `root` user inside the container, as the Docker daemon will be run
101107
under a "fake" root user (via `rootlesskit`). The user inside the workspace can
@@ -129,6 +135,7 @@ including transparently enabling Docker inside workspaces. Most notably, it
129135
access inside their workspaces, if required.
130136

131137
Example:
138+
132139
```console
133140
docker run -it --rm \
134141
-v /tmp/envbuilder:/workspaces \

examples/docker/02_dind/Dockerfile

+21-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,23 @@
11
FROM ubuntu:noble
2+
3+
# Install Docker using Docker's convenience script.
24
RUN apt-get update && \
3-
apt-get install -y curl apt-transport-https && \
4-
curl -fsSL https://get.docker.com/ | sh -s -
5-
ADD entrypoint.sh /entrypoint.sh
6-
ENTRYPOINT ["/entrypoint.sh"]
5+
apt-get install -y curl sudo apt-transport-https && \
6+
curl -fsSL https://get.docker.com/ | sh -s -
7+
8+
# The ubuntu:noble image includes a non-root user by default,
9+
# but it does not have sudo privileges. We need to set this up.
10+
# Note: we chown /var/run/docker.sock to the non-root user
11+
# in the onCreateCommand script. Ideally you would add the
12+
# non-root user to the docker group, but in this scenario
13+
# this is a 'single-user' environment. It also avoids us
14+
# having to run `newgrp docker`.
15+
RUN echo "ubuntu ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/ubuntu
16+
17+
# Add our onCreateCommand script.
18+
ADD on-create.sh /on-create.sh
19+
20+
# Switch to the non-root user.
21+
USER ubuntu
22+
23+
ENTRYPOINT ["bash"]
+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"build": {
33
"dockerfile": "Dockerfile"
4-
}
5-
}
4+
},
5+
"onCreateCommand": "/on-create.sh"
6+
}

examples/docker/02_dind/entrypoint.sh

-7
This file was deleted.

examples/docker/02_dind/on-create.sh

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/usr/bin/env bash
2+
3+
set -euo pipefail
4+
5+
# Start Docker in the background.
6+
sudo -u root /bin/sh -c 'nohup dockerd > /var/log/docker.log &'
7+
8+
# Wait up to 10 seconds for Docker to start.
9+
for attempt in $(seq 1 10); do
10+
if [[ $attempt -eq 10 ]]; then
11+
echo "Failed to start Docker"
12+
exit 1
13+
fi
14+
if [[ ! -e /var/run/docker.sock ]]; then
15+
sleep 1
16+
else
17+
break
18+
fi
19+
done
20+
21+
# Change the owner of the Docker socket so that the non-root user can use it.
22+
sudo chown ubuntu:docker /var/run/docker.sock
+21-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,22 @@
11
FROM ubuntu:noble
2-
ADD entrypoint.sh /entrypoint.sh
3-
ENTRYPOINT ["/entrypoint.sh"]
2+
3+
# Install some dependencies such as curl and sudo.
4+
# Also set up passwordless sudo for the ubuntu user.
5+
RUN apt-get update && \
6+
DEBIAN_FRONTEND=noninteractive apt-get install -y \
7+
curl \
8+
sudo \
9+
apt-transport-https && \
10+
echo "ubuntu ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/ubuntu
11+
12+
# Add our onCreateCommand script.
13+
ADD on-create.sh /on-create.sh
14+
15+
# Switch to the non-root user.
16+
USER ubuntu
17+
18+
# The devcontainer feature provides /usr/local/share/docker-init.sh
19+
# which will handle most of the steps of setting up Docker.
20+
# We can't put this in the entrypoint as it gets overridden, so
21+
# we call it in the on-create script.
22+
ENTRYPOINT ["bash"]

examples/docker/03_dind_feature/devcontainer.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
"build": {
33
"dockerfile": "Dockerfile"
44
},
5+
"onCreateCommand": "/on-create.sh",
56
"features": {
67
"ghcr.io/devcontainers/features/docker-in-docker:2": {}
78
}
8-
}
9+
}

examples/docker/03_dind_feature/entrypoint.sh

-7
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/usr/bin/env bash
2+
3+
set -euo pipefail
4+
5+
# Known issue: Kaniko does not symlink /run => /var/run properly.
6+
# This results in /var/run/ being owned by root:root which interferes
7+
# with accessing the Docker socket even if the permissions are set
8+
# correctly. Workaround: symlink it manually
9+
sudo ln -s /run /var/run
10+
11+
# Run the docker init script. This needs to be
12+
# run as root. It will take care of starting the
13+
# daemon and adding the ubuntu user to the docker
14+
# group.
15+
sudo /usr/local/share/docker-init.sh
16+
17+
# Change the owner of the Docker socket so that the non-root user can use it.
18+
sudo chown ubuntu:docker /var/run/docker.sock

examples/docker/04_dind_rootless/Dockerfile

+8-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
FROM ubuntu:noble
2+
23
# Based on UID of ubuntu user in container.
34
ENV XDG_RUNTIME_DIR /run/user/1000
45
ENV DOCKER_HOST unix:///${XDG_RUNTIME_DIR}/docker.sock
6+
57
# Setup as root
8+
USER root
69
RUN apt-get update && \
710
# Install prerequisites
811
apt-get install -y apt-transport-https curl iproute2 uidmap && \
@@ -19,6 +22,8 @@ USER ubuntu
1922
RUN dockerd-rootless-setuptool.sh install && \
2023
docker context use rootless && \
2124
mkdir -p /home/ubuntu/.local/share/docker
22-
# Add our custom entrypoint
23-
ADD entrypoint.sh /entrypoint.sh
24-
ENTRYPOINT ["/entrypoint.sh"]
25+
26+
# Add our onCreateCommand script.
27+
ADD on-create.sh /on-create.sh
28+
29+
ENTRYPOINT ["bash"]
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"build": {
33
"dockerfile": "Dockerfile"
4-
}
5-
}
4+
},
5+
"onCreateCommand": "/on-create.sh"
6+
}

examples/docker/04_dind_rootless/entrypoint.sh renamed to examples/docker/04_dind_rootless/on-create.sh

+1-3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,4 @@
33
set -euo pipefail
44

55
# Start the rootless docker daemon as a non-root user
6-
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 &
7-
8-
exec bash --login
6+
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 &

0 commit comments

Comments
 (0)