☰
Linux安装Docker全流程:源配置、权限与排错指南
2026/10/22 22:02:32 网站建设 项目流程

很多人第一次在 Linux 上装 Docker,都以为跑几条命令就完事了,结果真正折腾人的往往在后面:要么装完发现docker run连不上守护进程,要么 apt 源报错、密钥过期,要么 overlay2 存储驱动不支持,甚至有人装到最后连 hello-world 都没跑起来。我自己前前后后也给各种 Linux 环境装过不少次 Docker,踩过的坑几乎都集中在系统底子、软件源可用性、用户组权限和存储驱动这几块。这篇文章就把整个流程重新捋一遍:从装之前应该查哪些东西,到 Ubuntu / Debian 和 CentOS / RHEL 两套主流安装路线,再到权限配置、镜像加速、常见报错排查和卸载清理,全部按实际操作顺序来写。文章主要面向刚接触 Docker 的运维和开发者,也适合那些已经装上但总出莫名其妙的服务器环境做一次“重新体检”。

1. 动手安装前的三件自查:内核、代号与磁盘

1.1 先确认你的系统底子够不够

Docker 本质上依赖 Linux 内核的命名空间、cgroup、网络过滤等能力,所以内核太旧是装不动的。官方长期给出的最低门槛是 3.10 版本,但那是很多年前的要求了,放到今天看,3.10 内核配合新版 Docker 虽然能跑,却会遇到 overlay2 存储驱动限制、cgroup v1/v2 兼容性等一系列麻烦。

我的建议是:能用 4.18 以上内核的发行版就别停在老内核上。判断方法很简单:

uname -r cat /etc/os-release

第一条看内核版本,第二条看发行版代号。如果你手头是一台旧的 CentOS 6,内核还在 2.6 时代,那基本不用折腾了,先考虑升级系统再谈 Docker。反过来,Ubuntu 20.04 LTS 及更新的版本、Debian 11/12、CentOS 7/8、Fedora 这些主流系统,正常情况下都是可以直接装的。

不同发行版对应的包管理体系和安装方式有差异,我整理了一张简表,方便对照:

发行版包管理常用安装方式备注
Ubuntu / Debianapt / dpkg官方 apt 仓库兼容性最好,教程资料最多
CentOS / RHELyum / dnf / rpm官方 yum 仓库CentOS 7 用 yum,8 以上用 dnf
Fedoradnf官方 dnf 仓库新版本可能自带 Podman,注意端口冲突
openSUSEzypper官方 zypper 仓库用得少,但原理和其他发行版一致
Alpineapkapk 直接装镜像极小,适合轻量场景,但安装参数略有差异

还有一点容易被忽略:CPU 架构要统一。比如树莓派上常见的 32 位 ARM 系统,虽然也能装 Docker,但部分镜像和插件支持有限,后面拉镜像时容易踩“no matching manifest”这种错。若条件允许,尽量用 amd64 或 arm64 的系统。

1.2 磁盘布局别等满了才想起来

Docker 默认把镜像、容器、卷、构建缓存全部放在/var/lib/docker下。很多人只看剩余内存和 CPU,不看磁盘,结果 Docker 装上去没问题,用了一个月之后df -h一看根分区满了,连日志都写不进去。

所以装之前我一定先跑一句:

df -h /var/lib

如果/var/lib所在分区的剩余空间没到 10GB,我会事先把 Docker 的数据目录指到一个容量更大的挂载点上。最常见的做法是:先建目标目录,比如/data/docker,然后在/etc/docker/daemon.json里写上:

{ "data-root": "/data/docker" }

注意daemon.json是 Docker 守护进程的核心配置文件,改完一定要重启 docker 服务才生效。我见过不少同事装完 Docker 直接开始拉镜像,等根分区报警了才发现没提前规划磁盘,后面迁移数据又得停服务又得搬文件,折腾很久。

