1. 安装前的必修课:Docker CE到底是什么,为什么选它
今天不整虚的,直接说Docker CE。CE是Community Edition的缩写,也就是社区版,和它对应的是EE(Enterprise Edition)企业版。CE免费、开源、迭代快,新特性先在CE里验证,功能上核心的容器编排、镜像管理、网络隔离、存储卷这些全都有,绝大多数个人服务器、中小团队生产环境用的都是CE。你如果只是自己折腾、部署应用、搭CI/CD环境,选CE足够了,没必要为企业版掏钱,也没必要去搞什么“简化版”的三方发行套件,官方源装出来的最干净、最好排查问题。
我见过很多新手上来就问“Docker和虚拟机有什么区别”,其实一句话就能说清:虚拟机虚拟的是整台硬件,每个虚拟机里都有完整的内核和系统;Docker虚拟的是操作系统层,所有容器共享宿主机的内核,只是把用户态的文件、进程、网络隔离开了。所以容器启动速度是秒级甚至毫秒级,一个镜像几百兆就算大的,和虚拟机几个G起步完全不在一个量级。
这次讲的是Ubuntu和CentOS两条安装路线。标题里写的“Contos”我猜是CentOS的手误,这两个系统是目前服务器领域的两大主流阵营,一个走apt系,一个走RPM系,安装方式有同有异。我踩过不少坑,比如源没配好导致下载慢成蜗牛、内核版本太旧导致overlay2驱动起不来、systemd里Docker和NAT防火墙打架导致容器访问外网超时……这篇文章就是把这些事一次性说透。
2. 安装之前的硬性检查:不然后面全是坑
2.1 操作系统版本要求
不要拿着一个老的Ubuntu 16.04或者CentOS 7.0直接开干,Docker对系统版本有明确的最低要求。
| 系统 | 最低版本 | 推荐版本 | 说明 |
|---|---|---|---|
| Ubuntu | 22.04 LTS | 24.04 LTS | apt源直接有,内核默认满足 |
| Ubuntu | 20.04 LTS | 20.04 LTS | 经典老将,生产环境存量很大 |
| CentOS | 7.9 | 7.9 | 7.x系列最后更新的版本 |
| CentOS | 8.x | 8.5+ | 仓库已转Vault,需要修改源地址 |
| 其他 | - | - | 不支持或需要额外内核配置 |
有朋友问Ubuntu 18.04行不行,能用,但官方仓库已经不太积极维护那套软件包了,apt源里可能还是老版本Docker,新特性用不上,装的时候源配置也得折腾,没必要。CentOS 8是个特殊情况,上游停更以后默认的yum源全部失效,得先把baseos和appstream的源指到镜像站的Vault目录,再装Docker,这个流程我在后文会讲。
2.2 内核版本与存储驱动
Docker对内核最基本的要求是3.10以上,但这只是最低门槛。现代的Docker推荐用overlay2作为存储驱动,它要求内核支持OverlayFS,一般4.x以上的内核都没问题。如果内核太老,Docker会退回用devicemapper或者vfs,前者配置麻烦,后者性能差到离谱。
检查内核的命令很简单:
uname -r我实际遇到过一台老机器内核是3.10.0,yum装Docker倒是装上了,但docker info里Storage Driver显示的是devicemapper,拉镜像、启动容器都慢,而且有时候莫名其妙的文件读写报错。后来升级内核到5.x才彻底消停。所以装Docker之前先把内核版本确认一下,省得后面白折腾。
如果你跑的是Ubuntu,想确认存储驱动的可用性,可以看内核模块:
modprobe overlay lsmod | grep overlay没输出就说明模块没加载,Ubuntu默认会加载;CentOS 7默认是xfs文件系统,如果当初分区的时候用了ftype=0的xfs,overlay2会用不了,这个坑后面单说。
2.3 系统干净程度与防火墙状态
装Docker之前最好先看一眼系统里有没有装过podman、containerd这些容器运行时。有些发行版默认带podman,和Docker抢套接字和cgroup管理权,启动之后互相干扰。
which docker which podman rpm -qa | grep -E "docker|podman|containerd" # CentOS用 dpkg -l | grep -E "docker|podman|containerd" # Ubuntu用装了老版本Docker的话建议先彻底卸载,后面再说卸载细节。防火墙这块,Ubuntu的ufw、CentOS的firewalld如果开着,Docker的桥接网络可能会受iptables规则影响。我的建议是先保持防火墙开启,Docker装好后会自己写iptables规则,关键是别手动去清空iptables,不然容器的网络直接就断了。
3. Ubuntu上安装Docker CE:从零到能跑
3.1 卸载旧版本与依赖清理
如果系统里装过docker.io、docker-engine这些老包,先卸载干净。Ubuntu下这几个包名还不一样,注意全卸载。
sudo apt-get remove docker docker-engine docker.io containerd runc这一步做不做都不会影响新装,但做了图个安心。我遇到过两三次旧版docker.io残留了配置文件,导致新装的Docker启动时读到了旧的daemon.json,报一些奇怪的参数错误,卸载干净再装省得排查半天。
3.2 添加官方GPG密钥与apt仓库
这里说一个重点:不要直接apt install docker.io。你从Ubuntu官方源装的docker.io是阉割版或者老版本,依赖陈旧,后续compose插件、buildx这些新工具配起来还要走额外渠道,麻烦。正路是加Docker官方的apt源,虽然下载速度看网络情况,但版本新、组件全、升级方便。
先装依赖工具:
sudo apt-get update sudo apt-get install -y ca-certificates curl gnupg然后创建密钥目录并下载GPG密钥:
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把ASCII格式的密钥转成二进制,放到/etc/apt/keyrings目录,权限设成可读。以前很多人习惯把密钥追加到/etc/apt/trusted.gpg.d里,但新版apt在Ubuntu 22.04之后不推荐那种方式,用独立的keyrings目录更规范,apt不会报警告。
接着写源文件:
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这里用$(dpkg --print-architecture)自动识别架构,注意购买ARM服务器(比如鲲鹏、飞腾)的人这里会自动变成arm64,反之x86机器就是amd64。版本代号通过VERSION_CODENAME自动读取,Ubuntu 24.04是noble,22.04是jammy,一行命令解决,不用手写。
更新一下源索引:
sudo apt-get update如果这一步提示无法解析download.docker.com,说明服务器访问不了官方源,解决办法是换成国内的镜像源地址,把上面源文件里的download.docker.com替换成镜像站域名即可。具体地址我这里不推广特定服务商,你搜索“Docker apt镜像源”就有很多选择,选一个顺手的。
3.3 安装并配置镜像加速
源配好之后,安装就是一条命令的事:
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugindocker-buildx-plugin是构建镜像要用到的BuildKit增强插件,docker-compose-plugin提供docker compose子命令。新手很容易漏掉这两个,只装了docker-ce,后面想用compose还得再补。建议一步到位全装上。
装好之后先别急着用,先把镜像加速配置了。Docker从官方仓库拉镜像国内外速度差异极大,不配置加速源拉一个几百MB的镜像能等到怀疑人生。修改/etc/docker/daemon.json:
{ "registry-mirrors": ["https://你的加速地址"] }然后重启Docker:
sudo systemctl daemon-reload sudo systemctl restart docker用docker info看一下Registry Mirrors字段是否生效。
3.4 验证安装并跑起第一个容器
sudo docker run hello-world如果能正常打印出“Hello from Docker!”,说明整个安装链路是通的。这一步会从镜像仓库拉取一个极小的测试镜像,跑完即退,很适合做冒烟测试。
sudo docker version可以查看客户端和服务端版本,注意Client和Server都有才算真的装好。如果Server那部分报错,说明Docker守护进程没起来,看systemctl status docker排查。
4. CentOS上安装Docker CE:RPM系的正确姿势
4.1 卸载历史残留
CentOS上老的Docker包名是docker和docker-client,不是docker.io。先清理干净:
sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine如果系统是CentOS 8以上,yum已经被dnf接管了,但yum命令本身还能用,不用纠结,本质上都指向dnf。
4.2 配置yum源
CentOS 7装Docker需要先装yum-utils和device-mapper-persistent-data、lvm2,这些是Docker存储驱动和yum源管理要用的底层工具。
sudo yum install -y yum-utils device-mapper-persistent-data lvm2然后是核心步骤:添加Docker官方yum仓库。
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo同样的,如果访问官方源太慢,可以把仓库文件里的baseurl替换成国内镜像站,路径保持一样。这一步我建议直接做,因为在CentOS上不换源,后面yum install docker-ce大概率卡在下载几十MB的元数据阶段。
如果你是CentOS 8用户,yum-config-manager加好源之后会报错说仓库源指向了一个不存在的路径,因为CentOS 8的AppStream和BaseOS源都被官方移到Vault目录了。处理方式是编辑/etc/yum.repos.d/CentOS-Linux-*.repo这几个文件,把mirrorlist.centos.org的地址注释掉,把baseurl改成镜像站的CentOS-8下的对应目录,然后再装Docker。
4.3 安装与启动
sudo yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin注意一个细节:yum可能会提示你需要接受GPG密钥,或者遇到“没有可用软件包docker-ce”的报错。前者直接按y确认,后者大概率是源没生效,先跑一下yum makecache把缓存重新建立,再装。
安装完成后的启动和Ubuntu略有不同,CentOS默认不会开机自启,需要手动设置:
sudo systemctl start docker sudo systemctl enable docker不设置开机自启的后果就是服务器重启之后Docker服务不在了,所有容器不会自动恢复,如果是生产环境,这一下就够喝一壶。
4.4 CentOS特有的兼容性检查
CentOS 7上有几个特有的坑,这里必须单独列一下。
第一,overlay2和xfs文件系统的兼容问题。如果你当初装系统的时候,/var/lib/docker这个路径所在的分区用了xfs文件系统,并且format的时候没有开启ftype=1特性,Docker的overlay2驱动就用不了,会直接报“xfs: d_type verification failed”或者回退到vfs。怎么看当前分区格式:
df -Th /var/lib/docker如果是xfs,再查ftype:
xfs_info /dev/你的分区 | grep ftypeftype=0就悲剧了,常见解决办法是用ext4格式化一个独立分区挂到/var/lib/docker,或者重新格式化原分区(数据会没,慎重)。这个问题在CentOS 7默认安装配置里出现概率挺高,大家注意一下。
第二,SELinux问题。CentOS的SELinux默认是enforcing状态,Docker官方在CentOS上对SELinux的支持是有限的,有时候挂载文件会报权限错误。最简单的做法是给Docker相关的目录放行,或者直接临时把SELinux设成permissive:
sudo setenforce 0但这只是临时生效,重启又变回enforcing。要想永久生效就编辑/etc/selinux/config,把SELINUX=enforcing改成SELINUX=permissive。我自己生产环境是保持enforcing,然后给容器目录打上正确的SELinux标签,但这套操作对新手太复杂,如果你只是学习或者非核心环境,设成permissive没什么问题。
第三,iptables兼容性。CentOS 7默认用的是firewalld,Docker启动的时候会在nat表里加自己的规则。如果你在防火墙里手动配置过DOCKER链或者清空过iptables,容器网络会非常诡异。处理原则是:让firewalld管主机端口,让Docker管容器网络,两者别互相干预。
5. 装完必做的几个动作:别急着跑业务
5.1 配置镜像加速(不是可选项)
很多人喜欢把这步跳过,觉得“反正我网络快,不用加速也没什么”。等你真正拉一个node:20或者mysql:8的镜像,看着进度条几分钟纹丝不动,就该后悔了。镜像加速本质上就是给Docker配置一个registry mirror,拉镜像时优先打加速节点,没命中再回源。国内公共加速地址有很多,选一个稳定的填进去就行。
配置方式和前面Ubuntu部分一样,编辑/etc/docker/daemon.json。这里再强调一次,daemon.json是Docker守护进程的配置文件,改完必须重启守护进程才能生效:
sudo systemctl daemon-reload && sudo systemctl restart docker顺便说一句,改daemon.json有语法错误的话,Docker会直接起不来。改之前最好先用python3 -m json.tool校验一下JSON格式,别手滑打个中文逗号进去。
5.2 让当前用户免sudo执行docker
每次敲docker命令都要加sudo,相信我,几天之后你就烦了。把当前用户加入docker组:
sudo usermod -aG docker $USER然后重新登录或者执行newgrp docker让组权限生效。生效之后docker ps这些命令就不用sudo了。
注意这里有个安全隐患:docker组内的用户等同于root权限,容器可以通过挂载宿主机目录来实现任意文件读写,所以别随便把用户加进docker组。个人开发机无所谓,多用户服务器要谨慎。
5.3 调整Docker默认存储目录
Docker默认把镜像、容器层、卷都放在/var/lib/docker。如果系统盘不大,跑几个镜像就满了。我见过一个服务器根分区只有20GB,装了个数据库镜像加日志就飙到95%,直接拖垮整机。解决办法是把Docker数据目录迁移到大容量分区。
先停服务,再迁数据:
sudo systemctl stop docker sudo mv /var/lib/docker /data/docker # /data是大分区 sudo ln -s /data/docker /var/lib/docker或者直接用daemon.json指定data-root:
{ "data-root": "/data/docker" }两种方式效果一样,我倾向用软链接方式,因为这样即使以后重装Docker,旧数据也在原地,不会因为忘了配置data-root而找不到历史容器。
5.4 设置日志轮转,防止磁盘被日志撑爆
容器日志默认会无限写入宿主机的/var/lib/docker/containers目录,很多容器一旦输出日志多,比如Nginx访问日志、Java应用堆栈,一天就能写几个GB。如果不设轮转,磁盘迟早被写满。强烈建议在daemon.json里加上日志限制:
{ "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "3" } }这样每个容器日志文件达到10MB就会切分,最多保留3个文件,老的自动删掉。这个配置对已经有容器的环境,改完daemon.json并重启Docker之后新容器才生效,老容器要重建或者手动重启才生效。
6. 实战中的常见问题与排查思路
6.1 安装阶段的问题
问题1:apt update提示没有Release文件或仓库404
这种一般是源地址里的系统代号和你当前系统不匹配。比如你的系统是Ubuntu 21.10(代号impish),官方仓库早就把它对应的目录下线了,apt会报404。解决方法是改用代号对应的版本,比如升级系统到22.04,或者把源里VERSION_CODENAME手动改成jammy,但不保证兼容。
问题2:yum源下载Docker时一直卡住
CentOS上最常见的坑是yum源没换镜像,元数据下载慢。还有一个冷门原因:系统本地DNS解析有问题,download.docker.com解析到了IPv6地址,但服务器没有IPv6路由。可以加上ip_resolve=ipv4这个curl参数重新拉仓库文件:
curl -4 -fsSL https://download.docker.com/linux/centos/docker-ce.repo -o /etc/yum.repos.d/docker-ce.repo问题3:gpg密钥导入失败
一般是因为系统时间不对,https证书校验失败,用date看一下系统时间,差个几分钟就会出现这种怪问题。同步一下时间:
sudo ntpdate ntp.aliyun.com6.2 启动与运行阶段的问题
问题1:docker info提示server version报错
先查守护进程状态:
systemctl status docker journalctl -u docker -n 100大多数情况是daemon.json里配置写错了,或者端口被占用。有个很隐蔽的问题:如果你自己装了containerd并在非默认路径启动,Docker找不到它也会报错。解决方式是卸载掉系统自带的containerd,让Docker使用自带的那个。
问题2:容器内无法访问外网
这是老生常谈的问题了。排查顺序:宿主机能不能上网(排除物理链路问题)、宿主机ip_forward是否开启(sysctl net.ipv4.ip_forward,0就是没开)、防火墙nat规则是否完整(iptables -t nat -L POSTROUTING链里有没有MASQUERADE规则)。
CentOS上有个常见原因是NetworkManager把Docker的docker0网桥接管了,导致转发异常。把NetworkManager对docker0的托管关掉就行:
nmcli device set docker0 managed=no问题3:重启服务器后容器没有自动恢复
容器默认重启策略是no,就是永不自动重启。启动容器时加--restart=always,或者在已有容器的docker update里设置:
docker update --restart=always 容器名这样宿主机重启后,Docker守护进程启动时会自动把容器拉起来。
问题4:docker compose命令不存在
安装了docker-ce但是没装docker-compose-plugin。补上就行:
Ubuntu下:
sudo apt-get install docker-compose-pluginCentOS下:
sudo yum install docker-compose-plugin装完直接docker compose --version,注意新版是docker compose(中间有空格)而不是docker-compose连字符写法,后者是旧版Python实现的独立二进制。
6.3 卸载与重装
想卸载干净重装,Ubuntu下:
sudo apt-get purge docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin sudo rm -rf /var/lib/docker sudo rm -rf /var/lib/containerdCentOS下:
sudo yum remove docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin sudo rm -rf /var/lib/docker sudo rm -rf /var/lib/containerd删除/var/lib/docker这步要想清楚,里面有所有镜像和容器数据,删了就真的没了,最好提前确认没有需要保留的卷数据。
7. 两个发行版安装方式的对照总结
把Ubuntu和CentOS的安装流程揉在一起看,本质上是同一套思路:安装依赖工具、添加官方源、导入密钥、安装主包、启动并验证。区别只在包管理器命令和个别系统特性上。
| 环节 | Ubuntu | CentOS |
|---|---|---|
| 包管理器 | apt | yum/dnf |
| 依赖安装 | apt-get install ca-certificates curl gnupg | yum install yum-utils device-mapper-persistent-data lvm2 |
| 仓库配置 | 写apt源到/etc/apt/sources.list.d/ | 用yum-config-manager添加repo文件 |
| 密钥管理 | GPG密钥放/etc/apt/keyrings | repo文件内嵌gpgkey配置 |
| 服务管理 | systemctl | systemctl |
| 特有坑 | 系统代号过期 | SELinux、xfs ftype、CentOS 8 Vault源 |
不管用哪个系统,装完第一件事就是跑docker run hello-world验证。连hello-world都跑不起来,后面啥也别谈。
我个人在两项安装中最看重的就是源和存储驱动。源决定了你能不能装得上、下载快不快;存储驱动决定了你跑起来之后稳不稳。很多容器运行期诡异故障,追根溯源都是这两个环节埋的雷。
8. 安装收尾后的几点经验之谈
我在实际部署过程中体会最深的一条就是:别在生产服务器上做“最小化安装后马上跑业务”这种急事。装完Docker总要留十分钟做一次完整的状态体检,具体检查三样东西:docker info里Server Version和Storage Driver是否正常、daemon.json的JSON语法是否正确、docker run hello-world这种冒烟测试能不能过。
另外还有一个常被忽略的小技巧:把docker相关命令配置一条系统保留命令历史。因为Docker的命令变化快,新语法忘了翻历史记录会很痛苦。在bashrc里加一句:
export HISTTIMEFORMAT="%F %T "配合grep docker ~/.bash_history,随时能捞回来上次用的完整命令。
关于学习路线,我的建议是装好Docker之后别急着上Kubernetes,先老老实实玩两周单机Docker。把镜像构建、数据卷、网络模式、compose编排这几个核心概念搞熟练,再去看容器编排。否则一上来就是一大堆概念,Pod、Deployment、Service、Ingress全糊在一起,很难真正消化。
这篇文章把Ubuntu和CentOS两个平台上的Docker CE安装完整捋了一遍,每一步的坑也都标出来了。你按着操作,从一台裸机到能跑容器,算上镜像下载等待时间,半个小时之内可以搞定。遇到报错别慌,先看服务日志,日志里给的错误信息通常比你想的直白得多,照着关键字去搜,大概率能找到解决方案。