Skip to content

docker{,-rootful}.yaml: Use param in docker templates #2515

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
108 changes: 99 additions & 9 deletions examples/docker-rootful.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# $ export DOCKER_HOST=$(limactl list docker-rootful --format 'unix://{{.Dir}}/sock/docker.sock')
# $ docker ...

# This template requires Lima v0.20.0 or later
# This template requires Lima v0.23.0 or later
images:
# Try to use release-yyyyMMdd image if available. Note that release-yyyyMMdd will be removed after several months.
- location: "https://cloud-images.ubuntu.com/releases/24.04/release-20240423/ubuntu-24.04-server-cloudimg-amd64.img"
Expand Down Expand Up @@ -44,16 +44,95 @@ provision:
#!/bin/bash
set -eux -o pipefail
command -v docker >/dev/null 2>&1 && exit 0
if [ ! -e /etc/systemd/system/docker.socket.d/override.conf ]; then
mkdir -p /etc/systemd/system/docker.socket.d
readonly override_conf=/etc/systemd/system/docker.socket.d/override.conf
if [ ! -e $override_conf ]; then
mkdir -p $(dirname $override_conf)
# Alternatively we could just add the user to the "docker" group, but that requires restarting the user session
cat <<-EOF >/etc/systemd/system/docker.socket.d/override.conf
[Socket]
SocketUser={{.User}}
cat <<EOF >$override_conf
[Socket]
SocketUser={{.User}}
EOF
fi
export DEBIAN_FRONTEND=noninteractive
curl -fsSL https://get.docker.com | sh
- mode: user # configure docker under non-root user
script: |
#!/bin/bash
set -o errexit -o nounset -o pipefail -o xtrace

if ! command -v jq &>/dev/null; then
sudo apt-get install --assume-yes jq
fi
if systemctl --user list-unit-files docker.service &>/dev/null; then
readonly rootless_installed=true
else
readonly rootless_installed=false
fi

# Setting shell variable makes it easier to read cloud-init-output.log
readonly ROOTFUL="{{.Param.ROOTFUL}}"
if [ "$ROOTFUL" = true ]; then
if [ $rootless_installed = true ]; then
systemctl --user disable --now docker
fi

readonly config_dir=/etc/docker
readonly context=default
function systemctl_wrapper() { sudo systemctl "$@"; }
function tee_wrapper() { sudo tee "$@"; }
else
sudo systemctl disable --now docker
if [ $rootless_installed != true ]; then
sudo apt-get install --assume-yes dbus-user-session fuse3 uidmap
if [ -S /var/run/docker.sock ]; then
sudo rm /var/run/docker.sock
fi
dockerd-rootless-setuptool.sh install
fi

readonly config_dir="$HOME/.config/docker"
readonly context=rootless
function systemctl_wrapper() { systemctl --user "$@"; }
function tee_wrapper() { tee "$@"; }
fi

systemctl_wrapper enable --now docker
docker context use $context

readonly config="$config_dir/daemon.json"
function print_config() {
if [ -s "$config" ]; then
cat "$config"
else
# print empty JSON object instead of empty string for jq to work
echo "{}"
fi
}
needs_restart=false
function set_docker_daemon_json() {
local -r current=$(print_config | jq --raw-output "$1 // empty")
[ "$current" = "$2" ] && return 0
mkdir -p "$config_dir"
# sleep 0 is a trick to avoid tee_wrapper overwriting the file before reading it
if print_config | jq "$1 = ${2:-empty}" | (sleep 0 && tee_wrapper "$config"); then
needs_restart=true
fi
}

# Setting shell variable makes it easier to read cloud-init-output.log
readonly CONTAINERD_IMAGE_STORE="{{.Param.CONTAINERD_IMAGE_STORE}}"
# enable containerd image store
if [ "$CONTAINERD_IMAGE_STORE" = true ]; then
set_docker_daemon_json '.features."containerd-snapshotter"' 'true'
else
# passing empty string to remove the key and use the default value
set_docker_daemon_json '.features."containerd-snapshotter"' ''
fi

# restart docker to apply the new configuration
if [ $needs_restart = true ]; then
systemctl_wrapper restart docker
fi
probes:
- script: |
#!/bin/bash
Expand All @@ -62,8 +141,16 @@ probes:
echo >&2 "docker is not installed yet"
exit 1
fi
if ! timeout 30s bash -c "until pgrep dockerd; do sleep 3; done"; then
echo >&2 "dockerd is not running"
readonly ROOTFUL="{{.Param.ROOTFUL}}"
if [ "$ROOTFUL" = true ]; then
target=dockerd
target_description=dockerd
else
target=rootlesskit
target_description="rootlesskit (used by rootless docker)"
fi
if ! timeout 30s bash -c "until pgrep $target; do sleep 3; done"; then
echo >&2 "$target_description is not running"
exit 1
fi
hint: See "/var/log/cloud-init-output.log" in the guest
Expand All @@ -73,7 +160,7 @@ hostResolver:
hosts:
host.docker.internal: host.lima.internal
portForwards:
- guestSocket: "/var/run/docker.sock"
- guestSocket: "{{if eq .Param.ROOTFUL \"true\"}}/var/run{{else}}/run/user/{{.UID}}{{end}}/docker.sock"
hostSocket: "{{.Dir}}/sock/docker.sock"
message: |
To run `docker` on the host (assumes docker-cli is installed), run the following commands:
Expand All @@ -82,3 +169,6 @@ message: |
docker context use lima-{{.Name}}
docker run hello-world
------
param:
CONTAINERD_IMAGE_STORE: false
ROOTFUL: true
112 changes: 100 additions & 12 deletions examples/docker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# $ export DOCKER_HOST=$(limactl list docker --format 'unix://{{.Dir}}/sock/docker.sock')
# $ docker ...