另外也要顺手看一眼 SELinux 和防火墙状态,倒不是说一定要关掉它们,但你要知道它们是存在的。尤其 CentOS 这类默认开启 SELinux 的系统,后面容器如果碰到operation not permitted之类的报错,别第一时间怀疑 Docker,先考虑是不是 SELinux 策略拦住了。

1.3 搞清楚要装的四个组件分别是什么

现在官方仓库安装 Docker,已经不是早年“一个 docker 包”那么简单了。以 apt 和 yum 仓库来说,会安装这么几个东西:

  • docker-ce:Docker 守护进程dockerd和客户端docker的主体包。
  • docker-ce-cli:命令行工具,单独拆出来是为了方便客户端和服务端版本不同步时单独升级。
  • containerd.io:容器运行时,负责镜像传输、容器生命周期管理,Docker 从早年的“docker + libcontainer 全家桶”拆分成了多个组件,containerd 如今是底层执行者。
  • docker-buildx-plugin和docker-compose-plugin:分别对应docker buildx和docker compose两个扩展命令,新版 Docker 都建议直接装插件版而不是单独的二进制。

装的时候最好一次性把上述几个都装上,不要只装docker-ce和docker-ce-cli。我踩过一次只装了前两个包、后面用docker compose时提示 command not found 的坑,最后还得回头看是不是插件包漏了。

2. 从软件源安装 Docker 的完整操作流程

2.1 为什么优先选官方仓库而不是系统自带包

几乎每个主流 Linux 发行版都自带一个名为 docker 的软件包,比如 Debian/Ubuntu 里是docker.io,CentOS 的 Extras 源里也可能有 docker。直接执行apt install docker.io确实能装,但我个人极不建议在生产环境这么干,原因有两个:

第一,版本严重滞后。发行版仓库里的 docker 往往停留在一年甚至几年前,你指望它支持最新的 构建特性、容器安全和 API 规范是不现实的。第二,升级策略受制于发行版。Docker 官方迭代快,安全补丁频繁,用发行版自带的包很难第一时间更新。

官方仓库把软件源单独放出来,目的就是解决这两个问题。虽然多几条配置命令,但后面升级非常省心,一条apt update && apt upgrade就能跟着官方版本走。

2.2 Ubuntu / Debian 系的完整命令序列

这是国内用户最常见的环境,也是官方文档写得很细的一条路线。我按实际执行顺序把命令拆开讲一遍,尤其是签名密钥这一块,很多人第一次配的时候容易在这一步翻车。

先安装基础依赖,并下载官方 GPG 密钥:

sudo apt-get update sudo apt-get install -y ca-certificates curl sudo install -m 0755 -d /etc/apt/keyrings 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

这里用了新的/etc/apt/keyrings目录和signed-by方式,而不是老的apt-key add。老的apt-key方式是全局信任密钥,只要键一被引入,连同签名密钥的来源就难以审计;而指定signed-by可以让 apt 只信任这一个仓库的签名,安全性和可维护性都更好。

接着添加软件源。Ubuntu 和 Debian 用的是同一个 Docker 官方仓库域名,但源码里要分别指向各自的发行版代号:

echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \ $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

这段命令里的$(. /etc/os-release && echo "$VERSION_CODENAME")是动态获取发行版代号,比如 Ubuntu 22.04 得到jammy,Debian 12 得到bookworm。不过这里有个隐藏坑:部分非官方定制系统,/etc/os-release里的代号可能跟 Docker 官方源不匹配,比如某些基于 Ubuntu 的国产发行版会覆盖VERSION_CODENAME。遇到这种情况,直接手动把代号改成对应的底层发行版代号就行,别死背命令。

之后就是常规的更新和安装:

sudo apt-get update sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

如果apt-get update报 “Release file is not yet valid” 或 GPG 签名相关的错误,先检查本机时间是否准确,再检查密钥文件有没有被chmod a+r授权可读。“Release file is not yet valid” 这种报错一大半是系统时间偏了,直接date看一眼。

2.3 CentOS / RHEL 系的仓库安装步骤

