装 Docker CE 这事看起来就是复制几条命令的事但真到生产服务器上操作你会遇到仓库连不上、GPG 校验失败、SELinux 拦路、存储驱动不对这类七七八八的问题。Ubuntu 和 CentOS 两套流程虽然最终都装的是同一个 Docker但因为包管理器、系统初始化机制、安全模块的差异很多细节必须分开处理。这篇文章就把两套安装流程完整走一遍从装之前的系统检查、软件源配置到安装后的验证和坑点排查每一步都会给出实际命令和判断方法适合准备给 Linux 服务器搭建容器环境、又不想反复踩坑的同学直接参考。1. 安装前先搞清楚为什么选 Docker CE环境的坑在哪1.1 社区版和企业版怎么选顺手说说哪些版本不要碰Docker 的引擎版本分成两类Docker CE 社区版和 Docker EE 企业版。CE 是免费、开源、由社区维护的版本功能上已经涵盖日常开发和绝大多数生产需求容器运行、镜像构建、Compose 编排、网络管理这些核心能力都有。EE 主要是面向企业客户附加了镜像安全扫描、集中管控、商业支持这些东西普通团队基本用不上。除了这两类还有几个容易踩的坑。很多 Linux 发行版自带的软件源里有一个叫docker.io的包那是发行版维护者自己打的旧版 Docker版本往往落后官方一大截我见过不少机器装了它之后连新版docker compose的 v2 语法都不支持后面迁回官方版时还得先清理干净。另外 Ubuntu 上还有一种通过 Snap 安装 Docker 的方式安装确实快但 Snap 对文件路径做了隔离容器挂载目录、systemd 集成这些环节容易出现莫名其妙的问题生产环境也不建议用。所以这篇文章的安装方式统一走官方软件源也就是 Docker 官方维护的 apt/yum 仓库。1.2 安装之前的四个硬性检查内核、架构、包管理器、旧包残留装 Docker 之前我建议先花一分钟确认系统环境别上来就复制粘贴命令。第一条是内核版本。Docker 的存储驱动默认用overlay2它对内核版本有要求一般建议内核 3.10 以上新一些的发行版内核都在 4.x、5.x、6.x 了没什么问题。CentOS 7 默认的 3.10 内核也能跑 overlay2但要注意系统需要加载相关模块这个后面排错部分会提到。第二条是系统架构。Docker CE 官方支持 amd64、arm64、armhf 这些常见架构但 32 位系统基本不用想了。可以用uname -m看一下输出x86_64就说明是 64 位。第三条是包管理器的选择Ubuntu 走 aptCentOS 走 yum命令和软件源格式完全不同这也是我把两套流程拆开写的原因。第四条是检查机器上有没有装过旧的 Docker 包如果以前用其他渠道装过最好先卸载再装新版本避免新旧文件混在一起后面启动时各种冲突。1.3 软件源和 GPG 密钥的作用这一步省掉后面一堆麻烦Docker 官方软件源的作用不用多说就是告诉系统从哪里下载 Docker 的安装包。GPG 密钥的作用很多人容易忽略它是用来验签的确保你下载的软件包确实来自 Docker 官方而不是某个中间源被污染后塞给你的恶意包。早期教程喜欢用apt-key add来导入密钥但这个方式在新版本 apt 中已经标记为废弃现在推荐的做法是把密钥文件存到/usr/share/keyrings/目录然后在软件源配置里用signed-by参数指定它这套机制更安全也符合现代 Debian/Ubuntu 的实践。安装 Docker 的过程其实就是三条主线准备软件源、安装核心包、启动并验证服务。把这三条线理解了Ubuntu 和 CentOS 的差异就只剩命令长什么样的问题了。2. Ubuntu 装 Docker CE 完整步骤apt 源 GPG 校验2.1 先清掉旧 Docker别让残留包搞乱依赖如果你不确定机器上之前装没装过 Docker我的建议是先把旧包卸载一遍。Ubuntu 上这个命令是sudo apt remove docker docker-engine docker.io containerd runc这个命令会把常见的旧版 Docker 相关包清掉即使有些包不存在apt remove也不会报错它会正常继续。有一点要注意卸载不会删除/var/lib/docker目录这里面是历史的镜像层、容器文件系统、卷数据。如果你确定这些数据都不需要了可以在卸载之后手动删除sudo rm -rf /var/lib/docker如果你是在老机器上升级 Docker这个目录里可能存着重要业务的旧镜像删除之前一定要确认。我见过有人清理旧包后习惯性把整个 Docker 数据目录删了结果线上镜像全没了只能重新构建。卸载和删数据是两件事脑子要清醒。2.2 安装依赖包并导入官方 GPG 密钥接下来安装几个必需的依赖工具。Ubuntu 上这条命令sudo apt update sudo apt install -y ca-certificates curl gnupg lsb-release这里curl用来下载密钥gnupg提供gpg命令来处理密钥文件ca-certificates保证 HTTPS 证书校验能正常走通lsb-release里的lsb_release命令后面要用来获取系统版本代号。缺了任何一个后面的命令都可能卡住。导入 Docker 官方 GPG 密钥并保存成二进制格式curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpgcurl的-fsSL这几个参数别去掉。-f让 curl 在返回 HTTP 错误时不往下执行不然你可能会把一个错误提示页面的内容当成密钥文件导入后续安装时验签报错-sS是静默模式但保留错误输出-L是跟随重定向。我见过有人精简参数后导入密钥那一步花式报错花了好久才反应过来是参数少了。2.3 写入 apt 源并安装 Docker 核心组件接下来把 Docker 官方仓库写进 apt 源列表。这里有一个好习惯用dpkg --print-architecture自动获取当前系统架构用lsb_release -cs获取系统版本代号这样写出的命令在不同 Ubuntu 版本上都能直接用不用手动替换echo deb [arch$(dpkg --print-architecture) signed-by/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable | sudo tee /etc/apt/sources.list.d/docker.list /dev/null写完之后更新一次索引然后安装。我建议一次把 Docker 的核心组件装齐sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugindocker-ce是 Docker 引擎本体包括后台守护进程dockerd和命令行工具dockerdocker-ce-cli是命令行客户端containerd.io是底层的容器运行时负责真正创建和管理容器进程docker-buildx-plugin是新版镜像构建工具 Buildxdocker-compose-plugin是 Compose 编排插件。如果你只装了docker-ce后面会发现docker compose命令根本不存在所以这几个插件一起装上最省事。2.4 启动服务并验证安装是否成功安装完成后不会有弹窗提示你服务已启动但 Ubuntu 上 Docker 包一般会自动把 systemd 服务文件放好并启动守护进程。可以用下面的命令确认sudo systemctl is-active docker sudo docker run hello-world如果输出active并且hello-world容器能正常打印出信息说明安装成功。这中间如果出现Cannot connect to the Docker daemon先看服务状态多半是 dockerd 没起来原因五花八门后面第五部分会展开排查。最后还要做一步把当前用户加进docker组这样就不必每次敲命令都带sudosudo usermod -aG docker $USER执行完这一步一定要重新登录或者干脆重启一次终端会话。如果不重新登录当前会话的权限缓存里还没有你加入 docker 组的记录敲docker ps照样报 permission denied。这是一个非常容易让人误判是安装出问题的小坑。3. CentOS 装 Docker CE 完整步骤yum 源 systemctl 管理3.1 确认 CentOS 版本和生命周期状态再清理旧包CentOS 和 RHEL 系的仓库管理走 yumCentOS 8 也可以走 dnf先把系统版本确认了cat /etc/centos-release如果显示 7.x那就用 yum 走下面的流程。如果显示 8.x要留个心CentOS 8 已经结束维护了我建议这类机器尽快迁移到兼容的替代发行版上安装 Docker 的流程和 CentOS 7 几乎一样但系统的安全更新已经停了继续跑生产是很有风险的事情。如果你手上还有这类老系统后续换系统时 Docker 的数据目录/var/lib/docker是可以整体搬走的这一点在准备迁移时很有用。照例先清旧包sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine3.2 安装 yum-utils 并写入 Docker 官方 yum 源CentOS 配置软件源需要先装一个yum-utils里面提供了yum-config-manager命令这个命令可以一键把 Docker 官方仓库写入系统sudo yum install -y yum-utils sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo执行完第二条命令后/etc/yum.repos.d/docker-ce.repo文件就出现了。如果yum-config-manager找不到说明yum-utils确实没装上先检查那一步是否报错。CentOS 8 上如果默认没有yum-config-manager同样用yum install yum-utils解决。然后安装 Docker 组件和 Ubuntu 那边的包名几乎一样sudo yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin这里 yum 会自动处理依赖关系过程会比 apt 稍慢一点耐心等它跑完就行。3.3 systemd 启动、开机自启和安装后的验证CentOS 和 Ubuntu 一个明显的差异是Docker 安装完成后服务不会自动启动必须手动用 systemd 把它拉起来。一条命令同时完成启动和配置开机自启sudo systemctl enable --now dockerenable是设置开机自启--now表示立即启动服务加减号一举两得。以前有些教程让你先systemctl start docker再systemctl enable docker其实用enable --now一条就够了。启动后验证版本确保客户端和服务端都能正常看到docker version docker infodocker version会输出 Client 和 Server 两段信息。如果只有 Client没有 Server说明守护进程没有正常启动或者你当前用户访问不了 socket先去查服务状态。docker info能看到更详细的环境信息存储驱动、容器数量、系统内核这些都在里面。3.4 SELinux 与 firewalld生产环境最常翻车的地方CentOS 默认开启 SELinux很多人在 CentOS 上装完 Docker 跑容器结果遇到权限错误第一反应就是关 SELinux。我的建议是不要一上来就setenforce 0SELinux 本身和 Docker 是兼容的Docker 官方在 RHEL/CentOS 上做了大量适配工作正常情况下不需要关闭。如果你是因为某个容器挂载了宿主机目录而报 permission denied可以查一下/var/log/audit/audit.log里有没有avc denied记录如果确认是文件上下文问题用这条命令给挂载目录打上容器文件标签sudo chcon -Rt container_file_t /你的挂载路径另外CentOS 的 firewalld 和 Docker 的 iptables 规则可能会互相影响。Docker 在启动容器时会把规则插入 iptables而 firewalld 也在管理 iptables两者配合不好时可能出现容器间网络不通、端口映射失败等问题。遇到这类情况先看 firewalld 状态再查看当时的 iptables 规则确认 Docker 创建的链是否被其他规则干扰了。直接systemctl stop firewalld是一种常见的临时手段但生产环境我建议还是搞清楚是谁在冲突毕竟防火墙关了你的服务可能直接暴露到外网。4. 装完别急着跑验证容器、基础配置与生产级细节4.1 hello-world 验证全链路本地没镜像时会发生什么很多新手执行完docker run hello-world看到一大段英文输出后也不知道这算成功还是失败。其实这个镜像是 Docker 官方设计的一个极简测试镜像它本身只做一件事打印一段欢迎信息。关键不是这段文字说了什么而是这个过程验证了什么。运行命令时Docker 客户端会去连接守护进程守护进程发现本地没有hello-world镜像就会去远程仓库拉取拉完创建容器启动进程打印输出退出。整条链路客户端权限、守护进程、镜像拉取、容器运行时、进程隔离全都会在这条命令中走一遍。能成功跑完说明安装基本靠谱。如果卡在拉镜像那一步多半是网络问题解决办法在 4.3 节的镜像加速里先把加速配置好再跑验证。4.2 docker info 里的三个关键字段新手最容易忽略安装完别急着关终端执行一下docker info重点关注几个字段。第一个是Storage Driver正常情况下应该是overlay2这是 Docker 推荐的高性能存储驱动镜像层可以共享启动容器快写操作直接落在文件系统上效率高。如果显示vfs说明内核模块支持有问题Docker 被迫降级使用了最原始的存储方式性能差得离谱这种情况不要继续用去查内核和 overlay 模块。第二个是Cgroup Driver在主流系统上是systemd这表示容器资源控制通过 systemd 统一管理。第三种情况是cgroupfs在老版本 Docker 或特殊配置下会出现混用两种 cgroup 驱动在整机跑多容器时容易出问题。第三个是Logging Driver一般是json-file后面配置日志上限时改的就是它。想快速过滤某个字段可以用 Go 模板docker info --format {{.ServerVersion}} {{.Driver}} {{.CgroupDriver}}4.3 镜像加速与 daemon.json 配置下载提速的通用做法在国内环境使用 Docker镜像拉取慢是逃不开的问题。官方仓库在国外直接拉一个小镜像可能几百 KB 都能卡半天。通用解法是在 Docker 守护进程配置里加上镜像加速器镜像加速器一般由各大云厂商提供。修改配置文件/etc/docker/daemon.json如果文件不存在就新建内容大概是这样的结构{ registry-mirrors: [https://你的加速地址] }改完重启 Docker 生效sudo systemctl restart docker这里有个常见的配置错误文件内容如果是空的{}Docker 会当成没有额外配置来读但如果你把 JSON 写错了比如少了逗号或多了注释Docker 守护进程可能直接启动失败。改完配置文件后先执行sudo systemctl restart docker然后马上docker info看看有没有报错别等跑容器时才发现。加速器的地址要选择当前可用的网上很多年初还能用年底就失效的地址直接用错了反而是浪费时间。4.4 生产环境进阶日志上限、存储路径迁移、开机自启线上环境用 Docker有两件事我建议装完就做。第一是限制容器日志大小。Docker 默认会把容器写出来的标准输出和标准错误都存成 json-file 日志而且不设上限如果有个容器疯狂打日志/var/lib/docker/containers下的文件能涨到几个 GB最后把整块磁盘塞满。在daemon.json里加日志上限配置{ log-driver: json-file, log-opts: { max-size: 10m, max-file: 3 } }这样单个容器日志最大 10 MB保留 3 个文件滚出来的老日志自动删掉磁盘压力会小很多。第二是如果根分区空间不大我建议把 Docker 的数据目录迁到大磁盘上。Docker 默认数据目录是/var/lib/docker如果你的系统盘只有 40 GB随便拉几个大镜像就满了。迁移步骤不复杂先把 Docker 服务停了把数据整个复制到新目录然后改daemon.json里的>{ data-root: /data/docker }实际迁移命令sudo systemctl stop docker sudo rsync -avxP /var/lib/docker/ /data/docker/ sudo systemctl start docker迁移完成后先确认原来目录里的镜像在docker images里还能看到再考虑清理旧目录。rsync 过程中不要中断否则数据不一致Docker 启动后可能报错。至于开机自启Ubuntu 上 Docker 包一般装完就默认开了CentOS 上通常需要手动执行一次sudo systemctl enable --now docker。装完之后可以顺手确认一下sudo systemctl is-enabled docker输出enabled就说明开机自启已经配置好了。5. 实战排错速查表我踩过的 Docker 安装故障5.1 Cannot connect to the Docker daemon 这类启动问题这个报错是安装后最常遇到的出现时先不要怀疑命令敲错了基本方向是守护进程没有正常监听。第一步看服务状态sudo systemctl status docker sudo journalctl -u docker -n 50 --no-pagersystemctl status会显示当前服务是否 active (running)如果显示 failedjournalctl里基本会有堆栈信息照着错误往下查。如果你是非 root 用户报错内容是permission denied while trying to connect to the Docker daemon socket这其实和守护进程没关系就是当前用户不在docker组里重新执行sudo usermod -aG docker $USER并重新登录即可。5.2 下载超时、仓库连接失败、镜像拉取卡住这类问题在网络层面表现多种多样有的是apt update时连接download.docker.com超时有的是docker pull卡在waiting。先做基础判断执行curl -I https://download.docker.com看能不能正常访问如果能访问但很慢说明是网络到国外站点延迟高这时候就配镜像加速器。如果是 DNS 解析失败看一下cat /etc/resolv.conf确认系统 DNS 配置正常。还有一种情况是宿主机在公司内网需要走 HTTP 代理才能访问外网这时候 Docker 的拉取一般是配在/etc/systemd/system/docker.service.d/http-proxy.conf里面而不是在 daemon.json。普通场景下镜像加速器基本能解决 80% 的拉取问题。5.3 overlay2 和 iptables内核特性相关故障如果docker info显示存储驱动不是 overlay2或者启动容器时报ERROR: overlay2 is not supported说明内核模块没加载或者当前文件系统不支持 overlay。先手动加载模块sudo modprobe overlay如果提示modprobe: FATAL: Module overlay not found说明内核里根本没有这个功能那就不是配置能解决的需要升级内核。CentOS 7 上偶尔还会遇到 XFS 文件系统不支持d_type导致 overlay2 无法使用的问题这种情况通常会回退成 vfs性能下降明显。遇到文件系统相关的问题排查方向就是系统本身的内核和文件系统格式而不是 Docker 配置。还有一类报错是iptables failed: Resource temporarily unavailable这通常发生在 firewalld 或其他网络管理工具同时操作 iptables 的时候锁冲突导致 Docker 插入规则失败。可以试着重启一下 firewalld 或 Docker也可以稍等重试但更要紧的是搞清楚为什么会有两个程序同时操作 iptables长期解决方案是把规则管理职责拆清楚。5.4 端口冲突、磁盘打满、容器名重复等运行期报错装完 Docker 开始跑容器还会遇到几类高频报错我把常见情况和应对方法整理了一下报错症状常见原因排查 / 解决port is already allocated宿主机端口被其他进程或容器占用ss -lntp查看端口占用换映射端口name already in use同名容器已存在改名或先docker rm 旧容器名no space left on device磁盘满了或 inode 耗尽df -h、df -i再用docker system df查 Docker 占用device or resource busy挂载目录被占用删除容器/卷失败找到占用进程先停容器再删卷deadline exceeded拉镜像或容器操作超时多半和网络相关配合镜像加速器重试磁盘满是最隐蔽的因为很多人只看df -h忽略 inode 耗尽的情况Docker 数据目录里大量小文件很容易把 inode 用光这时df -h显示空间还有剩余但写文件还是报no space left。遇到这种情况执行df -i确认一下顺便说一句清理 Docker 数据用docker system prune或者docker image prune -a都比手动删文件安全手动删/var/lib/docker里目录搞坏 Docker 的概率非常大。5.5 几个经常被忽略的小细节有些细节不能算严格意义的报错但不注意会持续消耗你的时间。Docker 的补全功能装完 Docker 后Ubuntu 和 CentOS 上如果装有bash-completionDocker 包自带的补全脚本一般在/usr/share/bash-completion/completions/docker。如果 tab 键敲不出docker run的子命令提示检查一下这个文件是否存在重新加载 shell 后补全就能用了这条提升命令行体验很明显。GPG 密钥过期问题如果你是在老机器上配置的 apt 源可能某一天apt update突然报密钥签名错误那就是旧版的 GPG 密钥过期了。解决方式是按文章前面的方式重新导入一次官方最新密钥不用卸载 Docker。最后说一下守护进程的操作习惯Docker 服务在运行中尽量不要直接用kill命令杀dockerd进程这会绕过 systemd 的服务状态管理留下残留的 pid 文件和 socket下次启动时各种奇怪问题。一律用sudo systemctl restart docker处理干净又不会破坏状态。我在实际维护服务器的过程里最深的体会是Docker CE 安装本身真的不难难的是对系统现状的判断。同样的命令在 Ubuntu 20.04 和 24.04 上跑出来的行为不完全一样CentOS 7 和 CentOS 8 的依赖处理也各有脾气。所以别把教程当成机械的命令复制工具装的过程里多看一眼每一步的输出尤其是docker info和docker version的服务端部分确认它真起来了再继续。装完之后马上把镜像加速、日志上限、存储路径这几件基本配置做了后面省的心远不止这点时间。如果你接下来准备在这台机器上跑业务容器建议先用几个简单镜像把网络、存储、端口映射都测试一遍有问题在没上真实业务前暴露出来处理成本是最低的。