☰
Linux下安装Docker Engine完整指南:Ubuntu与CentOS实战排错
2026/10/10 12:36:49 网站建设 项目流程

先交代一下背景。我经常在技术群里看到同一个问题:“Linux 怎么装 Docker?”下面通常有人直接甩一条 curl 安装脚本,也有人复制一长串命令,但真操作起来,不少人装到一半就卡住——不是 GPG key 报错,就是装好了运行docker ps提示 permission denied,还有人在服务器上折腾半天找不到 Docker Desktop 的安装包。这篇文章把我在 Ubuntu、CentOS、以及国内常见发行版上装 Docker Engine 的完整流程和踩过的坑整理出来,既适合刚接触 Linux 的人按步骤复现,也适合运维老手快速对照排查。

1. 装之前先摸清发行版底细:安装路径不是一条路走到底

1.1 为什么官方文档要分成 Ubuntu 和 CentOS 两套流程

很多人第一次装 Docker 时,习惯去搜索引擎找一条“通用命令”,结果在 Debian 系能跑通的脚本,放到 CentOS 上直接报错说找不到apt-get。这不是脚本的问题,而是 Linux 生态本来就是“同族同源、异族异路”:

  • Debian/Ubuntu 系:包管理器是apt,软件源用sources.list.d/下面的.list文件管理,Docker 官方仓库提供的是deb格式的包。
  • RHEL/CentOS 系:包管理器是yum或dnf,仓库配置在/etc/yum.repos.d/,Docker 官方提供的是rpm格式的包。
  • openEuler、Rocky、AlmaLinux、Amazon Linux 等:多数基于 RHEL 体系,可以用 CentOS 的 docker-ce.repo,但要注意版本代号差异。
  • Deepin、UOS、Kylin 等:通常基于 Debian/Ubuntu 体系,apt 流程可用,但系统代号需要适配。

安装 Docker 前多花两分钟确认自己的发行版和包管理器,后面能少走很多弯路。用一行命令就能查清楚:

cat /etc/os-release

看ID和VERSION_CODENAME两栏,就能确定走哪条安装路线。

1.2 内核版本和系统初始化方式:先自查再动手

Docker 跑在 Linux 上,依赖内核的若干特性(命名空间、cgroups、网络桥接等)。新版 Docker Engine 对内核版本有硬性要求,安装前建议自查:

uname -r
  • 内核版本低于 3.10的旧系统(比如 CentOS 6),官方已经不再支持,直接装 Docker 会出现各种诡异问题,建议先升级系统。
  • CentOS 7 默认内核是 3.10.x,虽然能用 overlay2 存储驱动,但遇到文件系统问题比新版内核多。如果准备长期跑 Docker,建议选内核 4.x 以上的发行版(如 Rocky Linux 9、Ubuntu 22.04+)。
  • 内核版本 5.x 及以上,基本不用担心兼容性,直接往下走。

另外还要确认系统的初始化方式是 systemd 还是 SysV init:

ps -p 1 -o comm=

如果输出是systemd,就可以用systemctl管理 Docker 服务;如果是init或者sysvinit,服务管理命令会不同。现在主流发行版基本都是 systemd,这个检查主要是帮老古董系统排雷。

我的建议:如果是生产环境,优先选一个还在维护期内的发行版(比如 Ubuntu 22.04 LTS、Rocky Linux 9),而不是守着快 EOL 的版本强行装新东西。Docker 更新很快,底层系统太旧,后面升级容器引擎时才是真正的痛苦。

2. Ubuntu/Debian 系完整安装:从换源到跑通 hello-world

2.1 先清理旧版本,避免“半新半旧”的脏环境

如果机器上之前用apt install docker装过老版 Docker(比如 Ubuntu 自带的 docker.io),建议先清掉,再装官方 docker-ce。两个版本混在一起,经常出现/usr/bin/docker和/usr/bin/dockerd版本不一致的问题。

sudo apt-get remove docker docker-engine docker.io containerd runc

这个删除命令不影响/var/lib/docker下的镜像和容器数据。如果想彻底重置环境(比如之前配置搞乱了),可以再删数据目录,生产环境慎用:

sudo rm -rf /var/lib/docker

接着更新索引并安装基础依赖:

sudo apt-get update sudo apt-get install ca-certificates curl gnupg

ca-certificates是为了 HTTPS 证书校验,curl用来下载 GPG key,gnupg用来处理密钥。这三样缺一不可,少了后面必报错。

2.2 添加 Docker 官方软件源:GPG 钥匙这一步别跳过

这一步是整个安装过程中最容易出问题的环节。先创建密钥目录并下载并处理 GPG key:

sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg sudo chmod a+r /etc/apt/keyrings/docker.gpg

这里有两个细节很多人忽略:

  • --dearmor参数把 GPG 公钥从 ASCII 格式转换成二进制格式,否则 apt 无法识别。
  • chmod a+r给密钥文件添加读权限。如果权限不对,apt update 会报Key is stored in legacy trusted.gpg keyring或者直接无法校验。

然后写入软件源。我建议用官方文档里的动态写法,不要手写死版本代号:

echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] 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,24.04 是 noble),写死代号会导致后续换系统版本时软件源失效。动态获取能省掉这个麻烦。

注意:Ubuntu 的过渡版本(比如 21.10、23.04)在停止维护后,Docker 官方仓库会移除对应的软件源路径。如果你正好用这类版本,apt update 会报 404。要么换 LTS 版本,要么把$VERSION_CODENAME手动改成离它最近的 LTS 代号(比如把 impish 改成 jammy),但不保证依赖完全兼容。

执行完上面的写入后,重新 update 并安装:

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

docker-ce是守护进程和客户端主包,docker-ce-cli是命令行工具,containerd.io是容器运行时,docker-buildx-plugin和docker-compose-plugin是官方推荐的构建插件和 Compose 插件。一步装齐,后面就不用再补装了。

2.3 启动服务并验证:hello-world 不只是跑个寂寞

安装完成后先启动服务并设置开机自启:

sudo systemctl enable --now docker

然后检查版本:

docker version

如果服务正常,会分别显示 Client 和 Server 的版本信息。注意 Server 部分不能为空,如果只有 Client 没有 Server,说明 daemon 没起来,看后面的排错章节。

接下来跑经典验证:

sudo docker run hello-world

这个镜像只有几百 KB,如果能看到 “Hello from Docker!” 的输出,说明整个链路(拉镜像、创建容器、运行、输出)已经打通。到这里,Ubuntu 系的最小可用环境就齐了。

3. CentOS/RHEL 系安装与旧版本升级:yum-config-manager 与内核的坑

3.1 用 yum-utils 添加仓库

CentOS/RHEL 系装 Docker 的前两步,关键是添加官方仓库。先装 yum-utils(提供yum-config-manager工具):

sudo yum install -y yum-utils

然后添加 Docker 官方仓库:

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

这里有个细节:Rocky Linux、AlmaLinux 等 RHEL 衍生版也可以直接用这个 CentOS 仓库,因为包格式和系统兼容性一致。但如果你的系统是 RHEL 9 或 Rocky 9,软件源里的$releasever会自动解析成 9,而 centos 仓库确实有对应的 9 目录,所以可以正常使用。对于 CentOS Stream 用户,同样适用。

清理缓存并安装:

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

安装完成后同样启用服务:

sudo systemctl enable --now docker

3.2 CentOS 7 上老版本升级与新版本内核陷阱

CentOS 7 是个绕不开的话题,到现在还有大量生产机器在跑。如果你是从 CentOS 7 自带的老 Docker(docker 1.13,来自 base 源)升级到 docker-ce,官方建议是先把老的卸掉:

yum remove docker docker-common docker-selinux docker-engine

这里的docker-selinux是齐装保险,老版本装了但名字可能不完全相同,逐个yum list installed | grep docker查出来再删也行。

CentOS 7 最大的坑是内核。默认 3.10 内核跑 Docker 会出现两类问题:

  • overlay2 存储驱动不稳:虽然 RHEL 7 内核有 backport 补丁,官方声称支持 overlay2,但在大量写操作、磁盘压力大的场景下,还是能遇到文件系统层面的异常。如果你用 CentOS 7 跑生产容器,要么升级内核(用 ELRepo 的 kernel-lt 或 kernel-ml),要么老老实实接受可能存在的存储问题。
  • iptables 版本过旧:Docker 网络策略依赖 iptables,CentOS 7 默认的 iptables 版本较老,配合 firewalld 会出现端口映射不生效的问题。常见现象是容器起来了,docker ps里看到 8080→80 映射,但从外部 curl 不通。排查时先看firewall-cmd --list-all确认端口是否放行,再看/proc/sys/net/ipv4/ip_forward是否为 1。

我的实际建议是:如果机器还要跑三五年,别在 CentOS 7 上死磕,直接迁到 Rocky Linux 9 或 AlmaLinux 9,内核 5.14,省掉一大半隐性问题。Docker 本身升级很快,底层系统落后反而拖后腿。

4. 装完才是开始:权限、开机自启与镜像加速三件套

4.1 docker 用户组:告别每条命令前面挂 sudo

装完 Docker 后,普通用户直接跑docker ps会撞上 permission denied。原因很简单:Docker 客户端要和/var/run/docker.sock这个 Unix Socket 通信,而该 Socket 默认属主是 root:docker,普通用户不在 docker 组里,没有访问权限。

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

sudo usermod -aG docker $USER newgrp docker

usermod -aG中的-a(append)很重要,少了它会把用户从其他附加组里踢出去。newgrp docker是让当前终端立即生效,不用注销重登;如果换了新终端还报错,注销一次就好。

需要提醒的是:docker 组的权限等价于 root。能操作 Docker 的用户可以挂载主机目录进容器,也就等于能读写宿主机文件。所以这个操作只应该用在可信用户身上,生产环境切忌把一堆人加进 docker 组。

4.2 开机自启与日志清理:不配置好后面迟早要还

systemctl enable --now docker已经同时完成开机自启和立即启动。但 Docker 默认的日志策略是“无限增长”,容器只要一直打印日志,/var/lib/docker/containers下的 json 日志文件会膨胀到几个 GB,把磁盘塞满。

建议安装后马上创建一个守护进程配置文件,把日志轮转配置好:

sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<'EOF' { "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "3" }, "registry-mirrors": [] } EOF

改完配置后重启:

sudo systemctl restart docker

max-size: 10m表示单个日志文件达到 10MB 就轮转,max-file: 3表示最多保留 3 个文件。这样单容器最多占 30MB 日志空间。这个配置我建议从第一天就设上,别等磁盘告警了再去清日志,那是给自己找活干。

4.3 镜像加速:网络环境下的必要配置

如果发现docker pull经常超时或速度感人,可以在刚才的daemon.json里加registry-mirrors:

{ "registry-mirrors": ["https://docker.mirrors.example.com"] }

国内常见的做法是配置云厂商提供的容器镜像加速地址(阿里云、腾讯云等控制台里都能找到专属地址)。配置后执行systemctl daemon-reload && systemctl restart docker,再用docker info查看 Registry Mirrors 字段确认生效。

需要说明的是,镜像加速只对 Docker Hub 的公共镜像有效。如果你要拉的是其他私有仓库镜像,加速不生效,需要单独配置认证或代理。

5. 真实排错:三个高频翻车现场及完整排查思路

5.1 permission denied while trying to connect to the docker api

这是我见过最频繁的报错。完整信息是:

permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock

按以下顺序排查,基本都能定位:

排查步骤命令判断依据
确认 daemon 是否运行systemctl status docker状态应为 active (running)
确认 Socket 权限ls -l /var/run/docker.sock属主应为 root:docker,权限 srw-rw----
确认当前用户组groups $USER应包含 docker
确认环境变量env | grep DOCKER_HOST如果有 DOCKER_HOST 指向了别的地址,会导致客户端去找错误的 daemon

很多人只盯着“权限”二字,以为是文件权限不对,结果检查 Socket 权限完全正常,最后发现是DOCKER_HOST这个环境变量在作怪。有些工具(比如某些 CI 客户端或之前的调试脚本)会设置它,把它 unset 掉再试即可:

unset DOCKER_HOST

5.2 在服务器上到处找 Docker Desktop 的误区

最近总有人问“Linux 上怎么安装 Docker Desktop”。这里要先分清楚场景:

  • 桌面版 Linux(比如 Ubuntu Desktop、Fedora Workstation):可以装 Docker Desktop,它提供 GUI 界面、Kubernetes 集成、文件共享等功能。安装方式是去 Docker 官网下载 .deb 或 .rpm 包,或者走官方 apt 仓库的docker-desktop包。
  • 服务器版 Linux(无图形界面、远程 SSH):Docker Desktop 没有意义。它就是一层封装,底层还是要 docker-ce 引擎,而且它的虚拟机组件在纯服务器环境下纯属多余。

如果你在无桌面的云服务器上执行yum install docker-desktop,大概率找不到包,因为 Docker Desktop 没有走 yum 仓库分发。正确的是装 docker-ce 那套,参看前面第二、三节。一句话:服务器装 Engine,桌面机才考虑 Desktop。

5.3 docker compose 命令不存在

装完 docker-ce 后执行docker compose version报 command not found,有两种可能:

  • 你的docker compose是子命令形式,需要docker-compose-plugin插件包。Ubuntu 系把插件放在docker-compose-plugin这个包名里,CentOS 系则是docker-compose-pluginrpm。如果当初只装了docker-ce没装插件,补上即可:
sudo apt-get install docker-compose-plugin # 或者 sudo yum install -y docker-compose-plugin
  • 你习惯的是老版docker-compose独立命令。新版插件语法是docker compose up -d(中间有个空格),老版是docker-compose up -d(连字符)。如果项目里的docker-compose.yml还在用旧语法,装新插件后记得把命令改成docker compose up -d。

提示:在脚本里判断用哪个命令时,可以这样写:docker compose version >/dev/null 2>&1 && DOCKER_COMPOSE="docker compose" || DOCKER_COMPOSE="docker-compose",但建议新项目统一docker compose,官方新特性基本都往插件上堆。

6. 用真实业务容器做最终验证:Nginx 与 MySQL 的部署检查

6.1 拉取并运行 Nginx:五分钟确认端口映射和网络正常

装完 Docker 光跑 hello-world 是不够的,它只验证了“容器能跑起来”,没验证“宿主机和容器的网络打通”。我用 Nginx 做第一次业务验证:

docker run -d --name nginx-test -p 8080:80 nginx:latest

-d是后台运行,-p 8080:80表示把宿主机的 8080 端口映射到容器内的 80 端口。执行后等几秒,然后验证:

curl -I http://localhost:8080

如果返回 HTTP/1.1 200 OK,说明:

  • 镜像拉取正常(网络通)
  • 容器创建和启动正常(运行时正常)
  • 端口映射正常(iptables/NAT 正常)

如果 curl 不通,先执行docker logs nginx-test看容器日志,再执行docker port nginx-test确认映射配置。注意像 8080 这种端口,如果宿主机开了 firewalld,需要放行端口。

6.2 启动 MySQL 8.0:数据卷挂载与远程访问检查

很多人在群里问“怎么访问 Docker 容器内的 MySQL”,这个坑通常不在容器内,而在端口映射和认证配置。我用一个带数据卷的 MySQL 8.0 容器演示:

docker run -d \ --name mysql8 \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORD=YourStrongPass \ -v mysql-data:/var/lib/mysql \ mysql:8.0

几个参数的含义:

  • -e MYSQL_ROOT_PASSWORD:容器初始化时设置 root 密码。注意只在首次初始化数据目录时生效,后面修改要用 SQL。
  • -v mysql-data:/var/lib/mysql:把 MySQL 的数据目录挂到 Docker 命名卷mysql-data上,容器删了数据还在。
  • -p 3306:3306:宿主机 3306 映射到容器 3306。

验证连接:

docker exec -it mysql8 mysql -uroot -p

从宿主机访问时,用mysql -h127.0.0.1 -P3306 -uroot -p。如果连不上,优先检查 MySQL 8 的认证插件:默认 caching_sha2_password,老客户端可能不兼容;另外确认容器实际监听端口:

docker ps | grep mysql8

如果STATUS列反复显示 Restarting,大概率是初始化参数问题,用docker logs mysql8看具体报错。我遇到过最常见的原因是首次启动时MYSQL_ROOT_PASSWORD没传导致初始化失败,删容器重来即可:

docker stop mysql8 && docker rm mysql8

数据卷mysql-data保留,再次docker run时会复用已有数据目录,不会重新初始化。

到这一步,Docker 在 Linux 上的安装、配置、排错和基本业务验证就全走完了。后面你可以沿着 Compose 路线把 Redis 主从、GitLab、青龙面板那类多容器应用编排起来,本质上都是在今天这个基础上叠加 YAML 文件的事。我自己装过太多次 Docker,最大的体会是:跟着官方文档走永远比搜来的“秒装脚本”稳;装完第一时间把用户组、日志轮转、镜像加速配好,后面能省一大半运维功夫。

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

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

立即咨询