CentOS 7 和 CentOS 8 的安装思路与 Ubuntu 基本一致,只是命令变成了 yum/dnf。先安装yum-utils工具集,再用yum-config-manager把官方仓库加进去:

sudo yum install -y yum-utils sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

然后安装整套组件:

sudo yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

CentOS 8 及以上版本把yum换成了dnf,但yum作为兼容别名一般也能用。如果你装的是比较精简的 RHEL 衍生系统,可能连yum-config-manager都没有,此时可以改用dnf config-manager --add-repo,或者手动把.repo文件写到/etc/yum.repos.d/下。

装完后 CentOS 默认不会自动启动 Docker,这也是和 Ubuntu 一个明显的体验差异:

sudo systemctl start docker sudo systemctl enable docker

2.4 快速脚本安装与离线安装的备选路线

除了仓库安装,还有两条路线值得一提。一条是官方提供的快速安装脚本:

curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh

这个脚本会检测发行版、自动配置仓库并安装,演示环境里用着确实方便。但我不建议在无人值守的生产环境直接无脑跑:它会在系统里写入源配置和密钥文件,整个过程基本是黑盒,万一你后面维护翻车了,排查范围会变大。

另一条是离线安装。某些生产内网是完全无法访问外网软件源的,这时你只能准备离线包。最稳妥的做法是:

  1. 找一台网络环境相同、系统版本一致的机器,装上 Docker。
  2. 用apt download或yumdownloader把 docker 相关 rpm/deb 和它们的依赖全部拉下来,打成 tar 包。
  3. 在内网机器上dpkg -i或rpm -Uvh依次安装。

离线安装的难点不在 Docker 本身,而在依赖链路。containerd、runc 这些组件之间版本有对应关系,拉包时一定要按“完整依赖树”来,别只拿一个主安装包,否则装到一半提示缺这个缺那个,现场又没网,会很被动。

3. 装完别急着交差:服务、用户组与镜像加速

3.1 开机自启和服务状态确认

仓库安装完成之后,Docker 服务默认状态在不同发行版上并不一样。Debian/Ubuntu 系通常安装完会自动设置好开机自启,但 CentOS 系往往需要手动开启。我最怕看到的状态就是:装了几天之后服务器重启,然后发现所有容器都没了,敲docker ps报 “Cannot connect to the Docker daemon”。

排查依据很简单:

sudo systemctl status docker sudo systemctl enable docker

第一次装完最好就用systemctl enable docker把自启打开,别依赖记忆。服务是否正常,除了看status,还可以看日志:

sudo journalctl -u docker --no-pager -n 50

看懂服务日志是排查一切 docker 故障的基础能力。很多时候外面花式报错,到最后看一眼日志就发现只是磁盘满了或者某个目录没有权限。

3.2 用户组:不想每次敲 sudo 就这么配

Docker 客户端与守护进程通过一个 Unix socket 通信,默认路径是/var/run/docker.sock。这个 socket 文件默认属于root和docker用户组,所以普通用户直接敲docker ps会得到:

permission denied while trying to connect to the Docker daemon socket

解决办法是把当前用户加进docker组:

sudo usermod -aG docker $USER

这里要注意,用户组变更不是立刻生效的。很多人加完组直接再开一个终端去试,发现还是报权限错误,那不是没生效,而是当前登录会话里还没有把新组加载进来。稳妥的做法是执行完usermod之后重新登录,或者用newgrp docker刷新当前会话的组信息。

另外提醒一句:加入docker组的用户,本质上已经拥有和 root 相当的能力。因为 Docker 的 socket 可以让你直接挂载宿主机目录、执行容器内特权操作,所以只把可信用户加入这个组,别图省事给所有人开放。这一点在很多团队里都容易被忽略。

3.3 跑通 hello-world:整条链路是否正常的试金石

装完 Docker 之后,很多人第一件事就是拉业务镜像,实际上应该先跑官方提供的测试镜像:

docker run hello-world

