diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..63d5305 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,10 @@ +{ + "permissions": { + "allow": [ + "Bash(find:*)", + "Bash(tree:*)" + ], + "deny": [], + "ask": [] + } +} diff --git a/.env.scripts b/.env.scripts index b047e4b..1804507 100644 --- a/.env.scripts +++ b/.env.scripts @@ -73,7 +73,7 @@ DEFAULT_DATA_DIR="/usr/local/share/template-files/data" DEFAULT_CONF_DIR="/usr/local/share/template-files/config" DEFAULT_TEMPLATE_DIR="/usr/local/share/template-files/defaults" # - - - - - - - - - - - - - - - - - - - - - - - - - -ENV_PACKAGES="fuse-overlayfs btrfs-progs xfsprogs e2fsprogs e2fsprogs-extra zfs git ip6tables iptables openssl pigz shadow-uidmap xz docker openssh" +ENV_PACKAGES="cgroup-tools fuse-overlayfs btrfs-progs xfsprogs e2fsprogs e2fsprogs-extra zfs git ip6tables iptables openssl pigz shadow-uidmap xz docker openssh" # - - - - - - - - - - - - - - - - - - - - - - - - - # ex: ts=2 sw=2 et filetype=sh # - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Dockerfile b/Dockerfile index f4d4007..b041ec1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -54,7 +54,7 @@ ARG PHP_SERVER ARG SHELL_OPTS ARG PATH -ARG PACK_LIST="fuse-overlayfs btrfs-progs xfsprogs e2fsprogs e2fsprogs-extra zfs git ip6tables iptables openssl pigz shadow-uidmap xz docker openssh " +ARG PACK_LIST="fuse-overlayfs btrfs-progs xfsprogs e2fsprogs e2fsprogs-extra zfs git ip6tables iptables openssl pigz shadow-uidmap xz docker openssh cgroup-tools " ENV ENV=~/.profile ENV SHELL="/bin/sh" diff --git a/rootfs/tmp/etc/docker/daemon.json b/rootfs/tmp/etc/docker/daemon.json index 3823d75..1bacecd 100644 --- a/rootfs/tmp/etc/docker/daemon.json +++ b/rootfs/tmp/etc/docker/daemon.json @@ -4,5 +4,6 @@ "log-level": "error", "experimental": true, "pidfile": "/tmp/docker.pid", + "cgroup-parent": "/docker", "insecure-registries": ["localhost"] } diff --git a/rootfs/usr/local/bin/entrypoint.sh b/rootfs/usr/local/bin/entrypoint.sh index 1c386d9..f663fd3 100755 --- a/rootfs/usr/local/bin/entrypoint.sh +++ b/rootfs/usr/local/bin/entrypoint.sh @@ -223,10 +223,32 @@ mkdir -p "/usr/local/etc/docker/exec" touch "/data/logs/start.log" touch "/data/logs/entrypoint.log" # - - - - - - - - - - - - - - - - - - - - - - - - - -# Enable cgroup v2 delegation for Docker-in-Docker +# Setup cgroups v2 for Docker-in-Docker without mounting host cgroups +if ! mountpoint -q /sys/fs/cgroup 2>/dev/null; then + mkdir -p /sys/fs/cgroup + mount -t cgroup2 none /sys/fs/cgroup 2>/dev/null || true +fi +# Enable cgroup v2 controller delegation if [ -f "/sys/fs/cgroup/cgroup.controllers" ]; then + # Create init cgroup and move processes out of root (required for subtree_control) + [ -d "/sys/fs/cgroup/init" ] || mkdir -p /sys/fs/cgroup/init + if [ -f "/sys/fs/cgroup/cgroup.procs" ] && [ -w "/sys/fs/cgroup/init/cgroup.procs" ]; then + while read -r pid; do + echo "$pid" > /sys/fs/cgroup/init/cgroup.procs 2>/dev/null || true + done < /sys/fs/cgroup/cgroup.procs + fi + # Enable controllers at root level if [ -w "/sys/fs/cgroup/cgroup.subtree_control" ]; then - cat /sys/fs/cgroup/cgroup.controllers > /sys/fs/cgroup/cgroup.subtree_control 2>/dev/null || true + for controller in $(cat /sys/fs/cgroup/cgroup.controllers 2>/dev/null); do + echo "+$controller" > /sys/fs/cgroup/cgroup.subtree_control 2>/dev/null || true + done + fi + # Create docker cgroup for Docker-in-Docker + [ -d "/sys/fs/cgroup/docker" ] || mkdir -p /sys/fs/cgroup/docker + if [ -f "/sys/fs/cgroup/docker/cgroup.subtree_control" ]; then + for controller in $(cat /sys/fs/cgroup/cgroup.controllers 2>/dev/null); do + echo "+$controller" > /sys/fs/cgroup/docker/cgroup.subtree_control 2>/dev/null || true + done fi fi # - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rootfs/usr/local/etc/docker/init.d/05-dockerd.sh b/rootfs/usr/local/etc/docker/init.d/05-dockerd.sh index f1f2247..c8efc9a 100755 --- a/rootfs/usr/local/etc/docker/init.d/05-dockerd.sh +++ b/rootfs/usr/local/etc/docker/init.d/05-dockerd.sh @@ -227,13 +227,75 @@ __run_pre_execute_checks() { __banner "$pre_execute_checks_MessageST" # Put command to execute in parentheses { - # Fix cgroup v2 delegation for Docker-in-Docker + # Setup cgroups v2 for Docker-in-Docker without mounting host cgroups + echo "Setting up cgroups v2 for Docker-in-Docker" + + # Check if cgroup2 filesystem needs to be mounted + if ! mountpoint -q /sys/fs/cgroup 2>/dev/null; then + echo "Mounting cgroup2 filesystem" + mkdir -p /sys/fs/cgroup + mount -t cgroup2 none /sys/fs/cgroup || { + echo "Warning: Failed to mount cgroup2 filesystem" + } + fi + + # Verify we have cgroup v2 (unified hierarchy) if [ -f "/sys/fs/cgroup/cgroup.controllers" ]; then - echo "Enabling cgroup v2 delegation for Docker-in-Docker" - # Enable all available controllers at root - if [ -w "/sys/fs/cgroup/cgroup.subtree_control" ]; then - cat /sys/fs/cgroup/cgroup.controllers >/sys/fs/cgroup/cgroup.subtree_control 2>/dev/null || true + echo "Detected cgroup v2 (unified hierarchy)" + + # Get available controllers + CONTROLLERS=$(cat /sys/fs/cgroup/cgroup.controllers 2>/dev/null) + echo "Available controllers: $CONTROLLERS" + + # In cgroups v2, we need to move all processes out of root cgroup + # before we can enable subtree_control (no internal processes rule) + + # Create init cgroup for system processes (including PID 1) + if [ ! -d "/sys/fs/cgroup/init" ]; then + echo "Creating init cgroup for system processes" + mkdir -p /sys/fs/cgroup/init fi + + # Move all root cgroup processes to init cgroup + # This allows us to enable subtree_control at root level + if [ -f "/sys/fs/cgroup/cgroup.procs" ] && [ -w "/sys/fs/cgroup/init/cgroup.procs" ]; then + echo "Moving processes to init cgroup" + while read -r pid; do + echo "$pid" > /sys/fs/cgroup/init/cgroup.procs 2>/dev/null || true + done < /sys/fs/cgroup/cgroup.procs + fi + + # Now enable controllers at root level (after processes moved out) + if [ -w "/sys/fs/cgroup/cgroup.subtree_control" ]; then + echo "Enabling cgroup v2 controller delegation at root" + for controller in $CONTROLLERS; do + echo "+$controller" > /sys/fs/cgroup/cgroup.subtree_control 2>/dev/null || true + done + fi + + # Create docker cgroup - this creates proper cgroup with interface files + if [ ! -d "/sys/fs/cgroup/docker" ]; then + echo "Creating docker cgroup" + mkdir -p /sys/fs/cgroup/docker + fi + + # Enable controllers in docker cgroup for nested containers + if [ -f "/sys/fs/cgroup/docker/cgroup.subtree_control" ]; then + echo "Enabling controllers in docker cgroup" + for controller in $CONTROLLERS; do + echo "+$controller" > /sys/fs/cgroup/docker/cgroup.subtree_control 2>/dev/null || true + done + fi + + # Verify setup + if [ -f "/sys/fs/cgroup/docker/cgroup.subtree_control" ]; then + echo "Docker cgroup setup successful" + echo "Enabled controllers: $(cat /sys/fs/cgroup/docker/cgroup.subtree_control 2>/dev/null)" + else + echo "Warning: Docker cgroup subtree_control not available" + fi + else + echo "Warning: cgroup v2 not available, Docker-in-Docker may have limited functionality" fi [ -L "/config/docker/daemon.json" ] && unlink "/config/docker/daemon.json" if [ -n "$DOCKER_REGISTRIES" ]; then @@ -275,6 +337,7 @@ EOF "log-level": "error", "experimental": true, "pidfile": "/tmp/docker.pid", + "cgroup-parent": "/docker", "insecure-registries": [$registry] } EOF @@ -285,7 +348,8 @@ EOF "iptables": true, "log-level": "error", "experimental": true, - "pidfile": "/tmp/docker.pid" + "pidfile": "/tmp/docker.pid", + "cgroup-parent": "/docker" } EOF fi