# This template requires Lima v0.8.0 or later
# This template requires Lima v0.23.0 or later
images:
# Try to use release-yyyyMMdd image if available. Note that release-yyyyMMdd will be removed after several months.
- location: "https://cloud-images.ubuntu.com/releases/24.04/release-20240423/ubuntu-24.04-server-cloudimg-amd64.img"
Expand Down Expand Up @@ -44,18 +44,95 @@ provision:
#!/bin/bash
set -eux -o pipefail
command -v docker >/dev/null 2>&1 && exit 0
readonly override_conf=/etc/systemd/system/docker.socket.d/override.conf
if [ ! -e $override_conf ]; then
mkdir -p $(dirname $override_conf)
# Alternatively we could just add the user to the "docker" group, but that requires restarting the user session
cat <<EOF >$override_conf
[Socket]
SocketUser={{.User}}
EOF
fi
export DEBIAN_FRONTEND=noninteractive
curl -fsSL https://get.docker.com | sh
# NOTE: you may remove the lines below, if you prefer to use rootful docker, not rootless
systemctl disable --now docker
apt-get install -y uidmap dbus-user-session
- mode: user
- mode: user # configure docker under non-root user
script: |
#!/bin/bash
set -eux -o pipefail
systemctl --user start dbus
dockerd-rootless-setuptool.sh install
docker context use rootless
set -o errexit -o nounset -o pipefail -o xtrace

if ! command -v jq &>/dev/null; then
sudo apt-get install --assume-yes jq
fi
if systemctl --user list-unit-files docker.service &>/dev/null; then
readonly rootless_installed=true
else
readonly rootless_installed=false
fi

# Setting shell variable makes it easier to read cloud-init-output.log
readonly ROOTFUL="{{.Param.ROOTFUL}}"
if [ "$ROOTFUL" = true ]; then
if [ $rootless_installed = true ]; then
systemctl --user disable --now docker
fi

readonly config_dir=/etc/docker
readonly context=default
function systemctl_wrapper() { sudo systemctl "$@"; }
function tee_wrapper() { sudo tee "$@"; }
else
sudo systemctl disable --now docker
if [ $rootless_installed != true ]; then
sudo apt-get install --assume-yes dbus-user-session fuse3 uidmap
if [ -S /var/run/docker.sock ]; then
sudo rm /var/run/docker.sock
fi
dockerd-rootless-setuptool.sh install
fi

readonly config_dir="$HOME/.config/docker"
readonly context=rootless
function systemctl_wrapper() { systemctl --user "$@"; }
function tee_wrapper() { tee "$@"; }
fi

systemctl_wrapper enable --now docker
docker context use $context

readonly config="$config_dir/daemon.json"
function print_config() {
if [ -s "$config" ]; then
cat "$config"
else
# print empty JSON object instead of empty string for jq to work
echo "{}"
fi
}
needs_restart=false
function set_docker_daemon_json() {
local -r current=$(print_config | jq --raw-output "$1 // empty")
[ "$current" = "$2" ] && return 0
mkdir -p "$config_dir"
# sleep 0 is a trick to avoid tee_wrapper overwriting the file before reading it
if print_config | jq "$1 = ${2:-empty}" | (sleep 0 && tee_wrapper "$config"); then
needs_restart=true
fi
}

# Setting shell variable makes it easier to read cloud-init-output.log
readonly CONTAINERD_IMAGE_STORE="{{.Param.CONTAINERD_IMAGE_STORE}}"
# enable containerd image store
if [ "$CONTAINERD_IMAGE_STORE" = true ]; then
set_docker_daemon_json '.features."containerd-snapshotter"' 'true'
else
# passing empty string to remove the key and use the default value
set_docker_daemon_json '.features."containerd-snapshotter"' ''
fi

# restart docker to apply the new configuration
if [ $needs_restart = true ]; then
systemctl_wrapper restart docker
fi
probes:
- script: |
#!/bin/bash
Expand All @@ -64,8 +141,16 @@ probes:
echo >&2 "docker is not installed yet"
exit 1
fi
if ! timeout 30s bash -c "until pgrep rootlesskit; do sleep 3; done"; then
echo >&2 "rootlesskit (used by rootless docker) is not running"
readonly ROOTFUL="{{.Param.ROOTFUL}}"
if [ "$ROOTFUL" = true ]; then
target=dockerd
target_description=dockerd
else
target=rootlesskit
target_description="rootlesskit (used by rootless docker)"
fi
if ! timeout 30s bash -c "until pgrep $target; do sleep 3; done"; then
echo >&2 "$target_description is not running"
exit 1
fi
hint: See "/var/log/cloud-init-output.log" in the guest
Expand All @@ -75,7 +160,7 @@ hostResolver:
hosts:
host.docker.internal: host.lima.internal
portForwards:
- guestSocket: "/run/user/{{.UID}}/docker.sock"
- guestSocket: "{{if eq .Param.ROOTFUL \"true\"}}/var/run{{else}}/run/user/{{.UID}}{{end}}/docker.sock"
hostSocket: "{{.Dir}}/sock/docker.sock"
message: |
To run `docker` on the host (assumes docker-cli is installed), run the following commands:
Expand All @@ -84,3 +169,6 @@ message: |
docker context use lima-{{.Name}}
docker run hello-world
------
param:
CONTAINERD_IMAGE_STORE: false
ROOTFUL: false
Loading