用 Docker 准备节点

普通 Docker 容器里没有 systemd,装不上节点环境。按下面的步骤创建一个运行 systemd 的 Ubuntu 24.04 容器,再到控制台添加。

适用范围:你有一台 Linux 服务器的 root 权限,能自己运行 docker。如果你的服务器本身就是服务商提供的 Docker 或 NAT 容器,没法在里面再运行 Docker,请改用 Ubuntu 24.04 的 KVM 云服务器。

0. 检查宿主机

uname -m                      # 必须是 x86_64
stat -fc %T /sys/fs/cgroup    # 应为 cgroup2fs
nproc; free -g; df -h /var/lib/docker

至少 2 核;内存建议 4 GiB 以上(最低 1.8 GiB);Docker 数据盘至少 6 GiB 可用,建议 15 GiB 以上。

1. 新建一个目录,把下面的内容保存为 Dockerfile

# syntax=docker/dockerfile:1
FROM ubuntu:24.04
ENV container=docker
RUN printf '#!/bin/sh\nexit 101\n' > /usr/sbin/policy-rc.d \
 && apt-get update \
 && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
      systemd systemd-sysv dbus openssh-server python3 sudo ca-certificates curl iproute2 \
 && rm -rf /var/lib/apt/lists/* /etc/ssh/ssh_host_* \
 && rm /usr/sbin/policy-rc.d \
 && truncate -s 0 /etc/machine-id \
 && mkdir -p /etc/node-ssh /etc/ssh/node-hostkeys \
 && systemctl mask getty.target getty@.service serial-getty@.service \
      console-getty.service console-shell.service \
      sys-kernel-debug.mount sys-kernel-tracing.mount sys-kernel-config.mount dev-hugepages.mount \
 && systemctl disable ssh.socket \
 && systemctl enable ssh.service
COPY <<"EOF" /etc/ssh/sshd_config
Port 22
PermitRootLogin prohibit-password
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitEmptyPasswords no
AuthenticationMethods publickey
AuthorizedKeysFile /etc/node-ssh/authorized_keys
HostKey /etc/ssh/node-hostkeys/ssh_host_ed25519_key
HostKey /etc/ssh/node-hostkeys/ssh_host_rsa_key
UsePAM yes
StrictModes yes
PrintMotd no
Subsystem sftp internal-sftp
EOF
COPY --chmod=0755 <<"EOF" /usr/local/sbin/node-hostkeys
#!/bin/sh
set -eu
dir=/etc/ssh/node-hostkeys
install -d -m 0700 "$dir"
for type in ed25519 rsa; do
    key="$dir/ssh_host_${type}_key"
    [ -f "$key" ] || ssh-keygen -q -t "$type" -N '' -f "$key"
    chmod 0600 "$key"
    [ -f "$key.pub" ] || ssh-keygen -y -f "$key" > "$key.pub"
    chmod 0644 "$key.pub"
done
EOF
COPY --chmod=0755 <<"EOF" /usr/local/sbin/node-init
#!/bin/sh
set -eu
mount -o remount,rw /sys/fs/cgroup
exec "$@"
EOF
COPY <<"EOF" /etc/systemd/system/node-hostkeys.service
[Unit]
Description=Persistent SSH host keys
Before=ssh.service
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/node-hostkeys
RemainAfterExit=yes
EOF
COPY <<"EOF" /etc/systemd/system/ssh.service.d/node.conf
[Unit]
Requires=node-hostkeys.service
After=node-hostkeys.service
EOF
STOPSIGNAL SIGRTMIN+3
ENTRYPOINT ["/usr/local/sbin/node-init"]
CMD ["/sbin/init"]

2. 构建镜像

docker build -t vps-node:ubuntu24.04 .

3. 生成专用 SSH 密钥

ssh-keygen -t ed25519 -N '' -f ./vps-node-key -C vps-node
sudo install -d -m 0755 /srv/vps-node
sudo install -m 0644 -o root -g root vps-node-key.pub /srv/vps-node/authorized_keys

私钥文件 vps-node-key 稍后要粘贴到控制台,请妥善保管。容器只接受私钥登录,不支持密码。

4. 启动容器

docker volume create vps-node-hostkeys
docker run -d --name vps-node --hostname vps-node --restart unless-stopped \
  --cgroupns=private --cap-add SYS_ADMIN --security-opt apparmor=unconfined \
  --tmpfs /run --tmpfs /run/lock --shm-size 1g \
  --cpus 2 --memory 4g \
  -p 2222:22 \
  --mount type=bind,src=/srv/vps-node/authorized_keys,dst=/etc/node-ssh/authorized_keys,readonly \
  --mount type=volume,src=vps-node-hostkeys,dst=/etc/ssh/node-hostkeys \
  vps-node:ubuntu24.04

然后在云服务商的安全组或防火墙放行 TCP 2222。

5. 自检

docker exec vps-node ps -p 1 -o comm=              # 输出 systemd
docker exec vps-node systemctl is-system-running   # running 或 degraded 都可以
docker exec vps-node ssh-keygen -lf /etc/ssh/node-hostkeys/ssh_host_ed25519_key.pub   # 记下指纹

再从另一台电脑确认能登录:

ssh -i vps-node-key -p 2222 root@<宿主机公网 IP> 'grep VERSION_ID /etc/os-release'   # 应为 "24.04"

6. 到控制台添加

  1. 地址填宿主机公网 IP,SSH 端口填 2222,用户填 root,认证方式选「SSH 私钥」,粘贴 vps-node-key 的全部内容。
  2. 点「验证连接」,用第 5 步记下的指纹核对。页面提示里的 /etc/ssh/ssh_host_ed25519_key.pub,在这个容器里对应 /etc/ssh/node-hostkeys/ssh_host_ed25519_key.pub。指纹一致再保存并安装。

日后维护

这套配置取自平台的 Docker 测试节点:Ubuntu 24.04、systemd 作为 PID 1、cgroup v2 宿主机。cgroup v1 宿主机未验证。