
如果你手头有一台阿里云ECS系统是Ubuntu想装Docker却卡在下载源上那这篇大概率是你需要的。我在阿里云服务器和本地Ubuntu虚拟机里前前后后装过不下十次Docker踩过的坑几乎都集中在“源”上Ubuntu默认的软件源在境外docker-ce官方仓库也在境外直接跑apt update和apt install docker-ce速度往往只有几KB/s甚至直接连接超时。后来我把系统源和Docker仓库源都切到阿里云镜像站整个过程就变成了几分钟的事。这篇文章会把从换源、装Docker Engine到配置镜像拉取策略、解决几个常见报错的完整链路写下来适合从零部署阿里云ECS环境的运维新手也适合本地Ubuntu想通过国内镜像提速的开发者。1. 先搞清楚三个“源”apt源、docker-ce源、镜像加速器很多人以为装Docker就是照着官网复制三行命令实际落到国内环境下问题基本都出在“源”上。这里的“源”分三层每一层负责不同的下载任务源类型默认地址阿里云镜像地址负责内容apt系统源archive.ubuntu.commirrors.aliyun.com/ubuntuUbuntu系统软件包docker-ce源download.docker.commirrors.aliyun.com/docker-ceDocker引擎本体镜像加速器registry-1.docker.io阿里云容器镜像服务ACR容器镜像如nginx、mysql拉取打个比方apt源是手机应用商店的下载渠道决定你装“微信”快不快docker-ce源是Docker这个安装包本身的渠道决定你装“微信安装程序”快不快镜像加速器则更像是安装完成之后下载微信内的小程序内容用的CDN。三层互不替代每一层慢或不通观感都是“装不上”或“拉不动”。第一个容易忽略的点如果你用的是阿里云ECS而且这台ECS没有做特殊出网配置那么阿里云内部其实给了一套内网镜像域名——mirrors.cloud.aliyuncs.com。走内网镜像有几个实打实的好处速度更稳定不走公网出口而且不占公网流量带宽计费。本地物理机或非阿里云的云主机用不了这个地址只能走公共镜像站mirrors.aliyun.com。另一个容易忽略的点docker-ce源解决的是“安装Docker这个程序”的问题镜像加速器解决的是“安装好Docker之后里面拉nginx/mysql镜像”的问题。很多教程混着说导致用户跟着配完源发现docker pull还是慢就很困惑。这篇文章后面会把两条链路都讲到。1.1 Docker Engine 和 Docker Desktop 的区别如果你的Ubuntu是服务器版无图形界面装Docker Engine就行这是生产环境的标准选择。如果用的是Ubuntu桌面版且习惯有图形界面操作Docker可能会考虑Docker Desktop但桌面版经常碰到“Virtualization support not detected”一类的虚拟化检测问题对应着很多人在网上搜的关键词。我的建议很直接服务器、云主机一律装Docker Engine只有你在本机开发、且特别依赖图形管理面板时才去考虑Docker Desktop。本文主要讲服务器场景。2. 动手前的系统准备版本、旧版残留、基础依赖装Docker之前我习惯先把系统环境摸一遍。不是浪费时间很多安装失败都是环境问题而不是Docker本身的问题。2.1 确认Ubuntu版本和架构先看一下系统版本号不同版本对应的源仓库代号不一样lsb_release -a cat /etc/os-release我用的阿里云ECS大多是20.04focal、22.04jammy最近也有不少24.04noble的新机器。lsb_release -cs的结果就是源仓库里的版本代号后续配置docker-ce源时要用到。顺手确认一下CPU架构尤其注意阿里云上那些ARM实例dpkg --print-architecturex86机器输出amd64ARM机器输出arm64。如果你用的是阿里云倚天实例这里是arm64配置仓库时让系统自己识别架构不要写死amd64。2.2 清理旧版本Docker残余新机器一般没这个问题但如果之前手动装过docker.io、docker-engine或者系统里残留了旧版本先清干净再装dpkg -l | grep -i docker sudo apt remove docker docker-engine docker.io containerd runc -y这里有个提醒/var/lib/docker目录下保存的是历史镜像、容器和数据卷。如果你只是重装Docker引擎清理命令不会动这个目录但如果要完全清干净需要手动删除整个目录。生产机器上务必先确认里面有没有重要数据再决定删不删。2.3 安装基础依赖接下来把基础依赖装好。这一步可能有人觉得多余但恰恰是很多“装到一半报错”的隐患来源sudo apt update sudo apt install -y ca-certificates curl gnupg lsb-releaseca-certificates保证后面下载GPG密钥时SSL证书校验正常curl用来拉取密钥文件gnupg负责处理GPG校验lsb-release提供版本代号查询命令。Ubuntu 20.04默认都会带但显式装一遍没有副作用。3. 把系统apt源切到阿里云这一步别省很多教程会直接让你跳过系统源配置只加docker源。我不建议这样。装Docker时系统需要依赖一系列基础软件包这些包走的都是系统apt源。如果apt源本身就慢你加再多的docker源安装时照样卡在依赖下载上。3.1 备份现有源文件先备份养成习惯sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak如果你的系统是22.04及以上源配置可能在/etc/apt/sources.list.d/ubuntu.sources文件里。Ubuntu 22.04之后默认改成deb822格式路径不再只有sources.list一个。确认方式很简单ls -l /etc/apt/sources.list.d/3.2 替换为阿里云镜像地址20.04及更早版本直接修改/etc/apt/sources.listsudo sed -i shttp://archive.ubuntu.com/ubuntuhttps://mirrors.aliyun.com/ubuntug; shttp://security.ubuntu.com/ubuntuhttps://mirrors.aliyun.com/ubuntug /etc/apt/sources.list22.04及更新版本改/etc/apt/sources.list.d/ubuntu.sourcessudo sed -i shttp://archive.ubuntu.com/ubuntuhttps://mirrors.aliyun.com/ubuntug; shttp://security.ubuntu.com/ubuntuhttps://mirrors.aliyun.com/ubuntug /etc/apt/sources.list.d/ubuntu.sources如果你用的是阿里云ECS把上面的mirrors.aliyun.com替换成内网地址mirrors.cloud.aliyuncs.com这样走的是阿里云内网链路。验证内网地址是否通curl -I https://mirrors.cloud.aliyuncs.com更换后更新索引sudo apt update正常会看到像Get:1 http://mirrors.aliyun.com/ubuntu jammy InRelease这样的输出说明源已经生效。如果你看到的还是archive.ubuntu.com检查一下是不是还有/etc/apt/sources.list.d/下的其他源文件覆盖了配置。4. 添加阿里云docker-ce仓库安装Docker Engine系统源就绪后开始进入正题配置docker-ce源并安装Docker引擎。4.1 下载并安装Docker官方GPG密钥Docker仓库需要GPG密钥校验只有密钥匹配apt才会信任来自这个仓库的软件包。用阿里云镜像站上的密钥文件sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg sudo chmod ar /etc/apt/keyrings/docker.gpg这里用了--dearmor将ASCII格式的密钥转成二进制GPG文件现代apt推荐这种做法而不是老的apt-key add。chmod ar让系统其他用户也能读到密钥避免权限问题。4.2 写入docker-ce源配置接着把阿里云的docker-ce仓库写入apt源列表echo deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable | sudo tee /etc/apt/sources.list.d/docker.list解释一下这行配置arch$(dpkg --print-architecture)让系统自己选择架构signed-by指向刚才下载的GPG密钥文件$(lsb_release -cs)输出当前系统的版本代号比如20.04就是focal末尾的stable表示使用稳定版通道如果你想测试预发布版可以换成test生产环境没必要。4.3 刷新索引并查看可用版本sudo apt update如果配置正确输出里会出现Get:... https://mirrors.aliyun.com/docker-ce/linux/ubuntu jammy stable InRelease。这时可以查看有哪些可用版本apt-cache madison docker-ce这条命令列出的就是当前仓库里docker-ce的可用版本列表。我一般建议直接装最新稳定版除非你的业务对版本有明确要求。4.4 安装Docker引擎及相关组件sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin这里多装了几样docker-ce-cli是命令行客户端containerd.io是容器运行时docker-buildx-plugin是BuildKit构建插件docker-compose-plugin是新版Docker自带的Compose插件后面编排多容器应用会用到。如果需要指定版本可以在包名后用接版本号sudo apt install -y docker-ce5:26.1.4-1~ubuntu.22.04~jammy docker-ce-cli5:26.1.4-1~ubuntu.22.04~jammy containerd.io4.5 启动并验证安装完成后Docker服务默认会被创建但不一定启动了。手动启动并设置开机自启sudo systemctl enable --now docker sudo systemctl status docker --no-pager看到Active: active (running)说明服务正常。再验证一下版本docker version docker compose versiondocker version会输出Client和Server两块内容如果Server信息为空说明daemon没起来直接journalctl -u docker.service看日志。5. 镜像加速器的真实情况与离线救急方案Docker引擎装好了但很多人会倒在下一步docker pull hello-world拉了半天不动。这正是镜像加速器要解决的问题。不过说到这块我需要先泼一盆冷水。5.1 个人加速器地址不要随便抄早年网上教程里有很多“阿里云镜像加速器地址”形如xxxx.mirror.aliyuncs.com需要在阿里云容器镜像服务控制台里申请。但这类个人加速服务这几年调整很频繁很多地址已经不再对个人开发者提供服务。你要是从一篇旧教程里抄了个地址填进daemon.json大概率会遇到EOF、connection refused甚至一直卡在未授权状态。我的做法是不盲抄加速地址先直接测一下能不能连通Docker Hubdocker pull hello-world如果几秒内能拉下来说明网络环境不错不配加速器也没什么问题。如果明显卡住再考虑下面的方案。5.2 daemon.json的正确配置方式不管配不配加速器/etc/docker/daemon.json这个文件都是Docker守护进程的核心配置建议花半分钟把日志策略顺带设好sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json EOF { log-driver: json-file, log-opts: { max-size: 10m, max-file: 3 } } EOF sudo systemctl daemon-reload sudo systemctl restart docker这里设置了单个容器日志文件最大10MB、最多保留3个文件。别小看这个配置不限制日志的话一个高频日志的容器几天就能吃完你的磁盘到时候Docker可能直接拒绝启动。如果你单位或团队自己有企业版镜像仓库、或者开通了可用的公共镜像服务按服务商提供的方式把地址填进registry-mirrors数组即可。填完之后docker info在输出里找Registry Mirrors那一栏能看到当前配置的加速地址是否生效。5.3 离线镜像导入最笨但最稳的方法如果你所在的网络环境拉Docker Hub镜像确实很费力我强烈建议掌握离线导入这套流程找一台网络正常的机器把镜像打包成tar文件再拷贝到目标服务器导入。这是绕过网络问题的稳妥办法尤其适合内网环境的ECS。在能拉镜像的机器上执行docker pull nginx:alpine docker save -o nginx-alpine.tar nginx:alpine把tar包传到目标机器然后执行docker load -i nginx-alpine.tar docker imagessave和load是配对使用的中间可以随便传输文件U盘、内网scp都行。这个方法在处理docker pull超时时有奇效特别适合离线内网部署。缺点是不能像pull那样按层增量下载但总体稳定性高得多。6. 装完Docker之后我每次必做的四项配置Docker命令能跑了不等于环境已经顺手。以下四项配置我建议每台机器都做完能省掉后面大量权限和启动问题。6.1 让当前用户免sudo操作DockerDocker守护进程默认以root运行普通用户执行docker命令需要加sudo。每次加sudo会很烦而且新版Docker的Compose插件在sudo环境下还可能因为权限不一致报错。正确做法是把当前用户加入docker用户组sudo usermod -aG docker $USER执行后退出重新登录或者newgrp docker让用户组生效。验证方式id $USER看到类似uid1000(ubuntu) gid1001(ubuntu) groups1001(ubuntu),999(docker)的输出就OK了。这里有个安全提醒加入docker组的用户基本等同于拥有root能力因为docker支持挂载宿主机目录所以只在信任的账户上做这一步。6.2 确认开机自启第4节安装时用了systemctl enable --now docker这一步已经把自启配置好了。但有些云主机镜像做了systemd服务裁剪还是再确认一下systemctl is-enabled docker输出enabled就放心了。如果输出disabled执行sudo systemctl enable docker6.3 跑一遍hello-world配置好加速方案或离线导入后跑一次标准验证docker run --rm hello-world--rm让容器退出后自动删除不留垃圾。如果输出能看到Hello from Docker!说明docker pull、容器创建、运行整套链路都正常。6.4 把docker compose插件确认好安装时我特意装上了docker-compose-plugin这是Docker官方推荐的Compose v2实现。验证docker compose version看到Docker Compose version v2.x.x就OK。很多人在网上搜“docker青龙 依赖管理”或“docker安装mysql8.0并使用”这类玩法依赖的核心工具就是docker compose。用docker compose up -d来启动MySQL、Redis这类多容器应用比手工docker run加一堆参数靠谱得多。7. 真实踩坑链路从装不上到pull不动的排错记录最后分享几条我自己在阿里云Ubuntu环境上真实踩过的坑不是网上复制来的是按实际排查顺序写的。7.1 GPG签名错误The following signatures couldnt be verified典型现象apt update时看到类似The following signatures couldnt be verified because the public key is not available。原因一般是密钥文件没下载成功或者密钥文件权限不对。排查链路ls -l /etc/apt/keyrings/docker.gpg sudo curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg sudo chmod ar /etc/apt/keyrings/docker.gpg sudo apt update重新下载密钥再更新九成能解决。还有一种情况是阿里云源返回了旧密钥缓存把密钥文件删掉重新拉一次就好。7.2 找不到docker-ce包Package docker-ce has no installation candidate这个报错出现频率极高原因基本是docker仓库没有真正生效。按这个顺序查第一步确认docker.list文件存在且内容正确cat /etc/apt/sources.list.d/docker.list第二步确认apt update时有没有拉取docker仓库sudo apt update | grep docker如果什么也没输出说明仓库配置里的版本代号有问题。最常见的是系统上一秒还没安装lsb-releaselsb_release -cs返回了未知字符串导致仓库地址指向了一个不存在的目录。照第2节补装依赖重新生成源行即可。7.3 证书验证失败Certificate verification failed报错通常在apt update或curl镜像源时出现格式类似Err:1 https://mirrors.aliyun.com/ubuntu ... certificate verify failed。多数情况不是源的问题是系统时间不对导致SSL证书校验过期。阿里云ECS默认是UTC时间的问题少见但有些自定义镜像会把硬件时钟搞乱。处理方式sudo apt install -y ntpdate sudo ntpdate ntp.aliyun.com sudo timedatectl set-timezone Asia/Shanghai timedatectl校准时间和时区后重新apt update证书报错基本消失。这个坑容易被忽略因为它表面看起来完全是网络问题。7.4 docker pull超时或解析失败dial tcp: lookup registry-1.docker.iodocker pull阶段最常见的错误是连接Docker Hub超时有时表现为http: server gave HTTP response to HTTPS client或Temporary failure in name resolution。前者通常是镜像源地址配错或该地址不支持HTTPS后者多半是DNS性能差系统里/etc/resolv.conf指向的DNS服务器响应慢。临时排查手法cat /etc/resolv.conf ping -c 3 registry-1.docker.io docker pull hello-world如果是DNS问题先试试公共DNS这里仅作为排查手段描述不涉及任何不安全内容再回到daemon.json里确认是否有加速器配置有则暂时移除后重试。如果Docker Hub连通性确实不好直接走第5节的离线导入方案别和它死磕。7.5 容器内时区不对导致日志时间差8小时装完Docker跑起第一个容器后很多人会发现容器内date显示的是UTC时间比北京时间慢8小时。这个不是安装问题而是容器镜像默认时区就是UTC。解决办法很简单在运行容器时加环境变量docker run -e TZAsia/Shanghai nginx用Compose配置的话在服务下加environment: - TZAsia/Shanghai很多人在网上搜“ubuntu中文输入法怎么设置”时碰到的时区混乱和容器时间差是两回事但养成启动容器就带TZ参数的习惯日志时间会好排查很多。写在最后的体会我自己的感觉是Ubuntu上装Docker这件事百分之八十的功夫在于网络源剩下百分之二十才是系统环境本身的调教。新装的Ubuntu机器我会先把时区、系统源这两件事弄利落再动手装Docker整个流程基本不会再出幺蛾子。还有一个小技巧配置好docker源之后先把docker-ce的可用版本列表打印出来存到本地将来排查环境问题时会好用很多。不要照搬网上随手抄来的加速器地址配置一个已经失效的入口远比不配置更让人头疼。