这条命令做的事不少:如果本地没有镜像,会先从配置的镜像源把 hello-world 拉下来,然后创建容器、启动容器、输出一段欢迎信息、退出。它跑通了,说明客户端与守护进程的连接、镜像拉取、运行时创建容器这几个核心环节都没问题。

如果这一步汇报各种超时、网络错误,也别慌,十有八九是镜像拉取环节出了问题,不一定是你 Docker 本身装坏了。

3.4 镜像加速:daemon.json 的正确配置姿势

从公网拉 Docker 镜像的速度,受所在网络环境影响很大。很多人在拉镜像时遇到超时,第一反应是重试,第二次还是超时,第三次干脆怀疑自己是不是没装对。

这种问题通常可以通过配置镜像加速器缓解。Docker 支持在/etc/docker/daemon.json里配置registry-mirrors项,比如:

{ "registry-mirrors": ["https://你的云厂商加速地址"] }

改完别忘了一步,否则配置不生效:

sudo systemctl daemon-reload sudo systemctl restart docker

这里有个非常常见的坑:只改了文件,忘了重启,然后去看docker info发现 “Registry Mirrors” 下面什么都没输出,就以为是配置不生效。其实配置是启动时读取的,必须重启 dockerd。

验证配置是否生效的命令是:

docker info | grep -A 3 "Registry Mirrors"

在选择加速地址时,我的建议是不要盲目抄网上的公共地址。很多地址时效性很差,今天能用明天就失效。最靠谱的是看你自己所在网络环境里能稳定访问的云厂商加速服务,用它的配置生成一段地址,填入registry-mirrors。

4. 装 Docker 时最常见的四类求救信号

4.1 连不上 daemon,或者 socket 权限报错

最常见的一句报错是:

Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

遇到这句,先不要急着重装。按我的排查顺序来:

  1. sudo systemctl status docker看服务状态,如果服务是死的,systemctl start docker先拉起来。
  2. 服务起不来,看journalctl -u docker --no-pager -n 50日志。
  3. 如果服务正常,但普通用户仍报permission denied,再确认自己是否在docker组,以及当前会话是否重新登录过。

另一种报错干脆显示连接被拒绝:

dial unix /var/run/docker.sock: connect: permission denied

这种基本就是用户组问题。把用户加进组,重开终端,问题就消失了。不要一上来就改 socket 文件的权限,那等于把整个 Docker 的访问控制拆了。

4.2 apt 更新报错与 GPG 密钥问题

配置好 Docker 官方源后,下一次apt-get update可能突然报 GPG 错误,类似:

The repository '... Release' is not signed.

或者:

An error occurred during the signature verification.

这类问题的原因往往是密钥文件过期、被误删,或者系统时间漂移。应对方法是重新下载并安装密钥:

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 sudo apt-get update

还有一个容易忽略的场景:源文件里的发行版代号写错了。比如你在 Debian 12 上用了 Ubuntu 的jammy源码行,apt 找不到对应发行版的 Release 文件,会报类似 “The repository does not have a Release file” 的错误。所以sources.list.d/docker.list里那个代号一定要和实际系统匹配。

4.3 overlay2 存储驱动相关的坑

Docker 启动成功后,如果docker info里的 Storage Driver 显示的不是overlay2,而是vfs或者aufs,那就要小心了。vfs 是一个非常低效的复制型驱动,镜像一多,磁盘空间会疯涨;aufs 则是已经被淘汰的驱动。

overlay2 在较老内核或某些文件系统上可能不被支持,报错经常是:

ERROR: could not find a suitable storage driver Error starting daemon: error initializing graphdriver: backing file system is unsupported for overlay2

这通常发生在系统根分区是旧版 xfs 或没有 d_type 支持的文件系统上。一个是检查内核,另一个是检查分区挂载参数。最简单的规避办法是:把 Docker 数据目录挪到一个格式为 ext4 的全部分区上,通过前面说的daemon.json的>ss -tlnp | grep 3306

