Docker 安装、权限与升级:从软件包到可验证运行环境
Docker 安装不是执行一条 apt install docker 就结束。生产环境要回答:安装的是发行版自带包还是 Docker 官方仓库包,CLI、daemon、containerd、runc、Buildx、Compose 分别来自哪里,软件源签名如何验证,Docker 数据写到哪个文件系统,普通用户为什么会 permission denied,加入 docker 组为什么近似授予 root 权限,rootless 能降低什么风险,升级 daemon 会不会影响正在运行的容器,以及安装后如何证明镜像拉取、网络、Volume、日志和 cgroup 都正常。
安装命令会随操作系统版本和 Docker 官方仓库调整。执行生产安装前,应结合当前系统版本核对 Docker 官方安装文档。本页重点提供可解释、可验证、可回滚的完整方法,而不是把未知脚本直接交给 root 执行。
学习目标
学完后,应能:
- 解释 Docker CLI、dockerd、containerd、shim、runc、Buildx 和 Compose 的职责。
- 比较发行版仓库、Docker 官方仓库、便利脚本、静态二进制和 Docker Desktop 的边界。
- 在 Ubuntu/Debian 上按签名仓库方式安装,并解释每一步为什么存在。
- 使用 systemd 管理 docker.service 和 docker.socket,读懂 daemon 日志。
- 解释 Docker socket 权限、docker 组风险、sudo 混用和 rootless 模式。
- 规划 Docker Root Dir、文件系统、cgroup、网络地址池、日志轮转和代理。
- 验证镜像、容器、端口、DNS、Volume、资源限制、Compose 和优雅停止。
- 安全升级和卸载软件包,不误删镜像、Volume 与业务数据。
- 定位 daemon 连不上、GPG、TLS、DNS、overlay2、iptables、权限和磁盘问题。
一、安装后到底会多出哪些组件
flowchart TD
A["用户执行docker命令"] --> B["Docker CLI"]
B --> C["Docker Engine API"]
C --> D["dockerd守护进程"]
D --> E["containerd"]
E --> F["containerd-shim"]
F --> G["runc等OCI Runtime"]
G --> H["Linux内核namespace、cgroup、网络和Mount"]
B --> I["Buildx插件"]
B --> J["Compose插件"]| 组件 | 常见职责 | 没有或异常时的表现 |
|---|---|---|
| Docker CLI | 解析 docker 命令并调用 Engine API | shell提示命令不存在,或只有Client无法连接Server |
| dockerd | 管理镜像、容器、网络、Volume和API | Cannot connect to the Docker daemon |
| containerd | 管理镜像内容与容器任务生命周期 | daemon创建/启动容器失败 |
| containerd-shim | 保持容器任务与运行时状态、转发IO | daemon重启和容器任务管理异常 |
| runc | 根据OCI配置创建容器进程 | namespace/cgroup/rootfs创建阶段失败 |
| Buildx | BuildKit驱动的高级构建入口 | docker buildx不可用 |
| Compose plugin | 解析Compose项目并调用Engine | docker compose不可用 |
容器不是 dockerd 的子虚拟机。最终应用仍是 Linux 进程,使用宿主机内核。完整链路见 Docker容器运行底层原理。
二、先选择安装方式
| 方式 | 优点 | 风险与适用边界 |
|---|---|---|
| Docker官方软件仓库 | 组件版本配套、更新路径清晰 | 需要管理仓库信任、版本和变更窗口 |
| Linux发行版自带包 | 与发行版生命周期集成 | 包名、版本、默认配置可能与Docker官方包不同 |
| 官方便利脚本 | 实验机快速安装 | 不适合不审查就以root运行在生产;版本与行为需先阅读 |
| 静态二进制 | 特殊离线环境灵活 | systemd、升级、依赖、日志和安全补丁都需自行治理 |
| Docker Desktop | Windows/macOS开发体验完整 | Engine运行在Linux VM/WSL2;路径、资源和网络不等于原生Linux |
| rootless安装 | daemon和容器不以宿主机root运行 | 网络、低端口、cgroup、存储驱动和运维方式有兼容性边界 |
本页 Linux 主线采用 Docker 官方 APT 仓库。企业如果统一使用发行版仓库,应遵守内部基线,但要记录实际包来源和版本,不能混装两套冲突包。
三、安装前检查:先证明主机适合运行Docker
3.1 识别操作系统和CPU架构
cat /etc/os-release
uname -r
uname -m
dpkg --print-architecture 2>/dev/null || true需要记录:
- Ubuntu、Debian或其他发行版。
- 发行版版本和代号。
- Kernel版本。
- amd64、arm64等架构。
镜像架构必须与主机或仿真能力匹配,否则可能出现 no matching manifest 或 exec format error。
3.2 确认cgroup模式
stat -fc %T /sys/fs/cgroup
mount | grep cgroup常见:
- cgroup v1。
- cgroup v2。
它影响资源控制文件、监控和部分旧软件兼容性。现代系统普遍使用 v2,但不能只凭发行版名称猜测。
3.3 确认存储空间、inode和文件系统
df -h
df -i
lsblk -f
findmnt /至少规划:
- Docker Root Dir 可用空间。
- 镜像和构建缓存增长。
- 容器日志。
- 数据库 Volume。
- Heap/Core Dump。
- inode 数量。
根分区只有少量空间却把 /var/lib/docker 放在根分区,后续很容易因镜像、日志和 OverlayFS 写满宿主机。
3.4 确认时间、DNS、代理和外网
timedatectl status
getent hosts download.docker.com
getent hosts registry-1.docker.ioTLS 依赖正确系统时间。企业网络还要确认:
- HTTP/HTTPS代理。
- TLS中间代理CA。
- Docker官方仓库是否可达。
- 镜像Registry是否可达。
- 内部DNS。
APT能联网不代表 dockerd 拉镜像一定能联网,因为 daemon 是 systemd 服务,未必继承当前Shell代理变量。
3.5 检查旧包和现有数据
dpkg -l | grep -E 'docker|containerd|runc' || true
systemctl status docker --no-pager 2>/dev/null || true如果主机已经运行容器,先保存:
docker version
docker info
docker ps -a --no-trunc
docker image ls --digests
docker volume ls
docker network ls卸载软件包通常不会自动删除 /var/lib/docker,但混装和版本切换可能导致 daemon 无法读取现有状态。任何已有业务主机都应先做变更评估、备份和回滚计划。
四、Ubuntu使用Docker官方APT仓库安装
以下命令面向当前常见 Ubuntu APT 方式。执行前先核对操作系统确实是 Ubuntu,而不是把 Ubuntu 仓库地址照搬到 Debian。
4.1 移除可能冲突的软件包
先只查看:
dpkg -l | grep -E 'docker.io|docker-compose|docker-compose-v2|docker-doc|podman-docker|containerd|runc' || true确认不是已有生产运行环境后,移除与官方包冲突的发行版包:
sudo apt-get remove -y \
docker.io \
docker-compose \
docker-compose-v2 \
docker-doc \
podman-docker \
containerd \
runc包不存在时 APT 可能提示无法定位或未安装。关键不是机械忽略所有错误,而是再次检查包状态,确认没有两套 containerd/runc 来源冲突。
不要在这一步删除
/var/lib/docker或/var/lib/containerd。它们可能保存现有镜像、容器元数据和业务卷。
4.2 安装仓库访问依赖
sudo apt-get update
sudo apt-get install -y ca-certificates curlca-certificates:验证 HTTPS 服务端证书。curl:下载 Docker 仓库签名公钥。
如果企业使用私有CA,应由安全/运维流程把CA加入系统信任,不应使用 curl -k 跳过TLS校验。
4.3 创建APT Keyring目录
sudo install -m 0755 -d /etc/apt/keyringsinstall -m 同时创建目录并设置权限。单独 keyring 配合 signed-by,可以把该密钥的信任范围限制到指定仓库,而不是把第三方Key全局信任给所有APT源。
4.4 下载Docker仓库签名公钥
sudo curl -fsSL \
https://download.docker.com/linux/ubuntu/gpg \
-o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc参数含义:
-f:HTTP错误时失败。-sS:减少进度输出但保留错误。-L:跟随重定向。-o:写入明确文件。
生产可以按组织基线核对密钥指纹和来源。HTTPS只能证明连接到证书信任的站点,签名校验用于验证仓库元数据由持有对应私钥的一方发布。
4.5 添加Ubuntu软件源
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo \"${UBUNTU_CODENAME:-$VERSION_CODENAME}\") stable" |
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null拆解:
arch=...:只获取当前CPU架构包。signed-by=...:指定该仓库使用的公钥。/linux/ubuntu:Ubuntu仓库,Debian不能直接照搬。- codename:例如某个Ubuntu发行版代号。
stable:稳定通道。
检查生成结果:
cat /etc/apt/sources.list.d/docker.list
sudo apt-get update
apt-cache policy docker-ce若 apt-get update 出现 GPG、Release file、404,应修复仓库和代号,不能通过关闭签名校验绕过。
4.6 安装组件
sudo apt-get install -y \
docker-ce \
docker-ce-cli \
containerd.io \
docker-buildx-plugin \
docker-compose-plugin包职责:
| 包 | 主要内容 |
|---|---|
docker-ce | Docker Engine daemon及systemd集成 |
docker-ce-cli | docker命令行客户端 |
containerd.io | Docker配套containerd及相关运行组件 |
docker-buildx-plugin | docker buildx插件 |
docker-compose-plugin | docker compose V2插件 |
安装完成不代表业务环境已经验证,还要执行后续 systemd、网络、Volume 和资源测试。
五、Debian安装时与Ubuntu有什么不同
Debian 的 key URL 和仓库路径应使用 Debian:
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL \
https://download.docker.com/linux/debian/gpg \
-o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc仓库:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian $(. /etc/os-release && echo \"$VERSION_CODENAME\") stable" |
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null再执行 update 和安装同类组件。Ubuntu和Debian的发行版代号、仓库路径不能混用。衍生发行版还可能需要映射到上游代号,应以其支持说明为准。
六、RHEL系主机怎么处理
RHEL、Rocky Linux、AlmaLinux、CentOS Stream 等通常使用 RPM/DNF 体系,不能复制 APT 命令。核心流程仍相同:
识别发行版与版本
↓
清理冲突包
↓
添加受信任RPM仓库
↓
检查可用版本
↓
安装Engine、CLI、containerd、Buildx、Compose
↓
systemd启动与验证示意命令:
sudo dnf install -y dnf-plugins-core
sudo dnf config-manager --add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
sudo dnf install -y \
docker-ce \
docker-ce-cli \
containerd.io \
docker-buildx-plugin \
docker-compose-plugin不同RHEL系发行版、版本、订阅和SELinux策略可能不同,生产必须核对 Docker 官方支持矩阵与组织镜像仓库,不能把示意命令当成所有RPM系统完全一致的脚本。
七、为什么不建议生产直接执行便利脚本
常见快速脚本形式:
curl 某URL | sh问题不在于脚本一定恶意,而在于:
- 远程内容未经本地审查就交给 Shell。
- 常以 root 运行。
- 今天和明天下载内容可能不同。
- 版本选择、仓库变化和副作用不清楚。
- 不利于审计和重复部署。
实验机若使用便利脚本,也应先下载、固定内容、阅读脚本并记录版本。生产更适合配置管理工具或经过评审的安装脚本,明确软件源、包版本、daemon配置和验证结果。
八、systemd如何管理Docker
8.1 启用并立即启动
sudo systemctl enable --now docker相当于:
- 设置在适当启动目标中启用。
- 当前立即启动 docker.service。
验证:
systemctl is-enabled docker
systemctl is-active docker
sudo systemctl status docker --no-pager8.2 docker.service与docker.socket
查看:
systemctl status docker.service --no-pager
systemctl status docker.socket --no-pager
systemctl cat docker.service
systemctl cat docker.socket某些安装启用 socket activation:客户端访问 Docker Unix Socket 时,systemd可以触发 daemon 启动。实际行为取决于 unit 配置,不应只看进程是否曾手工 start。
8.3 查看daemon日志
sudo journalctl -u docker --since "30 minutes ago" --no-pager
sudo journalctl -u containerd --since "30 minutes ago" --no-pager实时查看:
sudo journalctl -u docker -f-f 持续占用终端。生产应控制时间范围并将关键日志外部采集。
8.4 restart与daemon-reload区别
sudo systemctl daemon-reload让 systemd 重新读取 unit 和 drop-in,不等于重启 Docker。
sudo systemctl restart docker会重启 daemon,可能影响所有容器和管理操作。修改 daemon 配置后常需 restart,但生产执行前必须评估运行容器、live-restore、重启策略和业务流量。
九、Docker Unix Socket与权限原理
Rootful Docker 默认常通过:
/var/run/docker.sock通信。检查:
ls -l /var/run/docker.sock
getent group docker
id常见权限类似:
srw-rw---- root docker ... /var/run/docker.sock含义:root和docker组成员可以调用 Engine API。
9.1 为什么加入docker组近似授予root权限
拥有 Docker API 权限的用户通常可以:
- 启动高权限容器。
- 挂载宿主机根目录。
- 访问宿主机文件。
- 挂载Docker socket。
- 创建带设备和Capability的容器。
因此 docker 组不是普通“应用用户组”,应按高权限管理员组控制、审计和定期复核。
9.2 将可信用户加入docker组
只对经过授权的运维或开发用户:
sudo usermod -aG docker "$USER"组成员关系通常在新登录会话生效。可退出重新登录,或在当前终端测试新组会话:
newgrp docker
id
docker version如果之前大量使用 sudo docker,用户家目录中的 Docker CLI 配置可能由 root 创建,导致普通用户访问 ~/.docker 出错。应检查所有者并修正明确文件,不要递归放宽整个家目录权限。
9.3 不要把socket挂给普通业务容器
危险配置:
volumes:
- /var/run/docker.sock:/var/run/docker.sock该容器获得的通常不是普通文件访问,而是控制宿主机Docker API的能力。仅基础设施组件在严格评估、只读代理、权限隔离和审计下才可能需要,普通Java服务不应挂载。
十、Rootless Docker解决什么
Rootless 模式让 daemon 和容器以普通宿主机用户身份运行,降低 daemon 或容器漏洞直接获得宿主机 root 的风险。
flowchart TD
A["普通用户启动rootless dockerd"] --> B["User Namespace映射"]
B --> C["用户目录下Docker数据"]
B --> D["用户级systemd服务"]
B --> E["rootless网络与端口机制"]10.1 前置条件
常见需要:
uidmap工具。/etc/subuid和/etc/subgid为用户分配从属ID范围。- 支持 user namespace 的内核。
- 用户级 systemd 或其他进程管理。
- Rootless配套组件。
Ubuntu/Debian示意:
sudo apt-get install -y uidmap
grep "^$USER:" /etc/subuid
grep "^$USER:" /etc/subgidDocker官方包可提供 rootless extras,具体包和安装工具应按当前版本确认:
dockerd-rootless-setuptool.sh check
dockerd-rootless-setuptool.sh install安装工具通常会提示设置 DOCKER_HOST 和用户级服务。按实际输出配置,不要把 rootful /var/run/docker.sock 与 rootless 用户 socket 混用。
10.2 用户级systemd
systemctl --user status docker --no-pager
systemctl --user enable --now docker若希望用户退出后服务继续运行,可能需要管理员评估并启用 linger:
loginctl show-user "$USER" -p Linger是否启用由组织安全和运维策略决定,不应对所有用户无条件开启。
10.3 Rootless不是没有边界
需要验证:
- 低于1024端口的绑定策略。
- cgroup资源限制是否完整可用。
- OverlayFS/fuse-overlayfs。
- 网络性能和真实源IP。
- 存储路径和配额。
- ICMP、设备、特权能力。
- 监控和备份工具兼容性。
Rootless降低风险,不会自动解决镜像漏洞、错误Mount、应用权限、Secret泄露和网络暴露。
十一、Docker数据目录和存储驱动
查看:
docker info --format 'root={{.DockerRootDir}} driver={{.Driver}}'Rootful常见数据目录是 /var/lib/docker,但可以通过配置改变。它可能包含:
- 镜像层。
- 容器可写层。
- 本地Volume。
- 容器日志。
- 网络和元数据。
- 构建缓存的相关数据。
11.1 为什么不能运行中直接移动目录
直接 mv /var/lib/docker 可能造成:
- daemon仍在写入。
- 文件所有权或安全标签变化。
- OverlayFS层关系损坏。
- 容器和Volume不可用。
- 回滚困难。
迁移 data-root 应制定停机、备份、复制校验、daemon配置和回滚流程,数据库业务数据还要使用数据库一致性备份,不能把复制 Docker Root Dir 当作通用热备。
11.2 overlay2和底层文件系统
常见 Linux 存储驱动是 overlay2。需要底层文件系统和内核支持。XFS 场景历史上需关注 ftype=1/目录项类型支持:
xfs_info <挂载点> 2>/dev/null | grep ftype || true实际支持以当前 Docker Engine 和发行版文档为准。不要通过强行切换 storage driver 启动旧数据目录,不同驱动的数据布局并不通用。
十二、daemon.json配置与验证
默认常见路径:
/etc/docker/daemon.json生产示意:
{
"data-root": "/data/docker",
"log-driver": "json-file",
"log-opts": {
"max-size": "20m",
"max-file": "5"
},
"live-restore": true,
"default-address-pools": [
{
"base": "172.30.0.0/16",
"size": 24
}
]
}每项含义:
| 配置 | 目的 | 风险与验证 |
|---|---|---|
data-root | 将Docker数据放到规划磁盘 | 迁移旧数据需停机和校验 |
log-driver | 设置默认日志驱动 | 新建容器才会按新默认配置 |
log-opts | 默认日志轮转 | 必须inspect最终容器LogConfig |
live-restore | daemon不可用时尽量保持容器运行 | 不代表所有升级/网络管理都无影响 |
default-address-pools | 控制自动网络地址池 | 必须避免与机房、VPN、K8s网段冲突 |
12.1 修改前备份和语法验证
先查看当前配置和 unit 参数:
sudo test -f /etc/docker/daemon.json && sudo cat /etc/docker/daemon.json
systemctl cat docker编辑后先进行 JSON 语法校验。若当前 dockerd 支持:
sudo dockerd --validate --config-file=/etc/docker/daemon.json不同版本支持情况以 dockerd --help 为准。还要注意同一选项若同时出现在 systemd启动参数和 daemon.json,可能导致冲突并使 daemon 启动失败。
12.2 应用配置
sudo systemctl restart docker
sudo systemctl status docker --no-pager
sudo journalctl -u docker --since "10 minutes ago" --no-pager
docker info生产重启前先摘流、确认运行容器和回滚方案。配置失败时应恢复已验证配置,而不是反复删除数据目录。
十三、镜像加速、私有Registry与信任边界
镜像加速示意:
{
"registry-mirrors": [
"https://mirror.example.com"
]
}需要确认:
- 镜像源由谁运营。
- 是否完整同步Digest和多架构Manifest。
- 是否有访问日志和限流。
- 是否可能返回过期或篡改内容。
- 企业是否应使用内部Registry代理缓存。
不要使用来源不明的公共镜像加速地址处理商业镜像。
私有 Registry 的 TLS 证书应由受信任 CA 签发,或将企业 CA 正确安装到 Docker 信任目录。不要为了省事配置明文 insecure registry,除非是隔离环境且经过明确风险评估。
十四、Docker daemon代理为什么与Shell代理不同
当前Shell设置:
export HTTPS_PROXY=http://proxy.example.com:3128不一定影响 systemd 启动的 dockerd。常见做法是创建 systemd drop-in:
sudo systemctl edit docker示意内容:
[Service]
Environment="HTTP_PROXY=http://proxy.example.com:3128"
Environment="HTTPS_PROXY=http://proxy.example.com:3128"
Environment="NO_PROXY=127.0.0.1,localhost,.example.internal,registry.example.com"应用:
sudo systemctl daemon-reload
sudo systemctl restart docker
sudo systemctl show docker --property=Environment代理地址可能包含凭据,systemd配置、日志和命令输出都要按敏感信息保护。NO_PROXY 需要覆盖内部Registry和服务地址,格式和端口行为应按使用组件验证。
十五、Docker网络与宿主机防火墙
Docker会创建 bridge、veth、路由和 iptables/nftables 规则。安装后需要理解:
- Docker发布端口可能添加NAT规则。
- ufw/firewalld与Docker规则链交互可能与直觉不同。
- 云安全组、宿主机防火墙和Docker发布端口是不同层。
- 不能因为使用Docker就关闭宿主机防火墙。
- 不要随意设置
"iptables": false,否则端口发布、隔离和转发可能失效,并需要自行完整管理规则。
检查:
docker network ls
ip link show
ip routeiptables/nft命令需要管理员权限且不同系统后端不同。详细报文路径见 Docker网络底层原理。
十六、安装后的分层验证
hello-world 只能验证一部分链路,不能证明生产能力完整。
16.1 验证CLI、daemon和运行时
docker version
docker info
docker run --rm hello-worldhello-world 大致验证:
CLI连接daemon
↓
daemon解析镜像
↓
缺失时从Registry拉取
↓
containerd/runc创建容器进程
↓
stdout通过日志链路返回它没有充分验证:
- 端口发布。
- 自定义网络DNS。
- Volume持久化。
- 日志轮转。
- CPU/内存限制。
- Compose。
- daemon重启行为。
16.2 验证端口发布
docker run -d \
--name install-check-nginx \
--label training=docker-install \
-p 127.0.0.1:18080:80 \
nginx:1.27
curl -fsS http://127.0.0.1:18080/
docker port install-check-nginx16.3 验证自定义网络DNS
docker network create --label training=docker-install install-check-net
docker network connect install-check-net install-check-nginx
docker run --rm \
--network install-check-net \
busybox:1.36 \
wget -qO- http://install-check-nginx/16.4 验证Volume持久化
docker volume create --label training=docker-install install-check-data
docker run --rm \
--mount type=volume,source=install-check-data,target=/data \
busybox:1.36 \
sh -c 'echo persisted > /data/check.txt'
docker run --rm \
--mount type=volume,source=install-check-data,target=/data,readonly \
busybox:1.36 \
cat /data/check.txt第一次临时容器已删除,第二个容器仍读到数据,证明命名卷具有独立生命周期。
16.5 验证资源限制
docker run -d \
--name install-check-resource \
--label training=docker-install \
--memory=128m \
--cpus=0.5 \
busybox:1.36 \
sh -c 'while true; do sleep 60; done'
docker inspect \
--format 'memory={{.HostConfig.Memory}} nanoCpus={{.HostConfig.NanoCpus}}' \
install-check-resource
docker stats --no-stream install-check-resource16.6 验证Buildx与Compose
docker buildx version
docker buildx ls
docker compose version16.7 安全清理验证对象
先按标签列出:
docker ps -a --filter label=training=docker-install
docker network ls --filter label=training=docker-install
docker volume ls --filter label=training=docker-install只清理明确实验对象:
docker stop install-check-nginx install-check-resource
docker rm install-check-nginx install-check-resource
docker network rm install-check-net
docker volume rm install-check-data不使用全局 prune,不影响其他业务对象。
十七、日志轮转验证
daemon默认日志设置通常只影响之后新创建的容器。创建容器后检查:
docker inspect \
--format '{{json .HostConfig.LogConfig}}' \
install-check-nginx如果容器已在应用默认设置前创建,单纯重启不会改变 HostConfig;需要受控重建。日志路径和磁盘告警还应结合:
docker info --format '{{.DockerRootDir}}'
docker system df -v
df -h
df -i十八、升级Docker Engine
升级不是直接运行 apt upgrade 后观察运气。
18.1 升级前收集
docker version
docker info
docker ps -a --no-trunc
docker image ls --digests
docker volume ls
docker network ls
sudo systemctl status docker --no-pager还需:
- 阅读目标版本Release Notes和弃用项。
- 检查API、Compose、Buildx、日志和存储驱动兼容性。
- 确认容器是否有其他节点承接。
- 确认数据库和Volume备份。
- 在测试/预发验证。
- 准备包版本回退和配置回退。
18.2 查看可用版本
Ubuntu/Debian:
apt-cache madison docker-ce
apt-cache policy docker-ce docker-ce-cli containerd.io生产应显式选择经过验证的版本组合。具体包版本字符串由仓库决定,不在文档中硬编码一个会过时的值。
18.3 升级窗口
flowchart TD
A["测试环境验证目标版本"] --> B["备份配置与业务数据"]
B --> C["摘流或迁移容器"]
C --> D["升级一个金丝雀节点"]
D --> E["验证daemon、网络、Volume、日志和业务"]
E --> F{"是否正常"}
F -- "否" --> G["停止扩散并按预案回退"]
F -- "是" --> H["分批升级其他节点"]live-restore 可在部分 daemon 不可用场景保持容器进程,但不等于升级完全无影响:CLI管理、网络变更、日志链路和新容器创建仍可能受影响,具体版本升级是否支持无缝需要验证。
十九、卸载软件包与删除数据必须分开
查看包:
dpkg -l | grep -E 'docker-ce|docker-ce-cli|containerd.io|docker-buildx|docker-compose' || true停止业务和备份后,卸载包可使用发行版包管理器。重要原则:
- 卸载包不等于安全删除
/var/lib/docker。 - 数据目录可能保存命名卷和事故证据。
- containerd数据也可能独立存在。
- daemon配置、systemd drop-in、CA和仓库文件需要按变更单识别。
- 是否保留数据取决于迁移/重装目标。
本页不提供递归删除 Docker Root Dir 的命令。若确实永久退役主机,应先导出审计清单、完成业务数据销毁审批,再由基础设施流程精确处理。
二十、Docker Desktop:Windows和macOS不是原生Linux安装
20.1 Windows常见架构
flowchart TD
A["Windows上的docker.exe"] --> B["Docker Desktop"]
B --> C["WSL2或Hyper-V Linux环境"]
C --> D["Linux dockerd/containerd"]
D --> E["Linux容器进程"]检查 WSL:
wsl --status
wsl --list --verbose
docker context ls
docker version
docker info需要区分:
- Windows磁盘空间。
- Docker Desktop虚拟磁盘空间。
- Windows路径与Linux路径。
- WSL发行版与Docker Desktop内部环境。
- Windows代理与daemon代理。
项目源码放在跨Windows文件系统Bind Mount上,文件监听和大量小文件IO可能比Linux文件系统慢。数据库数据不应随意放在高延迟共享路径。
20.2 macOS
macOS 同样通过 Linux VM 运行 Linux 容器,不共享 macOS 内核。CPU、内存、磁盘和文件共享由 Docker Desktop 配置限制。--network host、路径权限和性能不能机械套用原生Linux结论。
20.3 商业许可与组织策略
企业使用 Docker Desktop 应核对当前许可条款、软件分发、自动升级、代理、证书和数据采集策略。具体条款可能变化,应由组织依据当前官方许可确认。
二十一、常见安装故障
21.1 APT仓库没有Release文件或404
检查:
cat /etc/os-release
cat /etc/apt/sources.list.d/docker.list
sudo apt-get update常见原因:
- Ubuntu/Debian仓库路径混用。
- 发行版代号错误。
- 衍生发行版代号不被上游仓库支持。
- 代理或DNS返回错误页面。
不要关闭仓库安全校验来“修复”。
21.2 GPG签名错误
检查:
ls -l /etc/apt/keyrings/docker.asc
grep signed-by /etc/apt/sources.list.d/docker.list方向:
- key文件下载失败或是HTML错误页。
- APT用户不可读。
signed-by路径错误。- 企业代理替换下载内容。
- 系统时间异常。
21.3 Cannot connect to the Docker daemon
docker context show
systemctl is-active docker
sudo systemctl status docker --no-pager
sudo journalctl -u docker --since "30 minutes ago" --no-pager
ls -l /var/run/docker.sock区分:daemon未运行、context错误、socket权限、配置失败、磁盘满。
21.4 普通用户permission denied
id
getent group docker
ls -l /var/run/docker.sock加入组后旧会话仍可能没有新组身份。重新登录或验证 newgrp docker。不要把 socket 改成全员可写。
21.5 daemon配置后启动失败
sudo dockerd --validate --config-file=/etc/docker/daemon.json
sudo journalctl -u docker -b --no-pager
systemctl cat docker常见:JSON逗号错误、同一选项同时在启动参数和配置文件、data-root权限、地址池冲突、代理格式错误。
21.6 拉镜像TLS或超时
先区分宿主机curl和daemon:
getent hosts registry-1.docker.io
curl -I https://registry-1.docker.io/v2/
sudo systemctl show docker --property=Environment
docker pull hello-worldRegistry /v2/ 返回未认证响应也可能说明TLS和HTTP链路已到达,具体状态需结合响应判断。
21.7 failed to mount overlay
检查:
uname -r
docker info
findmnt "$(docker info --format '{{.DockerRootDir}}')"
sudo journalctl -u docker --since "30 minutes ago" --no-pager方向:内核模块、底层文件系统、XFS特性、嵌套虚拟化环境、旧数据目录的storage driver不一致。
21.8 容器能启动但不能联网
检查:
docker network ls
docker network inspect bridge
sysctl net.ipv4.ip_forward再查 iptables/nftables、firewalld/ufw、企业安全软件、代理和DNS。不要立即关闭防火墙或Docker iptables管理。
二十二、商业场景:新生产节点上线验收
场景:为订单系统新增一台 Linux 容器节点。
22.1 验收清单
| 项目 | 必须记录 |
|---|---|
| 主机 | OS、Kernel、CPU架构、时区、NTP |
| Docker | Engine、CLI、containerd、runc、Compose、Buildx版本 |
| 安装源 | 仓库URL、签名key、包版本 |
| 存储 | Docker Root Dir、文件系统、空间、inode、告警 |
| 资源 | cgroup版本、CPU/内存限制验证 |
| 网络 | 地址池、DNS、代理、Registry、端口发布 |
| 安全 | docker组成员、socket权限、SELinux/AppArmor、审计 |
| 日志 | driver、轮转、集中采集 |
| 数据 | Volume策略、数据库备份和恢复 |
| 运维 | systemd、升级窗口、回滚、监控告警 |
22.2 验收过程
flowchart TD
A["按受信仓库安装固定版本"] --> B["验证systemd与daemon"]
B --> C["验证Registry拉取"]
C --> D["验证容器运行与日志"]
D --> E["验证端口和自定义网络DNS"]
E --> F["验证Volume持久化"]
F --> G["验证cgroup资源限制"]
G --> H["验证Compose和Buildx"]
H --> I["接入监控、日志和审计"]
I --> J["再接生产流量"]不能因为 hello-world 输出成功就直接承载数据库和订单流量。
二十三、面试标准回答
Docker安装了哪些核心组件
Docker CLI负责解析命令并调用Engine API,dockerd管理镜像、容器、网络和Volume,containerd管理容器任务和镜像内容,shim维持任务与IO,runc根据OCI配置创建namespace、cgroup和rootfs中的进程;Buildx负责高级构建,Compose插件把多服务项目模型转换为Engine对象。容器最终仍是宿主机Linux进程。
为什么docker组近似root权限
docker组成员可以访问rootful daemon的Unix Socket,通过Engine API创建高权限容器、挂载宿主机目录或设备,因此通常可以间接获得宿主机高权限。不能把socket改成所有用户可写,也不能挂给普通业务容器;成员必须按管理员权限审批和审计,或者评估rootless模式。
rootless Docker解决什么问题
rootless让dockerd和容器进程以普通宿主机用户运行,并通过User Namespace映射降低daemon或容器漏洞直接获得宿主机root的风险。但低端口、网络、cgroup、OverlayFS、设备和监控存在兼容边界,它也不解决镜像漏洞、Secret泄露和错误Mount。
hello-world成功能证明什么
它大致证明CLI能连接daemon、daemon能解析和拉取镜像、containerd/runc能创建进程、stdout链路可用。但不能完整证明端口发布、自定义网络DNS、Volume持久化、日志轮转、cgroup限制、Compose和daemon升级行为,生产还要分层验收。
修改daemon.json后怎么安全生效
先备份和检查当前配置、unit启动参数及业务容器,使用JSON和dockerd validate校验,避免同一参数同时出现在命令行和配置文件;在摘流和有回滚方案的窗口重启daemon,立即查看systemd状态与journal,再用docker info和容器验收确认data-root、日志、网络等配置真正生效。
Docker升级为什么要做金丝雀
Engine升级可能影响API、containerd/runc、storage driver、网络规则、日志和运行容器管理。应先在测试环境验证,备份配置和业务数据,摘流一个节点进行金丝雀升级,验证daemon、网络、Volume、资源限制和业务,再分批扩散;live-restore也不等于升级完全无影响。
二十四、学习验收
不看答案完成:
- 画出 CLI、dockerd、containerd、shim、runc 和内核关系。
- 解释Docker官方仓库的HTTPS、GPG key、signed-by和发行版代号。
- 安装Engine、CLI、containerd、Buildx、Compose并记录包版本。
- 使用systemd查看service、socket、unit和journal。
- 解释Docker socket、docker组和rootless安全边界。
- 规划data-root、日志轮转、地址池、DNS、代理和Registry。
- 分别验证hello-world、端口、网络DNS、Volume、资源限制、Buildx和Compose。
- 制造一个daemon.json语法错误,在不删除数据目录的情况下定位并恢复。
- 写出Engine升级金丝雀、回滚和业务验收计划。
- 说明卸载软件包为什么不能直接等同删除Docker Root Dir。
