当前位置: 首页 > news >正文

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 表示已启用sysctluser.max_user_namespaces

期望输出user.max_user_namespaces >= 0(默认通常为 0 即无限制)。

3.3 检查磁盘空间

df-h/usr1

二进制文件约需240MB,镜像和容器数据视使用情况而定,建议至少保留10GB可用空间。

3.4 检查网络代理

Rootless Docker 拉取镜像必须通过代理。先用以下命令确认代理地址:

# 检查系统已有的代理环境变量env|grep-iproxy

如果无输出,则需联系管理员确认代理地址。确认代理后可测试连通性:

curl-x$HTTP_PROXY-Ihttps://registry-1.docker.io2>&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 官方下载静态二进制包:

# 先设置代理(替换为实际代理地址)exportHTTP_PROXY=<YOUR_PROXY_HOST:PORT>exportHTTPS_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-aarch64chmod+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 国内镜像)wgethttps://golang.google.cn/dl/go1.22.5.linux-arm64.tar.gz-O/tmp/go.tar.gzmkdir-p/usr1/xjt_docker/go /usr1/xjt_docker/go-hometar-xzf/tmp/go.tar.gz-C/usr1/xjt_docker/go/ --strip-components=1exportPATH=/usr1/xjt_docker/go/bin:$PATHexportGOPATH=/usr1/xjt_docker/go-homeexportGOPROXY=https://goproxy.cn,direct# 国内 Go 代理,避免 GitHub 被墙exportHTTP_PROXY=<YOUR_PROXY_HOST:PORT># 替换为实际地址exportHTTPS_PROXY=<YOUR_PROXY_HOST:PORT># 编译安装 rootlesskit(自动拉取依赖)goinstallgithub.com/rootless-containers/rootlesskit/v3/cmd/rootlesskit@latest# 复制到 docker-bincp/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-aarch64chmod+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 " SCRIPTchmod+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." SCRIPTchmod+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 也加载 .bashrccat>~/.bash_profile<<'EOF' if [ -f ~/.bashrc ]; then source ~/.bashrc fi EOF# 立即生效:启动新的 login shell(推荐,避免 PATH 缓存干扰)execbash-l# 或手动加载:source ~/.bashrc && hash -r

环境变量说明

变量作用
PATHdocker命令加入可执行搜索路径
DOCKER_HOST指定 Docker 客户端连接的 socket 路径
DOCKER_CONFIGDocker CLI 配置文件目录
XDG_RUNTIME_DIR用户运行时目录(非 systemd 环境下需要手动指定)
HTTP_PROXY/HTTPS_PROXY代理地址,拉取镜像时使用
NO_PROXY不走代理的地址列表

6. 启动与验证

6.1 启动 Docker

# 后台启动nohup/usr1/xjt_docker/start-docker.sh>/dev/null2>&1&# 查看进程psaux|grepdocker

期望看到rootlesskitdockerdcontainerd进程。

6.2 验证运行状态

# 查看客户端和服务端版本dockerversion# 查看 Docker 引擎详细信息dockerinfo

期望输出中应包含:

  • Server Version: 29.6.1
  • Storage Driver: vfs
  • NetworkDriver: slirp4netns
  • rootlesskit

6.3 运行测试容器

dockerrun--rmhello-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/null2>&1&# 停止/usr1/xjt_docker/stop-docker.sh

7.2 常用命令速查

dockerpull<镜像># 拉取镜像(仅支持 ARM64 架构)dockerrun-it<镜像>bash# 运行容器dockerps# 查看运行中的容器dockerps-a# 查看所有容器dockerimages# 查看本地镜像dockerstop<ID># 停止容器dockerrm<ID># 删除容器dockerrmi<镜像># 删除镜像dockerlogs<ID># 查看容器日志dockerexec-it<ID>bash# 进入运行中的容器

7.3 端口映射

Rootless 模式下无法使用低于 1024 的端口,映射示例:

# 正确:使用高端口dockerrun-p8080:80 nginx# 错误:无法绑定 80 端口dockerrun-p80:80 nginx

7.4 磁盘空间监控

vfs 存储驱动不共享镜像层,磁盘占用较大,建议定期检查:

du-sh/usr1/xjt_docker/docker-data/dockersystemdf# 查看 Docker 磁盘使用情况dockersystem prune-a# 清理未使用的镜像、容器、网络(谨慎操作)

8. 常见问题与排查

Q1:docker命令找不到或执行了系统 Docker

原因:当前终端未加载~/.bashrc中的环境变量。

解决

source~/.bashrc# 手动加载execbash-l# 或启动新的 login shell

Q2:镜像拉取失败 (timeout / connection refused)

原因:代理未生效或 Docker Hub 不可达。

排查

echo$HTTP_PROXY# 检查代理环境变量curl-x$HTTP_PROXYhttps://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:容器内无法访问外网

原因:容器内未继承代理环境变量。

解决:运行容器时传入代理:

dockerrun-eHTTP_PROXY=$HTTP_PROXY-eHTTPS_PROXY=$HTTPS_PROXY<镜像>

Q6:重新登录后 docker 报No such file or directory

原因DOCKER_HOST指向的 socket 文件不存在(Docker 未启动)。

解决:先启动 Docker:

nohup/usr1/xjt_docker/start-docker.sh>/dev/null2>&1&

Q7:docker命令报/home/xxx/bin/docker: No such file or directory

原因:新旧 shell 会话混用,bash 缓存了旧的docker命令路径(hash table)。

解决:清除缓存并重新加载环境:

hash-r&&source~/.bashrc# 或者直接启动新 shellexecbash-l

Q8:GitHub 下载链接全部超时或被拒绝

原因:代理拦截了 GitHub 域名。

解决

  • slirp4netns:在能访问 GitHub 的机器上下载后 scp 到目标机器
  • rootlesskit:使用方式一(Go 编译 +GOPROXY=https://goproxy.cn,direct),Go 代理会自动走国内 CDN

Q9:如何确认系统代理地址?

原因:不同环境代理地址不同,需要先获取。

解决

env|grep-iproxy# 查看当前环境变量中的代理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># === 以下全部以目标用户身份执行 ===exportHTTP_PROXY=<YOUR_PROXY_HOST:PORT>exportHTTPS_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.tgztar-xzf/tmp/docker.tgz-C/usr1/xjt_docker/docker-bin/docker/ --strip-components=1chmod+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-aarch64chmod+x /usr1/xjt_docker/docker-bin/slirp4netns# 4. 编译 rootlesskit(需要 Go,用国内镜像避免 GitHub 被墙)wgethttps://golang.google.cn/dl/go1.22.5.linux-arm64.tar.gz-O/tmp/go.tar.gzmkdir-p/usr1/xjt_docker/go /usr1/xjt_docker/go-hometar-xzf/tmp/go.tar.gz-C/usr1/xjt_docker/go/ --strip-components=1exportPATH=/usr1/xjt_docker/go/bin:$PATHexportGOPATH=/usr1/xjt_docker/go-homeexportGOPROXY=https://goproxy.cn,direct goinstallgithub.com/rootless-containers/rootlesskit/v3/cmd/rootlesskit@latestcp/usr1/xjt_docker/go-home/bin/rootlesskit /usr1/xjt_docker/docker-bin/rootlesskit# 5. 配置 daemon.jsoncat>/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/null2>&1&# 8. 验证execbash-ldockerrun--rmhello-world
http://www.jsqmd.com/news/1099827/

相关文章:

  • How To Secure A Linux Server:一份持续更新的服务器安全加固手册
  • 2026年6月个人工作生活总结
  • Linux Page Cache 导致视频解码第一次慢、第二次快的原因分析与缓存清理方法
  • PYTHON+AI LLM DAY NINTY-TWO
  • vmware安装win10教程(保姆级图文):VMware16虚拟机部署Windows10,附win10镜像iso文件下载
  • OpenHarness源码研究-3-codex配置到输出对话
  • PDF转Excel免费工具推荐,批量转换不收费绿色版
  • Windows 11本地部署GLM-5.2大模型:集成Claw工具调用与Agent知识库实战
  • 零基础自学C++逆向学习日记 Day.5
  • 【题解-信息学奥赛一本通】1224:最大子矩阵
  • 【数仓避坑04】金额换算精度踩坑:先除后乘导致大额资金隐性资损,先乘后除精度最优详解
  • 当企业应用AI销冠系统时,如何利用数字员工提升工作效率?
  • 数据库工程:生产级查询优化全案例拆解‌
  • 企业级离线翻译架构重构:LibreTranslate 1.9.6如何实现数据主权与性能突破
  • 2026年AI企业服务系统五大评测:乔掌门AI与同类品牌深度对比排名推荐
  • 基于微积分思维的数学分析教学
  • 剑指offer-62、⼆叉搜索树的第k个结点
  • MonkeyCode维护与质量:让代码在生成阶段就具备安全与可维护性
  • 微服务的特点、优点、缺点
  • Linux 开发工具:yum、vim 与 gcc 实操指南
  • 别光看感量!KEMET共模电感手册里这8个参数,选型时一个都不能漏
  • 鲁棒MPC、分布式MPC与学习型MPC:三种“进化版”模型预测控制
  • 企业级智能运维平台实战解析:Keep如何终结警报疲劳
  • 7大编程语言核心区别全解析
  • GLM5.2本地部署实战:vLLM与llama.cpp方案详解,性能超越官方API
  • 无限积分,免费生成电商设计图,AI详情页
  • 软件交付即暴露:Virbox Protector 的加密与加固逻辑
  • OPNsense:开源防火墙系统的管理核心
  • 【计算机毕业设计案例】基于 SpringBoot 的农用车维修保养管理系统的设计与实现 基于 SpringBoot 的农业机械设备库存管控系统(程序+文档+讲解+定制)
  • 手机卖不动,运动相机凭什么逆势上涨?