这时可以考虑换映射端口,或者停掉占用端口的进程。要注意,系统本身有没有跑着旧版容器运行时也很关键。某些发行版自带的 Podman 也会监听容器 socket,两个运行时同时存在时容易相互干扰。如果不需要 Podman,就果断禁用或卸载。

防火墙方面,如果你启用了 firewalld,容器端口映射有时会遇到外部访问不通的情况,因为 Docker 默认会操作 iptables 规则,firewalld 和 iptables 的策略叠加之后,规则顺序变得混乱。稳妥的做法是保证 Docker 需要的转发链路还在,具体取决于你环境里的稳定配置,这里不展开。

5. 升级、卸载与残留清理的后期动作

5.1 手动升级:脚本和仓库两条路线

Docker 装好以后不会再也不升级。小版本迭代很快,里面可能包含安全修复。如果你是用官方仓库安装的,升级非常简单:

sudo apt-get update sudo apt-get install --only-upgrade docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

CentOS 上对应的是yum update docker-ce docker-ce-cli ...。升级前建议先确认当前容器数量和数据卷情况,虽然正常升级不会动容器数据,但做任何有风险变更前先留个底,这是运维基本素养。

如果当年是用get-docker.sh脚本装的,升级也还是可以重新执行一遍脚本。脚本每次运行会把包更新到当时的最新版本,但我仍然推荐改用官方仓库,这样后面升级节奏完全可控。

5.2 卸载不彻底:为什么你总觉得“Docker 还在”

很多人卸载 Docker 只执行一个apt remove docker-ce,然后以为完事了,结果重新装的时候发现各种残留冲突,或者docker命令仍然存在。这是因为 Docker 的包拆得很细,需要逐个清理。

一个比较干净的卸载流程是这样的:

  1. 用包管理器卸载所有 docker 组件:
sudo apt-get remove -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
  1. 删除配置和源文件:
sudo rm -rf /etc/docker sudo rm -f /etc/apt/sources.list.d/docker.list sudo rm -rf /etc/apt/keyrings/docker.asc
  1. 删除数据目录。这一步要慎重,因为里面是所有容器和镜像数据,不可恢复:
sudo rm -rf /var/lib/docker sudo rm -rf /var/lib/containerd

如果不想把数据彻底删掉,可以先mv /var/lib/docker /var/lib/docker.bak留个备份,等确认新环境没问题后再删。

5.3 养成定期清理的习惯:缓存和日志是隐藏的磁盘杀手

Docker 用久了,最占磁盘的不一定是镜像本身,而是构建缓存、悬空镜像(dangling images)和容器日志。

docker system df能看到当前磁盘占用分布,类似于一个占用情况总览。清理构建缓存和停止的容器可以用:

docker system prune

这个命令会清理停止的容器、没有被使用的网络、悬空镜像和构建缓存,但对正在运行的容器和它依赖的镜像不会误删。如果要清理所有未使用镜像,加参数docker system prune -a,但这会连未在运行容器中使用的标签镜像一起删掉,下次要用时得重新拉,所以别手滑。

容器日志也需要留意。Docker 默认会把容器 stdout/stderr 写到宿主机的 json 文件里,时间长了有的单文件能到几个 GB。最好的方案是启动容器时就限制日志大小,在daemon.json里加:

{ "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "3" } }

这样单个容器日志文件最大的也就 30MB 左右,而不是无限增长。这个配置只对新创建的容器生效,老容器需要重建才会应用。

我自己养成的习惯是每个月固定看一眼docker system df,顺手把不需要的悬空镜像清掉,再检查一下/var/lib/docker/containers下的日志体量。这些操作不需要额外工具,几个命令的事,但能帮你省掉很多“磁盘突然爆满”的紧急事故。

最后再分享一个经验:安装 Docker 这件事本身不难,难的是装完之后对整个运行链路有清楚的认知。你要是能熟练看懂docker info的输出、会查journalctl日志、知道用户组和 daemon.json 都在管什么,那后面不管遇到什么诡异问题,都有一条清晰的排查路径在手上。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询