Docker rootless 脚本安装

Ubuntu 24.04 上安装 rootless 的 Docker

参考:https://docs.docker.com/engine/security/rootless/

说明

💧rootless Docker 不适合生产环境

  1. 性能较差:rootless 模式使用用户态网络(如 slirp4netns),吞吐低、延迟高,严重影响高负载服务性能。
  2. 功能受限:某些功能如自定义网络驱动、挂载卷、overlay 文件系统等在 rootless 模式下无法使用或不稳定。
  3. 兼容性问题: 需要系统支持 user namespacescgroup v2,在一些老旧或企业发行版上配置复杂、不稳定。
  4. 运维复杂度高:日志、存储路径不同于标准 Docker,调试和管理不方便,容易混乱。

以下是 rootless Docker 适合使用的场景

  1. 本地开发与测试环境:开发者无需 root 权限即可运行容器,降低系统风险,适合个人机器或 CI 流水线中的构建与测试。
  2. 多用户共享服务器:在一台服务器上多个用户运行容器时,使用 rootless 模式可避免互相干扰,提高隔离性和安全性。
  3. 受限或受控环境:在不允许获取 root 权限的系统中(如教育环境、托管虚拟机),rootless 模式是容器化运行的可行方式。
  4. CI/CD 系统中的隔离构建任务:用于构建、打包、测试等任务时,rootless 模式减少对主机系统的侵入,提升安全性。

这些场景下对性能和容器功能要求较低,因此更适合使用 rootless Docker。

准备

# 更新系统和软件包
sudo apt update && sudo apt upgrade -y
# 安装必要依赖
sudo apt install -y uidmap dbus-user-session fuse-overlayfs curl

# 加载 Linux 内核模块 nf_tables,该模块是 nftables 框架的核心组件,用于实现 Linux 防火墙和包过滤系统。
sudo modprobe nf_tables

用户映射文件

配置 /etc/subuid/etc/subgid

为每个用户分配 UID/GID 映射段(确保不重叠)

建议在 login.defs 配置文件中设置如下内容

SUB_UID_MIN 100000
SUB_UID_MAX 600100000
SUB_UID_COUNT 65536
SUB_GID_MIN 100000
SUB_GID_MAX 600100000
SUB_GID_COUNT 65536

Ubuntu24.04 已经默认设置,不需要任何操作。

Ubuntu22.04 需要放开注释,添加上述内容。

创建新用户和用户组

sudo adduser --disabled-password --gecos "" dockeruser1

你可以重复这个命令来创建多个用户,例如 dockeruser2dockeruser3 等。

adduser:创建新用户的命令(比 useradd 更易用,自动设置更多内容)。

--disabled-password:不为用户设置密码,用户不能使用密码登录系统(但可以通过 SSH 密钥等其他方式登录)。

--gecos ""GECOS 字段用于设置用户的全名、办公室号、电话等信息,这里设置为空字符串,表示不填写这些信息。

dockeruser1:要创建的用户名。

在创建用户之后,adduser 命令会自动分配 UID/GID 映射到 /etc/subuid/etc/subgid,可以通过以下命令确认:

grep dockeruser1 /etc/subuid /etc/subgid

给新用户配置登录密码,或者使用 SSH 公钥方式连接 Linux 服务器

# 配置密码
passwd dockeruser1

后续都在登录 dockeruser1 后操作

AppArmor 配置文件

AppArmor 用于限制 rootless Docker 的权限,提升安全性。

创建并安装当前登录用户的 AppArmor 配置文件

filename=$(echo $HOME/bin/rootlesskit | sed -e s@^/@@ -e s@/@.@g)
cat <<EOF > ~/${filename}
abi <abi/4.0>,
include <tunables/global>

"$HOME/bin/rootlesskit" flags=(unconfined) {
  userns,

  include if exists <local/${filename}>
}
EOF

此代码块会生成一个针对您的用户 rootlesskit 可执行文件路径量身定制的 AppArmor 配置文件。

比如 home.dockeruser1.bin.rootlesskit,dockeruser1 是当前的登录用户名

# 这一句需要 sudo 组,可以让 root 用户来操作
sudo mv ~/${filename} /etc/apparmor.d/${filename}

# 比如:sudo mv /home/dockeruser1/home.dockeruser1.bin.rootlesskit /etc/apparmor.d/home.dockeruser1.bin.rootlesskit

重新启动 AppArmor 服务

sudo systemctl restart apparmor.service

脚本安装

配置代理

这里是下载安装包的代理

代理的目的是下载 https://download.docker.com/linux/static/stable/ 里面的文件包

比如

https://download.docker.com/linux/static/stable/x86_64/docker-28.2.1.tgz

https://download.docker.com/linux/static/stable/x86_64/docker-rootless-extras-28.2.1.tgz

国内连 Docker 官网比较慢,可以考虑走代理。

# 这个是环境变量临时使用局域网的代理,(可选)如果网络受限,配置代理以加速下载
export http_proxy="http://192.168.10.40:10808"
export https_proxy="http://192.168.10.40:10808"

使用脚本安装

脚本安装 docker rootless

curl -fsSL https://get.docker.com/rootless | sh

使用脚本离线安装

访问 https://get.docker.com/rootless ,保存为 rootless_install.sh 文件

提前下载安装包,以版本 28.2.1 举例

  • docker-28.2.1.tgz
  • docker-rootless-extras-28.2.1.tgz

找到以下代码段:

(
	cd "$tmp"
	curl -L -o docker.tgz "$STATIC_RELEASE_URL"
	curl -L -o rootless.tgz "$STATIC_RELEASE_ROOTLESS_URL"
)

将其 替换为

cp ./docker-28.2.1.tgz "$tmp/docker.tgz"
cp ./docker-rootless-extras-28.2.1.tgz "$tmp/rootless.tgz"

示例修改后的关键部分:

do_install() {
	echo "# Executing docker rootless install script, commit: $SCRIPT_COMMIT_SHA"

	init_vars
	checks

	tmp=$(mktemp -d)
	trap 'rm -rf "$tmp"' EXIT INT TERM
	# 使用本地文件代替在线下载
	cp ./docker-28.2.1.tgz "$tmp/docker.tgz"
	cp ./docker-rootless-extras-28.2.1.tgz "$tmp/rootless.tgz"

	# 解压到 $HOME/bin/
	(
		mkdir -p "$BIN"
		cd "$BIN"
		tar zxf "$tmp/docker.tgz" --strip-components=1
		tar zxf "$tmp/rootless.tgz" --strip-components=1
	)

	exec_setuptool "$@"
}

如果你需要让这些 .tgz 来自固定目录(如 /opt/docker/),也可以将 cp 命令改成:

cp /opt/docker/docker-28.2.1.tgz "$tmp/docker.tgz"
cp /opt/docker/docker-rootless-extras-28.2.1.tgz "$tmp/rootless.tgz"

运行安装脚本 rootless_install.sh 文件

bash rootless_install.sh

配置环境变量

# 配置环境变量
cat <<EOF >> "$HOME/.bashrc"
export PATH=$HOME/bin:$PATH
export DOCKER_HOST=unix:///run/user/$UID/docker.sock
EOF
source "$HOME/.bashrc"

配置代理

Docker 镜像拉取的代理

# 创建文件夹
mkdir -p ~/.config/docker

配置镜像地址,请参考:搭建自己的免费 Docker 镜像加速器

tee ~/.config/docker/daemon.json <<EOF
{
    "registry-mirrors": ["https://docker.1ms.run"]
}
EOF

重启 Docker

systemctl --user restart docker

管理命令

启动 docker

systemctl --user start docker

设置 docker 开机启动,这样每次你用户的 systemd 启动时(登录或被唤醒时),docker 就会自动启动。

systemctl --user enable docker

查看 docker 状态

systemctl --user status docker

随系统开机启动

让用户服务在系统启动时自动启动

运行以下命令:

loginctl enable-linger dockeruser1

这一步是关键!它告诉系统:即使用户没有登录,也保持该用户的 systemd 用户服务活跃。

可以重复这个命令来让多个用户的 systemd 用户服务开机启动,例如 dockeruser2dockeruser3 等。

查看已经配置的用户

ls -l /var/lib/systemd/linger/

这个目录中列出的文件名就是启用了 linger 的用户名。

类似显示

dockeruser1@node25:~$ ls -l /var/lib/systemd/linger/
total 0
-rw-r--r-- 1 root root 0 Jun  9 07:31 dockeruser1

取消 linger

loginctl disable-linger dockeruser1

测试

# Hello
docker run --rm -it docker.io/library/alpine echo "Hello, Rootless Docker!"

# 启动一个 Redis 服务,然后退出登录,稍后登录查看服务是否刚刚启动,检查登出时服务是否也停止了
docker run -d \
  --name redis5 \
  -p 6379:6379 \
  --restart unless-stopped \
  redis:5

注意对外的端口是不能重复的,比如 dockeruser1 用了端口 6379 ,dockeruser2 是不能再用的。

个人习惯,所有应用放在 app 文件夹下

mkdir ~/app

compose 插件

新版 Docker自带了,不用额外安装

mkdir -p ~/.docker/cli-plugins
curl -SL https://github.com/docker/compose/releases/download/v2.40.3/docker-compose-linux-x86_64 -o ~/.docker/cli-plugins/docker-compose
chmod +x ~/.docker/cli-plugins/docker-compose

注意:v2.40.3 是当前最新版,

你可以前往 GitHub 发布页确认最新版本:https://github.com/docker/compose/releases

验证是否安装成功

docker compose version

如果输出类似如下信息说明安装成功:

Docker Compose version v2.40.3

目录

~/bin 目录下

  • dockerd-rootless.sh:启动 rootless Docker 守护进程的脚本。
  • dockerd:Docker 守护进程二进制文件。
  • rootlesskit:用户空间工具,用于管理 rootless 容器网络和命名空间。
  • vpnkit:用户空间网络代理,提供网络访问(如果启用了 vpnkit 网络)。
  • docker:Docker CLI 客户端命令。
posted @ 2025-06-06 16:49  ioufev  阅读(757)  评论(0)    收藏  举报