Docker部署-非root用户openEuler 20.03部署
Docker 非root用户完整安装部署文档
注意:本文档中
<PLACEHOLDER>格式(如<YOUR_PROXY_HOST:PORT>、<USERNAME>、<START_UID>)均为占位符,部署时需替换为实际环境的值。
1. 背景与目标
在 openEuler aarch64 服务器上,以普通用户身份(无需 root 权限)安装 Docker,
所有文件(二进制、配置、数据、运行时文件)全部放在 /usr1/xjt_docker/ 目录下,
不影响系统全局 Docker 及其他用户。
2. 环境信息
| 项目 | 值 |
|---|---|
| 操作系统 | openEuler 20.03 (LTS-SP3) |
| 内核版本 | 4.19.90-2112.8.0.0131.oe1.aarch64 |
| CPU 架构 | aarch64 (ARM64) |
| 目标用户 | xjt_docker (uid=54323, gid=54326) |
| 安装根目录 | /usr1/xjt_docker/ |
| 网络代理 | <PROXY_HOST:PORT>(系统环境变量 $HTTP_PROXY,拉取镜像必需) |
| Docker 版本 | 29.6.1 |
| 存储驱动 | vfs(因 kernel 4.19 不兼容 overlay) |
| 网络模式 | slirp4netns(用户态网络,无需 root 配置网桥) |
3. 前置校验
以下条件需要在安装前确认满足,由 root 用户执行(一次性操作,之后不再需要 root)。
3.1 检查 subuid/subgid 是否配置
Rootless Docker 依赖用户命名空间(user namespaces)进行权限隔离,
必须为安装用户分配从属 UID/GID 范围。
# 检查是否已配置(如无输出则未配置)
grep <USERNAME> /etc/subuid /etc/subgid
期望输出类似:
/etc/subuid:<USERNAME>:<START_UID>:65536
/etc/subgid:<USERNAME>:<START_UID>:65536
如果未配置,需 root 执行:
# 为指定用户分配 65536 个从属 ID(选择一个较大的起始 UID 避免冲突)
usermod --add-subuids <START_UID>-<END_UID> --add-subgids <START_UID>-<END_UID> <USERNAME>
说明:起始 UID 应选择较大值避免与其他用户冲突;
65536是 Docker 要求的标准分配数量。
3.2 检查内核是否启用用户命名空间
# 输出 >= 0 表示已启用
sysctl user.max_user_namespaces
期望输出 user.max_user_namespaces >= 0(默认通常为 0 即无限制)。
3.3 检查磁盘空间
df -h /usr1
二进制文件约需 240MB,镜像和容器数据视使用情况而定,建议至少保留 10GB 可用空间。
3.4 检查网络代理
Rootless Docker 拉取镜像必须通过代理。先用以下命令确认代理地址:
# 检查系统已有的代理环境变量
env | grep -i proxy
如果无输出,则需联系管理员确认代理地址。确认代理后可测试连通性:
curl -x $HTTP_PROXY -I https://registry-1.docker.io 2>&1 | head -5
确认可通过代理访问 Docker Hub。
4. 目录规划
/usr1/xjt_docker/
├── docker-bin/ # 所有 Docker 相关二进制文件(~236MB)
│ ├── docker/ # docker, dockerd, containerd, runc 等
│ ├── rootlesskit # Rootless 容器管理器
│ └── slirp4netns # 用户态网络实现
├── docker-config/ # Docker 守护进程配置
│ └── daemon.json
├── docker-data/ # 镜像、容器数据持久化目录
├── docker-run/ # 运行时文件(socket, PID 等)
├── start-docker.sh # 启动脚本
├── stop-docker.sh # 停止脚本
└── env.sh # 环境变量(备用手动加载)
5. 安装步骤
以下所有步骤以 xjt_docker 用户身份执行,无需 root。
5.1 创建目录结构
mkdir -p /usr1/xjt_docker/{docker-bin/docker,docker-config,docker-data,docker-run}
5.2 下载 Docker 静态二进制包
必须确认架构后再选择下载地址:
uname -m
# 输出 aarch64 → 用 arm64 链接
# 输出 x86_64 → 用 amd64 链接
从 Docker 官方下载静态二进制包:
# 先设置代理(替换为实际代理地址)
export HTTP_PROXY=<YOUR_PROXY_HOST:PORT>
export HTTPS_PROXY=<YOUR_PROXY_HOST:PORT>
# 下载 Docker 29.6.1(按架构选链接)
# aarch64:
wget -O /tmp/docker.tgz \
https://download.docker.com/linux/static/stable/aarch64/docker-29.6.1.tgz
# x86_64:
# wget -O /tmp/docker.tgz \
# https://download.docker.com/linux/static/stable/x86_64/docker-29.6.1.tgz
# 解压到指定目录
tar -xzf /tmp/docker.tgz -C /usr1/xjt_docker/docker-bin/docker/ --strip-components=1
# 确保可执行权限
chmod +x /usr1/xjt_docker/docker-bin/docker/*
# 验证
/usr1/xjt_docker/docker-bin/docker/docker --version
功能:解压后包含
docker(客户端)、dockerd(守护进程)、containerd(容器运行时)、runc(OCI 运行时)、docker-proxy等全部二进制文件。
5.3 安装 slirp4netns(用户态网络)
Rootless Docker 无法操作宿主机 iptables/网桥,需要 slirp4netns 提供容器网络。
# 下载预编译 aarch64 版本
wget -O /usr1/xjt_docker/docker-bin/slirp4netns \
https://github.com/rootless-containers/slirp4netns/releases/download/v1.3.4/slirp4netns-aarch64
chmod +x /usr1/xjt_docker/docker-bin/slirp4netns
# 验证
/usr1/xjt_docker/docker-bin/slirp4netns --version
备选:如果 GitHub 被代理拦截无法下载,可在能访问 GitHub 的机器上下载后 scp 传到目标机器,或通过其他渠道获取二进制文件。只要最终把可执行文件放到
docker-bin/slirp4netns即可。
5.4 安装 rootlesskit
rootlesskit 负责创建用户命名空间,并将 Dockerd 运行在其中。
方式一:Go 编译(推荐,避免平台/版本兼容问题)
# 下载 Go(如系统没有 Go,用 golang.google.cn 国内镜像)
wget https://golang.google.cn/dl/go1.22.5.linux-arm64.tar.gz -O /tmp/go.tar.gz
mkdir -p /usr1/xjt_docker/go /usr1/xjt_docker/go-home
tar -xzf /tmp/go.tar.gz -C /usr1/xjt_docker/go/ --strip-components=1
export PATH=/usr1/xjt_docker/go/bin:$PATH
export GOPATH=/usr1/xjt_docker/go-home
export GOPROXY=https://goproxy.cn,direct # 国内 Go 代理,避免 GitHub 被墙
export HTTP_PROXY=<YOUR_PROXY_HOST:PORT> # 替换为实际地址
export HTTPS_PROXY=<YOUR_PROXY_HOST:PORT>
# 编译安装 rootlesskit(自动拉取依赖)
go install github.com/rootless-containers/rootlesskit/v3/cmd/rootlesskit@latest
# 复制到 docker-bin
cp /usr1/xjt_docker/go-home/bin/rootlesskit /usr1/xjt_docker/docker-bin/rootlesskit
# 验证
/usr1/xjt_docker/docker-bin/rootlesskit --version
方式二:下载预编译二进制(需直接访问 GitHub)
wget -O /usr1/xjt_docker/docker-bin/rootlesskit \
https://github.com/rootless-containers/rootlesskit/releases/download/v3.0.1/rootlesskit-aarch64
chmod +x /usr1/xjt_docker/docker-bin/rootlesskit
功能:rootlesskit 是 Rootless 模式的核心组件,它利用 user_namespaces 创建
隔离环境,使 dockerd 以 rootless 方式运行。踩坑提醒:如果 GitHub 被代理拦截,方式二会失败,必须用方式一(Go 编译 +
GOPROXY国内代理)。
5.5 配置 Docker 守护进程 (daemon.json)
创建配置文件:
cat > /usr1/xjt_docker/docker-config/daemon.json << 'EOF'
{
"bridge": "none",
"iptables": false,
"ip6tables": false,
"registry-mirrors": ["https://docker.m.daocloud.io"]
}
EOF
各配置项说明:
| 配置项 | 说明 |
|---|---|
"bridge": "none" |
禁用默认 docker0 网桥,rootless 下无法创建网桥 |
"iptables": false |
禁用 iptables 规则操作,rootless 无权限修改 iptables |
"ip6tables": false |
同上,禁用 IPv6 iptables |
"registry-mirrors" |
国内镜像加速,避免直接从 Docker Hub 拉取被拦截 |
5.6 创建启动脚本
cat > /usr1/xjt_docker/start-docker.sh << 'SCRIPT'
#!/bin/bash
# Rootless Docker 启动脚本
# 功能:通过 rootlesskit 创建用户命名空间,在其中启动 dockerd
DOCKER_BIN=/usr1/xjt_docker/docker-bin
DOCKER_DATA=/usr1/xjt_docker/docker-data
DOCKER_RUN=/usr1/xjt_docker/docker-run
DOCKER_CONFIG=/usr1/xjt_docker/docker-config
# 设置运行时环境变量
export PATH=$DOCKER_BIN/docker:$DOCKER_BIN:$PATH
export DOCKER_HOST=unix://$DOCKER_RUN/docker.sock
export XDG_RUNTIME_DIR=$DOCKER_RUN
export HTTP_PROXY=<YOUR_PROXY_HOST:PORT>
export HTTPS_PROXY=<YOUR_PROXY_HOST:PORT>
export NO_PROXY=localhost,127.0.0.1,.local
mkdir -p $DOCKER_RUN $DOCKER_DATA
exec $DOCKER_BIN/rootlesskit \
--net=slirp4netns \
--slirp4netns-binary=$DOCKER_BIN/slirp4netns \
--disable-host-loopback \
--copy-up=/etc \
--copy-up=/run \
sh -c "
# 清理主机残留的 docker/containerd 符号链接(避免与命名空间内文件冲突)
rm -rf /run/docker /run/docker.pid /run/docker.sock /run/containerd 2>/dev/null
mkdir -p /run/docker/plugins /run/containerd
exec $DOCKER_BIN/docker/dockerd \
--rootless \
--data-root=$DOCKER_DATA \
--exec-root=$DOCKER_RUN \
--config-file=$DOCKER_CONFIG/daemon.json \
--storage-driver=vfs \
--pidfile=$DOCKER_RUN/docker.pid
"
SCRIPT
chmod +x /usr1/xjt_docker/start-docker.sh
关键参数说明:
| 参数 | 功能 |
|---|---|
--net=slirp4netns |
使用 slirp4netns 用户态网络驱动 |
--disable-host-loopback |
禁用宿主机回环网卡映射,避免端口冲突 |
--copy-up=/etc |
将宿主 /etc 复制到命名空间(dns 解析等需要) |
--copy-up=/run |
将宿主 /run 复制到命名空间 |
--rootless |
告知 dockerd 以 rootless 模式运行 |
--storage-driver=vfs |
使用 vfs 存储驱动(兼容 kernel 4.19) |
sh -c "..." |
在命名空间内先清理冲突文件,再启动 dockerd |
5.7 创建停止脚本
cat > /usr1/xjt_docker/stop-docker.sh << 'SCRIPT'
#!/bin/bash
# Rootless Docker 停止脚本
# 功能:通过 PID 文件优雅终止 Docker 进程
DOCKER_RUN=/usr1/xjt_docker/docker-run
echo "Stopping rootless Docker..."
if [ -f "$DOCKER_RUN/docker.pid" ]; then
kill $(cat "$DOCKER_RUN/docker.pid") 2>/dev/null
fi
sleep 2
# 兜底:清理残留进程
pkill -f "docker-bin.*rootlesskit" 2>/dev/null
pkill -f "docker-bin.*containerd" 2>/dev/null
echo "Docker stopped."
SCRIPT
chmod +x /usr1/xjt_docker/stop-docker.sh
5.8 配置用户环境变量
将 Docker 环境变量写入 ~/.bashrc,每次登录自动生效。
注意:以下操作会覆盖
~/.bashrc,如果已有重要配置,请手动追加内容而非覆盖。
cat > ~/.bashrc << 'EOF'
# Rootless Docker 环境变量
export PATH=/usr1/xjt_docker/docker-bin/docker:/usr1/xjt_docker/docker-bin:$PATH
export DOCKER_HOST=unix:///usr1/xjt_docker/docker-run/docker.sock
export DOCKER_CONFIG=/usr1/xjt_docker/docker-config
export XDG_RUNTIME_DIR=/usr1/xjt_docker/docker-run
# 代理(Docker 拉取镜像需要,替换为实际代理地址)
export HTTP_PROXY=<YOUR_PROXY_HOST:PORT>
export HTTPS_PROXY=<YOUR_PROXY_HOST:PORT>
export NO_PROXY=localhost,127.0.0.1,.local
EOF
# 同时创建 .bash_profile,确保 login shell 也加载 .bashrc
cat > ~/.bash_profile << 'EOF'
if [ -f ~/.bashrc ]; then
source ~/.bashrc
fi
EOF
# 立即生效:启动新的 login shell(推荐,避免 PATH 缓存干扰)
exec bash -l
# 或手动加载:source ~/.bashrc && hash -r
环境变量说明:
| 变量 | 作用 |
|---|---|
PATH |
将 docker 命令加入可执行搜索路径 |
DOCKER_HOST |
指定 Docker 客户端连接的 socket 路径 |
DOCKER_CONFIG |
Docker CLI 配置文件目录 |
XDG_RUNTIME_DIR |
用户运行时目录(非 systemd 环境下需要手动指定) |
HTTP_PROXY/HTTPS_PROXY |
代理地址,拉取镜像时使用 |
NO_PROXY |
不走代理的地址列表 |
6. 启动与验证
6.1 启动 Docker
# 后台启动
nohup /usr1/xjt_docker/start-docker.sh > /dev/null 2>&1 &
# 查看进程
ps aux | grep docker
期望看到 rootlesskit、dockerd、containerd 进程。
6.2 验证运行状态
# 查看客户端和服务端版本
docker version
# 查看 Docker 引擎详细信息
docker info
期望输出中应包含:
Server Version: 29.6.1Storage Driver: vfsNetworkDriver: slirp4netnsrootlesskit
6.3 运行测试容器
docker run --rm hello-world
期望输出:
Hello from Docker!
This message shows that your installation appears to be working correctly.
7. 日常使用
7.1 启动/停止
# 启动
nohup /usr1/xjt_docker/start-docker.sh > /dev/null 2>&1 &
# 停止
/usr1/xjt_docker/stop-docker.sh
7.2 常用命令速查
docker pull <镜像> # 拉取镜像(仅支持 ARM64 架构)
docker run -it <镜像> bash # 运行容器
docker ps # 查看运行中的容器
docker ps -a # 查看所有容器
docker images # 查看本地镜像
docker stop <ID> # 停止容器
docker rm <ID> # 删除容器
docker rmi <镜像> # 删除镜像
docker logs <ID> # 查看容器日志
docker exec -it <ID> bash # 进入运行中的容器
7.3 端口映射
Rootless 模式下无法使用低于 1024 的端口,映射示例:
# 正确:使用高端口
docker run -p 8080:80 nginx
# 错误:无法绑定 80 端口
docker run -p 80:80 nginx
7.4 磁盘空间监控
vfs 存储驱动不共享镜像层,磁盘占用较大,建议定期检查:
du -sh /usr1/xjt_docker/docker-data/
docker system df # 查看 Docker 磁盘使用情况
docker system prune -a # 清理未使用的镜像、容器、网络(谨慎操作)
8. 常见问题与排查
Q1:docker 命令找不到或执行了系统 Docker
原因:当前终端未加载 ~/.bashrc 中的环境变量。
解决:
source ~/.bashrc # 手动加载
exec bash -l # 或启动新的 login shell
Q2:镜像拉取失败 (timeout / connection refused)
原因:代理未生效或 Docker Hub 不可达。
排查:
echo $HTTP_PROXY # 检查代理环境变量
curl -x $HTTP_PROXY https://registry-1.docker.io # 测试代理到 Docker Hub 的连通性
解决:确认 ~/.bashrc 中代理地址正确,且 daemon.json 中配置了镜像加速。
Q3:容器启动报 iptables 错误
原因:rootless 模式无权限操作 iptables。
解决:daemon.json 中已配置 "iptables": false,如果仍有报错,检查启动命令是否加载了正确的 daemon.json。
Q4:overlay 存储驱动报错
原因:内核 4.19 不支持 rootless 下的 overlay。
解决:启动脚本中已通过 --storage-driver=vfs 强制使用 vfs 驱动,
镜像占用会偏大但功能完整。
Q5:容器内无法访问外网
原因:容器内未继承代理环境变量。
解决:运行容器时传入代理:
docker run -e HTTP_PROXY=$HTTP_PROXY -e HTTPS_PROXY=$HTTPS_PROXY <镜像>
Q6:重新登录后 docker 报 No such file or directory
原因:DOCKER_HOST 指向的 socket 文件不存在(Docker 未启动)。
解决:先启动 Docker:
nohup /usr1/xjt_docker/start-docker.sh > /dev/null 2>&1 &
Q7:docker 命令报 /home/xxx/bin/docker: No such file or directory
原因:新旧 shell 会话混用,bash 缓存了旧的 docker 命令路径(hash table)。
解决:清除缓存并重新加载环境:
hash -r && source ~/.bashrc
# 或者直接启动新 shell
exec bash -l
Q8:GitHub 下载链接全部超时或被拒绝
原因:代理拦截了 GitHub 域名。
解决:
- slirp4netns:在能访问 GitHub 的机器上下载后 scp 到目标机器
- rootlesskit:使用方式一(Go 编译 +
GOPROXY=https://goproxy.cn,direct),Go 代理会自动走国内 CDN
Q9:如何确认系统代理地址?
原因:不同环境代理地址不同,需要先获取。
解决:
env | grep -i proxy # 查看当前环境变量中的代理
curl -x <代理地址> http://www.baidu.com # 测试连通性
附录:快速部署清单
前提:已通过 3.4 节确认系统代理地址,并替换下方
<YOUR_PROXY_HOST:PORT>为实际值。
# === 前置(需 root 执行一次) ===
# 配置 subuid/subgid(替换 `<START_UID>` `<USERNAME>` 为实际值)
usermod --add-subuids <START_UID>-<END_UID> --add-subgids <START_UID>-<END_UID> <USERNAME>
# === 以下全部以目标用户身份执行 ===
export HTTP_PROXY=<YOUR_PROXY_HOST:PORT>
export HTTPS_PROXY=<YOUR_PROXY_HOST:PORT>
# 1. 创建目录
mkdir -p /usr1/xjt_docker/{docker-bin/docker,docker-config,docker-data,docker-run}
# 2. 下载 Docker 二进制
wget -O /tmp/docker.tgz https://download.docker.com/linux/static/stable/aarch64/docker-29.6.1.tgz
tar -xzf /tmp/docker.tgz -C /usr1/xjt_docker/docker-bin/docker/ --strip-components=1
chmod +x /usr1/xjt_docker/docker-bin/docker/*
# 3. 下载 slirp4netns(GitHub 不可达则手动传)
wget -O /usr1/xjt_docker/docker-bin/slirp4netns \
https://github.com/rootless-containers/slirp4netns/releases/download/v1.3.4/slirp4netns-aarch64
chmod +x /usr1/xjt_docker/docker-bin/slirp4netns
# 4. 编译 rootlesskit(需要 Go,用国内镜像避免 GitHub 被墙)
wget https://golang.google.cn/dl/go1.22.5.linux-arm64.tar.gz -O /tmp/go.tar.gz
mkdir -p /usr1/xjt_docker/go /usr1/xjt_docker/go-home
tar -xzf /tmp/go.tar.gz -C /usr1/xjt_docker/go/ --strip-components=1
export PATH=/usr1/xjt_docker/go/bin:$PATH
export GOPATH=/usr1/xjt_docker/go-home
export GOPROXY=https://goproxy.cn,direct
go install github.com/rootless-containers/rootlesskit/v3/cmd/rootlesskit@latest
cp /usr1/xjt_docker/go-home/bin/rootlesskit /usr1/xjt_docker/docker-bin/rootlesskit
# 5. 配置 daemon.json
cat > /usr1/xjt_docker/docker-config/daemon.json << 'EOF'
{
"bridge": "none",
"iptables": false,
"ip6tables": false,
"registry-mirrors": ["https://docker.m.daocloud.io"]
}
EOF
# 6. 创建启动/停止脚本并写入环境变量(参见 5.6 ~ 5.8 节完整内容)
# 7. 启动
nohup /usr1/xjt_docker/start-docker.sh > /dev/null 2>&1 &
# 8. 验证
exec bash -l
docker run --rm hello-world
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)