Files
2026-04-28 10:05:39 +08:00

111 lines
4.0 KiB
YAML

# CubeSandbox running inside a privileged systemd+DinD container.
#
# WHY THIS LOOKS UNUSUAL
# ----------------------
# CubeSandbox is NOT a containerized project upstream. Its core components
# (Cubelet, network-agent, cube-shim, CubeAPI, CubeMaster) ship as host
# binaries, and the official install.sh registers them as systemd units and
# manages them with systemctl.
#
# To run it purely with Docker without modifying the WSL2 host, this stack:
# 1. Runs systemd as PID 1 inside a privileged container so that
# install.sh can call systemctl enable / start / status normally.
# 2. Runs its own dockerd (DinD) for MySQL / Redis / CoreDNS / CubeProxy.
# 3. Mounts an XFS loop volume at /data/cubelet (install.sh hard-requires XFS).
# 4. Executes the upstream online-install.sh via cube-install.service.
#
# The /run and /run/lock paths are tmpfs so systemd can write its runtime
# state (PID files, socket files, etc.) during the container lifetime.
# stop_signal RTMIN+3 is the standard graceful-shutdown signal for systemd.
x-defaults: &defaults
restart: unless-stopped
logging:
driver: json-file
options:
max-size: 100m
max-file: '3'
services:
cube-sandbox:
<<: *defaults
image: ${GLOBAL_REGISTRY:-}compose-anything/cube-sandbox:${CUBE_SANDBOX_VERSION:-0.1.7}
build:
context: .
dockerfile: Dockerfile
args:
- UBUNTU_IMAGE=${UBUNTU_IMAGE:-ubuntu:22.04}
# CubeSandbox needs:
# - /dev/kvm for the MicroVM hypervisor
# - /dev/net/tun for cube TAP interfaces
# - SYS_ADMIN/NET_ADMIN to mount the XFS loop volume and create TAPs
# - Its own dockerd for MySQL / Redis / CubeProxy / CoreDNS
# - systemd as PID 1 so install.sh can register and start services
# The simplest correct configuration is privileged + host network.
privileged: true
network_mode: host
devices:
- /dev/kvm:/dev/kvm
- /dev/net/tun:/dev/net/tun
# cgroupns:host lets the in-container systemd + dockerd share the host's
# (i.e. WSL2's) cgroup v2 hierarchy directly — more reliable than private.
cgroup: host
# systemd needs to write its runtime state to /run; use tmpfs so it does
# not leak across container restarts and does not consume the named volumes.
tmpfs:
- /run:size=100m
- /run/lock:size=10m
- /tmp:size=2g,exec
# SIGRTMIN+3 is the proper graceful-shutdown signal for systemd.
stop_signal: RTMIN+3
environment:
- TZ=${TZ:-Asia/Shanghai}
# cn = pull installer + images via the cnb.cool / Tencent Cloud mirror
# gh = pull from raw.githubusercontent.com (slower in mainland China)
- CUBE_MIRROR=${CUBE_MIRROR:-cn}
# Size of the XFS loop file that backs /data/cubelet
- CUBE_XFS_SIZE=${CUBE_XFS_SIZE:-50G}
# Set to 1 to re-run install.sh even if a previous install is detected
- CUBE_FORCE_REINSTALL=${CUBE_FORCE_REINSTALL:-0}
volumes:
# DinD docker daemon storage (images for MySQL, Redis, CoreDNS, CubeProxy)
- cube_dind_data:/var/lib/docker
# XFS loop image + mounted /data/cubelet + cube-shim disks + logs
- cube_data:/data
# Installed CubeSandbox binaries & scripts
- cube_toolbox:/usr/local/services/cubetoolbox
# No `ports:` block — we use network_mode: host so the CubeAPI on
# 127.0.0.1:3000 inside the container is the same socket as
# 127.0.0.1:3000 on the WSL2 host.
healthcheck:
test:
- CMD-SHELL
- "curl -fsS http://127.0.0.1:3000/health && curl -fsS http://127.0.0.1:8089/notify/health && curl -fsS http://127.0.0.1:19090/healthz"
interval: 30s
timeout: 15s
retries: 5
start_period: 600s # First boot downloads ~400 MB + Docker images; be generous.
deploy:
resources:
limits:
cpus: '${CUBE_CPU_LIMIT:-8}'
memory: ${CUBE_MEMORY_LIMIT:-16G}
reservations:
cpus: '${CUBE_CPU_RESERVATION:-2}'
memory: ${CUBE_MEMORY_RESERVATION:-8G}
volumes:
cube_dind_data:
cube_data:
cube_toolbox: