先交代一下背景。我经常在技术群里看到同一个问题“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 initps -p 1 -o comm如果输出是systemd就可以用systemctl管理 Docker 服务如果是init或者sysvinit服务管理命令会不同。现在主流发行版基本都是 systemd这个检查主要是帮老古董系统排雷。我的建议如果是生产环境优先选一个还在维护期内的发行版比如 Ubuntu 22.04 LTS、Rocky Linux 9而不是守着快 EOL 的版本强行装新东西。Docker 更新很快底层系统太旧后面升级容器引擎时才是真正的痛苦。2. Ubuntu/Debian 系完整安装从换源到跑通 hello-world2.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 gnupgca-certificates是为了 HTTPS 证书校验curl用来下载 GPG keygnupg用来处理密钥。这三样缺一不可少了后面必报错。2.2 添加 Docker 官方软件源GPG 钥匙这一步别跳过这一步是整个安装过程中最容易出问题的环节。先创建密钥目录并下载并处理 GPG keysudo 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 ar /etc/apt/keyrings/docker.gpg这里有两个细节很多人忽略--dearmor参数把 GPG 公钥从 ASCII 格式转换成二进制格式否则 apt 无法识别。chmod ar给密钥文件添加读权限。如果权限不对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 是 jammy24.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-plugindocker-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 docker3.2 CentOS 7 上老版本升级与新版本内核陷阱CentOS 7 是个绕不开的话题到现在还有大量生产机器在跑。如果你是从 CentOS 7 自带的老 Dockerdocker 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 网络策略依赖 iptablesCentOS 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 dockerusermod -aG中的-aappend很重要少了它会把用户从其他附加组里踢出去。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 dockermax-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_HOST5.2 在服务器上到处找 Docker Desktop 的误区最近总有人问“Linux 上怎么安装 Docker Desktop”。这里要先分清楚场景桌面版 Linux比如 Ubuntu Desktop、Fedora Workstation可以装 Docker Desktop它提供 GUI 界面、Kubernetes 集成、文件共享等功能。安装方式是去 Docker 官网下载 .deb 或 .rpm 包或者走官方 apt 仓库的docker-desktop包。服务器版 Linux无图形界面、远程 SSHDocker 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 21 DOCKER_COMPOSEdocker compose || DOCKER_COMPOSEdocker-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_PASSWORDYourStrongPass \ -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最大的体会是跟着官方文档走永远比搜来的“秒装脚本”稳装完第一时间把用户组、日志轮转、镜像加速配好后面能省一大半运维功夫。
阅读完成 · 觉得有帮助?