标题已经写得很直白,这一章就是动手装东西。不管你是刚看完前面几章准备自己折腾一套开发环境,还是公司里要在一台新机器上把运行环境铺起来,Docker安装部署都是绕不开的第一步。这篇文章我会把整个安装过程掰开揉碎,从最开始的版本选择、环境检查,到实际敲命令、配镜像加速、踩坑处理,全部按真实操作顺序走一遍,尽量让照着做的朋友少走弯路。
这一章覆盖的内容比较基础,但基础不代表不重要。很多人的第一个Docker环境都有残留问题,比如装到一半源配错了、权限配置不到位、日志涨得飞快,这些问题源头都在安装阶段埋下的。所以我会把每一步“为什么要这么做”也讲清楚,而不是只丢一行命令让你复制。
1. 部署前先盘清楚:Docker是什么、装哪里、怎么选版本
1.1 Docker到底解决了什么问题
先花几十秒把Docker的价值捋一遍,不然你装了也不知道自己在装什么。Docker本质上是把应用和它依赖的运行环境打包成一个标准镜像,然后用容器来跑这个镜像。你可以理解成把一个软件的“完整生态系统”塞进一个标准集装箱里,不管集装箱运到哪台机器上,箱子里面的环境都不会变。
这带来的直接好处是部署效率大幅提升。以前发布一套服务,先装运行时、再配依赖、处理系统库版本冲突,光环境准备就可能花半天。有了容器,镜像一拉、容器一跑,应用就在里面跑起来了,外面系统不管是什么版本、缺了什么都跟你没关系。这也是为什么现在几乎所有的在线服务、微服务架构、持续集成流水线都在用Docker,连个人电脑上跑个数据库、装个中间件,用它也比直接装在宿主机上干净得多。
1.2 装在物理机、虚拟机还是个人电脑上
Docker的安装方式取决于你的场景,这决定了后面所有操作路径。
第一种是Linux物理机或云服务器,这是最标准、也最推荐的做法。容器本身就是Linux内核技术,在Linux上装Docker环境最自然,性能损耗最小,配置相对简单。生产环境、测试环境基本都走这条路。
第二种是Windows或macOS个人电脑。这类系统上是靠一个轻量级虚拟机把Linux内核跑起来,再在虚拟机里面跑Docker,官方对应的方案是Docker Desktop。便利性很高,适合做日常开发、本地联调,但不太适合当成生产运行环境来用,毕竟那层虚拟化多多少少会带来一些额外开销和兼容性边界。
第三种是虚拟机里面再装Docker。比如你在本机的虚拟化软件里开了一个CentOS或Ubuntu虚拟机,再把Docker装进去。这种相当于在物理机和个人方案之间取了个折中,适合需要模拟真实服务器环境、又不想直接上云的场景,我自己就经常这么干。有一点要提前跟你讲清楚:虚拟机里再套容器,性能会有一定损失,但用来学习、做实验完全够用。
1.3 版本怎么选:CE版还是发行版自带版
Docker官方提供的主要是Docker Engine(社区版)和Docker Enterprise(企业版)。社区版就是免费使用的,功能上已经覆盖了绝大部分开发和运维需求,咱们这一章安装的就是社区版。
很多人容易踩的一个坑是直接用Linux发行版自带的软件源里那个docker包。比如Ubuntu自带的docker.io,或者CentOS自带的老版本docker,装上确实能用,但版本更新通常滞后,功能落后,和最新版Compose、镜像格式之间都有兼容性问题。我建议一律从Docker官方源安装,这样能拿到最新稳定版,后续升级也统一。
另外要区分一下:安装Docker引擎不等于安装Docker Desktop。Docker Desktop是带图形界面和虚拟机Helper的个人电脑方案,而服务器上装的Docker引擎就是一个后台服务加一套命令行工具。这篇讲的后者。
2. 动手之前,先把环境条件和旧残留清干净
2.1 系统版本与内核要求,先查一遍再装
Docker对Linux系统是有要求的,不是随便哪个版本都行。先说硬性条件:操作系统必须是64位,内核版本最低3.10,再低就会出各种诡异问题,满屏报错却定位不到原因。现在主流的Ubuntu 20.04以上、CentOS 7以上、Debian 11以上,基本都满足,但新机器上还是要自己确认一下。
在终端跑三条命令,把架构、内核版本、系统版本都看一眼:
uname -m uname -r cat /etc/os-release第一条看架构,x86_64就是64位;第二条看内核版本,如果内核只有3.10左右,建议先把系统升级到较新版本再装Docker;第三条看系统发行版和版本号,后面配置软件源要用到对应版本代号。
注意:如果内核太老,你装完Docker之后很有可能出现容器能启动、但网络不通或者存储驱动不对的情况。这不是Docker的问题,是内核能力不够。内核太老就老老实实先升系统,别硬着头皮往下装。
2.2 先卸载系统里可能存在的旧版本Docker
这一步很多人直接跳过,结果新装的时候要么提示包冲突,要么装完发现docker命令指向的还是老一套。如果你这台机器以前装过docker、docker.io、docker-engine之类的包,最好先把它们清掉。
Debian系的清理命令大概是这样的:
sudo apt-get remove docker docker-engine docker.io containerd runcCentOS系则用:
sudo yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine如果你的机器本来就是全新的,没装过Docker相关东西,这一步可以跳过,不影响。
这里有个细节要提醒一下:卸载旧包不会删掉数据目录 /var/lib/docker。这个是故意的,因为里面可能是你之前辛苦拉下来的镜像和容器数据。如果你确定旧数据不要了,可以手动删掉它;如果要保留,就不要动。旧数据目录对安装本身没有影响,但如果你发现新装完Docker后docker images里还有旧镜像,别慌,那是因为镜像数据还在。
2.3 把软件源切成更快更稳的镜像源
这一步不是Docker专属,而是所有Linux软件安装的基本功。你的服务器默认用的软件源可能在国外,直接apt-get update或者yum makecache会非常慢,甚至超时,导致后面添加Docker源的时候半路卡死。
我一般都会先把系统源切成距离自己机房比较近的镜像源,这个操作因发行版而异。Ubuntu、Debian修改/etc/apt/sources.list或者/etc/apt/sources.list.d/下的文件,CentOS则有自己的Base源配置。切源完成后,先执行一次更新指令:
sudo apt-get update或者:
sudo yum makecache fast这样做的目的不只是为了快,更重要的是让系统能够正常访问、安装后面需要的依赖包。
3. 一步一步把Docker装上去
3.1 Debian/Ubuntu系列,用apt安装
Ubuntu、Debian以及它们的衍生版,最可靠的安装路径是走Docker官方apt源。第一步装几个基础工具:
sudo apt-get update sudo apt-get install ca-certificates curl gnupg第二步,创建目录并导入Docker官方GPG密钥。这个密钥的作用是验证从Docker源下载包的签名,防止源被篡改或者下载到伪造包:
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第三步,把Docker官方的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如果你用的是Debian,把上面源地址里的/ubuntu换成/debian即可。
第四步,更新源并安装Docker引擎以及相关的构建和编排插件:
sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin这里安装的不只是docker-ce这个服务,还包含了命令行工具、容器运行时、构建插件和Compose插件。Compose是现在编排多容器应用绕不开的工具,所以直接一起装上最省事。
3.2 CentOS/RHEL系列,用yum或dnf安装
CentOS 7用yum,CentOS 8及以上或新的RHEL系用dnf,命令格式差不多。先装配置仓库的工具:
sudo yum install -y yum-utils然后添加Docker官方yum仓库:
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo接着安装:
sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin如果系统提示依赖冲突或者找不到包,仔细看下是不是安装源没有生效,或者系统版本代号和源不匹配。CentOS 7在2024年之后官方源逐渐停更了,装的时候如果遇到404错误,很大概率是源的问题而不是你操作的问题,需要适当切换源方式。
3.3 启动服务,并设置开机自启
安装完成以后,Docker服务默认不会自动启动,需要手动开启。执行:
sudo systemctl start docker sudo systemctl enable docker第二条命令是设置开机自启,非常重要。如果漏了这一步,服务器一重启,Docker服务就不会自动起来,你那些依赖Docker的容器、服务会全部连带挂掉。我见过不止一次线上事故就是因为装完忘记enable,机器一重启,容器管理器没了,业务直接不可用。
验证一下服务的运行状态:
sudo systemctl status docker看到active(running)就说明服务正常。如果你的机器用的是init.d管理方式而不是systemd,那就用sudo service docker start来启动,老一些的系统会用到。
3.4 装完先验证,确认这四件事没问题
安装完成不是终点,验证才是。我建议依次跑下面四组命令:
docker version docker compose version docker run hello-world docker infodocker version会显示Client和Server两段信息。Server要能看到版本号和平台信息,说明Docker进程跑起来了。如果只显示Client、不显示Server,说明服务没起来,检查systemctl服务状态。
docker compose version确认Compose插件安好了。docker run hello-world会拉取一个极小的测试镜像并运行,然后打印一串说明文字。这一步验证了镜像拉取、容器创建、运行整个最小链路是通的。docker info则能看到你当前使用的存储驱动、Cgroup驱动、CPU和内存等环境信息。
提示:如果docker run hello-world卡在拉镜像的地方迟迟不动,大概率是网络导致拉不下来,先去配置镜像加速器,再回来重试。这一步可以放在第四节的配置之后做。
4. 安装之后立刻要做的四件事,不然用两天就后悔
4.1 配置镜像加速器,拉镜像速度翻倍
Docker默认从Docker Hub拉取镜像,国内网络环境下经常会超时、断流。这个问题装完当天就要解决,不然你拉一个稍微大点的镜像,卡到怀疑人生。
办法是在/etc/docker/daemon.json里配置registry-mirrors字段。文件可能不存在,直接创建就行:
{ "registry-mirrors": ["https://your-mirror-address"] }把your-mirror-address换成你自己环境里可用的镜像加速地址。现在很多公有云厂商、容器服务商都提供免费的个人加速地址,你可以从当前使用的云服务商控制台里找到,也可以在社区里搜“容器镜像加速地址”获取。
配置完以后重启Docker服务:
sudo systemctl daemon-reload sudo systemctl restart docker重启后用docker info查看Registry Mirrors一栏,看到配置的地址就说明生效了。这一步是我给所有新装Docker环境的第一条建议,别等拉取镜像报错再回来弄。
4.2 让普通用户免sudo运行docker命令
Docker安装完后,docker命令默认需要root权限或者用sudo执行。每次敲命令都要加sudo很烦,而且会有权限上的麻烦。更推荐的做法是把需要用Docker的用户加入docker组。
执行:
sudo groupadd docker sudo usermod -aG docker $USER然后退出当前终端、重新登录,或者执行以下命令让组变更生效:
newgrp docker之后直接敲docker ps就能看到结果,不需要再带sudo。
这里必须强调一个安全点:docker组的用户权限约等于root权限,因为用户可以通过挂载宿主机目录进入容器,进而操作宿主机文件。所以生产环境的服务器上,千万不要随便把用户加进docker组,只给那些真正负责容器管理的人加。
4.3 限制日志大小,防止磁盘被写满
容器默认的日志驱动是json-file,会不断把标准输出写到宿主机文件里。如果不加限制,一个频繁打印日志的容器运行几天就能吃掉几十GB磁盘,直到磁盘满、服务全部崩溃。这个教训我在真实环境里遇到过不止两次。
解决办法是在daemon.json里加上日志相关的全局配置:
{ "log-driver": "json-file", "log-opts": { "max-size": "50m", "max-file": "5" } }含义是每个日志文件最大50MB,最多保留5个文件,超出就滚动清理。配置完后同样需要重启Docker服务。这只影响新建的容器,已经存在的容器还是用旧的日志配置,需要重建容器才会生效。
你也可以在docker run命令行里单独给某个容器配置,但既然daemon.json能一次搞定,建议直接配全局。
4.4 处理好防火墙、SELinux和网络转发
服务器上一般都有防火墙策略或者云安全组。Docker端口映射用的是iptables规则,如果宿主机的防火墙规则顺序不对,或者Docker自带的iptables链和你的安全策略冲突,很容易出现容器内部端口通了、外部访问不通的情况。
我的排查经验是:先确认宿主机防火墙放行了你要映射的端口,再确认云安全组放行对应端口,最后再看docker port容器名能看到正确映射。很多“容器起不来”的假象,其实是安全组或防火墙把流量挡住了。
CentOS系还有一个特殊点,SELinux。SELinux处于Enforcing模式时,容器挂载目录卷可能被拒绝,报Permission denied。如果你不走安全加固审计的老路,我建议把SELinux先设成permissive来排查,确系它阻碍后再调整相应的布尔值,不要一上来就禁掉它。
5. 卸载、升级和日常维护,别等出事才想起来
5.1 想要干净卸载Docker,这几个残留点都要清
卸载Docker比安装容易踩更多坑。如果你只是想换一个版本,或者彻底清掉环境,执行以下步骤:
sudo systemctl stop docker sudo apt-get purge docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin用yum的话,把apt-get purge换成yum remove。但清理并不止于此。卸载包不会删除镜像、容器、卷和网络数据,它们全在/var/lib/docker下面。要彻底清掉,手动删除:
sudo rm -rf /var/lib/docker sudo rm -rf /var/lib/containerd这两个目录删了就找不回来了,执行前确认里面没有你需要的镜像或数据卷。
另外,之前手动添加的源文件和GPG密钥也会留下,需要一并清理。Ubuntu/Debian下是/etc/apt/sources.list.d/docker.list和/etc/apt/keyrings/docker.gpg,CentOS里是/etc/yum.repos.d/docker-ce.repo。不删的话,下次重装时可能因为源重复导致更新报错。
5.2 升级Docker版本,最稳妥的方式是跟随源升级
Docker的升级其实不复杂,因为安装源里就有最新稳定版。你只需要执行对应的更新命令:
sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin这样会把Docker相关组件升级到源里的最新版本。CentOS系对应:
sudo yum update docker-ce docker-ce-cli containerd.io升级完成后重启Docker服务:
sudo systemctl restart docker有一点要特别提醒:升级有风险,尤其是在生产环境。Docker的存储驱动、容器运行时不排除有兼容性变化,升级之前最好先在一个测试环境跑一遍,并且备份好重要容器的数据卷。另外,不要在业务高峰期做这件事,不怕一万就怕万一。
5.3 日常顺手做的维护,就三条命令的事
很多服务器的Docker环境变成“野山”状态,镜像堆成山、日志撑满盘、网络乱七八糟,都是因为缺少日常清理习惯。其实三条命令就够用:
docker system df docker system prune docker system prune -a --volumesdocker system df展示磁盘占用概况,让你心里有数。docker system prune清理闲置的构建缓存、停止的容器、没有被使用的网络对象。docker system prune -a --volumes连没有容器引用的镜像和未被使用的数据卷一并清掉。
注意:prune -a会删除没有任何容器使用的镜像,如果你某天想回滚到旧镜像或者重新部署时却发现镜像没了,就可能麻烦了。所以这条命令最好只在确定不需要旧镜像时执行,如果要留一手,就只加--volumes,不加-a。
6. 常见安装失败问题和排查方法,实测过的坑都写在下面
6.1 问题速查表
| 现象 | 最可能原因 | 排查方向 |
|---|---|---|
| 添加apt源后update报错,提示缺少公钥 | GPG密钥没有导入或权限不对 | 检查/etc/apt/keyrings/docker.gpg是否存在且可读 |
| Source列表提示codename不匹配 | 系统版本过旧或/etc/os-release读取异常 | 手动确认版本代号,在源地址中写死正确的codename |
| docker命令提示权限不足 | 用户不在docker组,或Socket权限不对 | 执行usermod -aG docker,并重新登录 |
| docker: Cannot connect to the Docker daemon | 服务没启动 | systemctl start docker并查看status日志 |
| 拉取镜像超时 | 镜像加速器没配或配错地址 | 改daemon.json里的registry-mirrors,重启Docker |
| 容器启动后网络不通 | 宿主机防火墙或安全组拦截 | 分别在宿主机和云控制台检查端口放行情况 |
| 挂载宿主机目录报Permission denied | SELinux或权限配置问题 | 临时用setenforce 0验证,再调整对应策略 |
| apt安装时提示依赖冲突 | 系统源里的旧依赖与官方Docker包冲突 | 先彻底删除旧版docker、containerd,再重装 |
6.2 几个典型问题的排查实录
先讲GPG密钥问题。这是我们接触最多的报错,现象是apt-get update后半段报“The following signatures couldn't be verified because the public key is not available”,一行红字特别吓人。原因多半是keyrings目录权限不对,或者密钥下载后usr keyring位置引用不对。处理方法就是按前面第三节的写法,严格走install -m 0755创建目录、chmod a+r设置读取权限、在source list里用signed-by指明绝对路径。这三样一个都不能少,很多人抄命令漏了chmod,Debian系的apt在读取keyring时会因为权限过宽报错。
再说权限问题。有一种情况是docker ps命令能正常执行,但报文里看起来像“permission denied while trying to connect to the docker daemon socket at unix:///var/run/docker.sock”,这个非常典型。八成是当前用户不在docker组。有人会用一个临时方案:chmod 666 /var/run/docker.sock,这样确实能立刻用,但等于把Docker Socket的权限完全打开,任何人都有可能控制宿主机上的容器,风险极高。正确做法就是前面的usermod那套,别图省事。
我遇到过最隐蔽的问题是host网络模式或者桥接网络模式下,容器内访问不到外部网络。查了一圈,最后发现是宿主机上的防火墙把FORWARD链给拦截了。Docker默认的桥接网络依赖内核IP转发,如果系统里 net.ipv4.ip_forward=0,或者防火墙策略阻塞了转发流量,容器就没有外网。遇到这种情况,可以用sysctl查看内核参数,顺手在/etc/sysctl.conf里把ip_forward改成1,然后sysctl -p生效。这也是安装阶段就该检查的一项基本功。
7. 我自己在安装这件事上的三点心得
装Docker这件事,说起来不难,但每个人反复踩的坑就那几个。我个人的习惯是装完以后先在daemon.json里一次性把镜像加速和日志限制配好,再启动服务,而不是装完默认状态先用,等出了故障再回改配置。改daemon.json虽然只需要重启Docker,但重启相当于把当前跑着的容器全部中断一次,在线环境里这就是一次小事故。
第二点是安装Docker之前,一定要把当前系统的源、内核、防火墙这些“底层环境”先确认好。很多人连内核版本都不看就装,最后容器跑不起来又怀疑Docker本身,实际上问题全在系统层。先花三分钟查环境,能省后面三小时。
最后一个小技巧:建议把装完之后初始化系统的过程整理成一个脚本,包括配置daemon.json、加docker组、设置日志限制、拉取测试镜像、验证Compose版本。以后换任何一台机器,执行一遍就能把Docker环境拉起来,效率翻倍。我自己就是这个流程的受益者,新环境从零到可以跑容器,五分钟以内搞定。