Ubuntu安装Docker全流程指南:从环境检查到避坑排查
2026/9/20 19:42:06 网站建设 项目流程

先说实话:在 Ubuntu 上装 Docker,很多人觉得难,其实难的不是敲那几条命令,而是搞不清每一步在干嘛。网上教程一大堆,但要么版本太老,要么直接跳步骤,小白照着敲完一头雾水,报错也不知道去哪查。这篇文章我会把从零到跑起来整个流程拆开讲清楚,包括怎么确认系统环境、为什么用官方仓库而不是apt install docker.io、装完要做什么配置、第一个容器怎么跑,以及我这些年踩过的坑和排查思路。适合刚接触 Linux 和 Docker 的初学者,也适合想把手里 Ubuntu 虚拟机或服务器认真搭成开发环境的小伙伴。文章尽量说人话,每条命令都会解释为什么这么做,这样下次遇到问题你能自己判断。

1. 安装前的准备工作与环境确认

1.1 为什么要先确认系统版本和架构

Docker 官方对 Ubuntu 版本是有适配范围的,支持的是 Ubuntu 的 LTS 长期支持版本,包括 Ubuntu 24.04、22.04、20.04,再早一些的 18.04 也曾经支持过。使用 LTS 版本的好处是 Docker 官方仓库会持续提供安全更新和适配包,非 LTS 版本不是不能用,但仓库里的二进制包不一定能对上号,有时候 apt 会报依赖不满足,折腾起来很费时间。

先看一下自己的系统版本:

lsb_release -a

或者:

cat /etc/os-release

重点看DescriptionCodename两项,Codename 很关键,后面添加 Docker 仓库的时候会自动用到。比如 Ubuntu 22.04 的 Codename 是 jammy,24.04 是 noble,如果仓库地址里的 Codename 和系统对不上,apt update 就会报错。

还要确认系统架构:

dpkg --print-architecture

绝大多数 PC 和服务器输出的是amd64,ARM 开发板或云上的 ARM 实例输出的是arm64,树莓派一般是armhf。这个信息决定了 Docker 仓库源要选哪个架构目录,也决定了你拉取的镜像是否能在本机运行。

1.2 清理旧版本 Docker

如果这台机器之前装过 Docker,或者系统里预装了docker.iodocker-engine这类包,建议先卸载干净。这里有个容易混淆的点:docker.io是 Ubuntu 软件源里自带的 Docker 老版本,和 Docker 官方源里的docker-ce不是同一个包,两者混着装很容易冲突。

清理命令:

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

这个命令只删除软件包本身,不会动/var/lib/docker目录,也就是说你之前拉取的镜像、创建的容器、数据卷都还在。如果确认这台机器不需要保留旧数据,可以顺手清掉:

sudo rm -rf /var/lib/docker

我个人建议新机器别着急删,先确认真的不需要旧数据再动手。毕竟镜像和容器数据有时候很重要,删了就真没了。

1.3 更新软件包索引并安装基础依赖

在添加 Docker 仓库之前,先让系统的软件包索引保持最新:

sudo apt update

然后安装几个基础工具:

sudo apt install -y apt-transport-https ca-certificates curl gnupg lsb-release

这几个包各有用途:apt-transport-https让 apt 支持通过 HTTPS 协议访问软件源;ca-certificates提供 CA 证书,用来验证仓库地址的合法性;curl用来下载 GPG 密钥文件;gnupg用来导入和管理密钥;lsb-release用来获取 Linux 发行版的具体版本信息。缺了其中任何一个,后面添加 Docker 官方源的时候都可能出问题。

2. 安装 Docker 的三种主流方式(含推荐方案)

2.1 方式一:官方 apt 仓库安装(推荐)

我最推荐的方式,也是 Docker 官方文档一直在用的方式,就是把 Docker 官方的 apt 仓库加到系统里,然后通过正常的 apt 流程安装。这样做的好处有三个:可以用sudo apt upgrade统一升级 Docker,不需要手动管理二进制文件;依赖关系由 apt 自动处理;安装、卸载、回滚都比较规范,适合长期使用。

第一步是添加 Docker 官方的 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

简单解释一下这几条命令在干嘛。install -m 0755 -d是创建目录同时把权限设置成 755,专门用来放密钥文件。curl下载的 GPG 密钥文件是 ASCII 格式,apt 不认这种格式,所以要用gpg --dearmor把它转换成二进制格式再保存。chmod a+r是让所有用户都能读取这个密钥,否则 apt 在更新索引时会因为没权限读密钥而报错。

第二步是添加 Docker apt 仓库:

echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

这条命令看起来复杂,其实核心就是把一行仓库地址写进/etc/apt/sources.list.d/docker.list文件。关键点是arch=$(dpkg --print-architecture)会自动代入系统架构,$(lsb_release -cs)会自动代入系统 Codename,比如 Ubuntu 22.04 会是 jammy。这样手动写错架构或版本代号的概率就大大降低了。

第三步是更新索引并安装:

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

注意这里的包名,现在 Docker 官方把组件拆得很细:docker-ce是 Docker 服务端,docker-ce-cli是命令行工具,containerd.io是底层的容器运行时,docker-buildx-plugin是高级构建插件,docker-compose-plugin是编排工具。建议一次性都装上,以后用得到。

2.2 方式二:便捷脚本安装

如果你想快速搭一个实验环境,不想一步步敲上面的命令,Docker 官方提供了一个自动化脚本:

curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh

这个脚本会把官方仓库配置、密钥导入、软件安装全部自动化完成,还会帮你设置好 systemd 服务并开启开机自启。优点是省事,特别适合临时测试或学习环境。

但我不建议生产环境用这个方式,原因是脚本永远是安装当前最新版本,你无法指定版本号,万一新版本有兼容性问题,回滚会比较麻烦。另外脚本内部做的事情太多,出了问题不好定位,你不知道它到底配置了哪些文件。

一个小习惯:任何从网上下载下来要执行的脚本,我都建议先看一遍内容再执行。上面第一步只下载不执行,所以你可以先less get-docker.sh大概扫一眼,确认没有异常再运行。

2.3 方式三:直接下载 deb 包离线安装

有些内网服务器无法访问外部软件源,或者你对版本有严格要求,这种情况可以手动下载 deb 包安装。Docker 官方仓库的 deb 包在https://download.docker.com/linux/ubuntu/dists/下面,先找到对应的 Codename 目录,然后进pool/stable/选择架构目录,把需要的包下载到本地。

手动下载安装命令:

sudo dpkg -i ./docker-ce_*.deb sudo dpkg -i ./docker-ce-cli_*.deb sudo dpkg -i ./containerd.io_*.deb

如果装的过程中提示依赖缺失,跑一句:

sudo apt-get install -f

apt 会自动补装缺失的依赖。离线安装最烦的就是依赖链,所以有条件还是优先用仓库方式。

2.4 三种安装方式如何选

安装方式优点缺点适合场景
官方 apt 仓库升级方便、依赖自动处理步骤较多绝大多数个人和服务器
便捷脚本一键完成、速度快无法指定版本、过程不透明学习测试、临时环境
离线 deb 包可指定版本、无需公网访问依赖需要手动处理内网环境、版本强约束生产环境

我自己的习惯是:笔记本和虚拟机用官方 apt 仓库,图省事图稳定;公司内网服务器用离线 deb 包,因为安全策略不允许随便连外网;临时开一台测试机,那就直接跑脚本,快是真的快。

3. 安装后的必要配置与验证

3.1 启动 Docker 服务并设置开机自启

安装完成不等于 Docker 正在运行,需要手动启动服务并设置为开机自启:

sudo systemctl enable docker sudo systemctl start docker sudo systemctl status docker

enable是把 Docker 服务加入开机启动项,这样重启机器后 Docker 会自动起来。start是立即启动服务。status是查看当前运行状态,看到active (running)才是正常的。

如果status显示失败,别慌,先看日志:

journalctl -u docker.service -n 50

-n 50表示只看最后 50 行日志。大多数情况下,启动失败是因为配置文件写错了,尤其是/etc/docker/daemon.json,格式稍有不对整个服务就起不来。

3.2 验证 Docker 是否安装成功

先看版本号:

docker --version

能输出类似Docker version 27.3.1的内容,说明命令行工具已经正常工作。

再验证整个链路是否通畅:

sudo docker run hello-world

这条命令会先从 Docker Hub 拉取一个极小的hello-world镜像,然后在容器里执行。看到类似Hello from Docker!的输出,说明 Docker 客户端、服务端、镜像拉取、容器创建整条链路都通了。

3.3 免 sudo 运行 Docker 的用户组配置

默认情况下,执行docker命令需要 sudo,否则会报这样的错:

docker: permission denied while trying to connect to the Docker daemon socket

原因是 Docker 的守护进程套接字/var/run/docker.sock属主是root:docker,当前用户不在 docker 组里。解决办法是把自己加进 docker 用户组:

sudo usermod -aG docker $USER newgrp docker

usermod -aG是把用户追加到 docker 组,newgrp docker是让当前终端立即生效,不用重新登录。之后直接docker ps就能用了。

这里必须提醒一句:加入 docker 组的用户实际上拥有 root 级别的权限,因为 Docker 可以挂载宿主机目录、修改网络配置,本质上等同于 root。所以生产服务器上不要把不信任的账号加进 docker 组。

3.4 配置镜像加速器

国内网络环境下,直接从 Docker Hub 拉取镜像经常很慢,甚至超时。常规解决办法是配置镜像加速器,也就是用云厂商提供的 registry mirror。

先创建或编辑/etc/docker/daemon.json

{ "registry-mirrors": ["https://your-mirror-service.example.com"] }

注意这是个 JSON 文件,格式必须严格正确,多一个逗号都会导致 Docker 服务启动失败。写完后重载配置并重启:

sudo systemctl daemon-reload sudo systemctl restart docker

重启后用docker info查看Registry Mirrors那一栏,确认配置生效。加速服务各个地区效果不一样,最好实测一下拉取速度再确定用哪个。另外要说明一点,镜像加速只是针对 Docker Hub 官方镜像的常规访问加速,不同服务商的稳定性和速度差异很大,建议选择口碑好、有备案的云服务厂商提供的加速地址。

4. 第一个容器:从入门到跑起来

4.1 hello-world 验证

hello-world是 Docker 官方提供的最小测试镜像,它只做一件事:容器启动后输出一段说明文字然后退出。虽然简单,但它验证了整个链路:

  • 客户端能连接到 Docker 守护进程
  • 守护进程能从远程仓库拉取镜像
  • 容器镜像能正常解压和启动

如果这条命令报错,大概率是网络原因拉不到镜像,回到 3.4 配置加速器后再试。

4.2 运行一个 Nginx 容器并理解端口映射

hello-world跑完就退出了,看不出容器的实际使用价值,所以我们来跑一个真正提供服务的容器。Nginx 是首选,镜像小、依赖少、效果直观:

docker run -d --name my-nginx -p 8080:80 nginx

参数逐个解释:-d表示后台运行;--name my-nginx给容器起个名字,方便后续管理;-p 8080:80是端口映射,把宿主机的 8080 端口映射到容器内的 80 端口;nginx是镜像名。

运行完以后,浏览器访问http://localhost:8080,如果看到 Nginx 的欢迎页,说明这个容器已经在正常工作了。

端口映射是 Docker 最核心也最容易搞混的概念。容器里的 Nginx 默认监听 80 端口,但这个 80 端口是容器内部的网络命名空间,和宿主机是隔离的。没有-p参数,宿主机根本访问不到容器内的服务。-p 8080:80就是把容器内的 80 翻译成宿主机的 8080,外面的人访问宿主机的 8080,数据就被转发到容器的 80。

4.3 常用容器操作命令速记

跑起来只是第一步,日常运维还需要掌握下面这些命令的场景:

docker ps # 查看运行中的容器 docker ps -a # 查看所有容器,包括已停止的 docker logs -f my-nginx # 实时查看容器日志 docker exec -it my-nginx bash # 进入容器终端 docker stop my-nginx # 停止容器 docker start my-nginx # 启动已停止的容器 docker rm my-nginx # 删除容器,需先停止 docker images # 查看本地镜像列表 docker rmi nginx # 删除本地镜像 docker system df # 查看 Docker 磁盘占用

ps查看容器状态,logs排查应用问题,exec进容器内看进程和文件。这几个命令频率最高,先记住它们,后面再慢慢拓展。

5. 常见问题与排查技巧实录

5.1 安装时出现 Unable to locate package docker-ce

这是新手最常见的报错,原因是 apt 源里根本没有docker-ce这个包。可能的情况有两种:

第一种是你没执行sudo apt update,新加的 Docker 仓库还没被索引。解决办法是先更新索引再安装。

第二种是你之前添加仓库那一步出了问题,比如 Codename 不匹配。检查一下仓库文件内容:

cat /etc/apt/sources.list.d/docker.list

看看里面的$(lsb_release -cs)最终被替换成了什么。如果系统不是 LTS 版本,或者/etc/os-release里的 Codename 和 Docker 官方仓库目录对不上,就会出现这个错误。

还有一种情况是源里只有stable但系统架构不匹配,比如在 ARM 机器上用了amd64的仓库。检查一下dpkg --print-architecture的输出,确认架构和仓库地址对应。

5.2 启动 Docker 报错 Cannot connect to the Docker daemon

这个报错说明命令行工具连不上 Docker 守护进程。先区分两种情况:守护进程没运行,或者守护进程运行了但套接字访问不了。

先用systemctl status docker看服务状态。如果服务根本没起来,看日志:

journalctl -u docker.service -n 50

日志里最常见的启动失败原因是/etc/docker/daemon.json格式不对。我曾经见过有人把 registry-mirrors 后面的逗号写错,导致整个 JSON 解析失败,Docker 服务直接起不来。可以用docker daemon --validate验证配置文件,或者用python3 -m json.tool /etc/docker/daemon.json检查 JSON 格式。

如果服务正常但命令还是连不上,检查环境变量:

echo $DOCKER_HOST

有些教程会让你设置DOCKER_HOST,但如果你用的是本地安装的 Docker,这个变量不应该被设置,设置了反而会让客户端去找一个不存在的远程地址。

5.3 运行 docker 命令出现 permission denied

这个问题的原因很清楚:当前用户不在 docker 组。解决方式前面已经讲过了,sudo usermod -aG docker $USER然后重新登录。

需要注意两个细节。第一,newgrp docker只对当前终端有效,新开的终端自然生效,但如果你的 SSH 会话是旧的,可能需要断开重连。第二,不要因为嫌麻烦就一直用sudo docker,这样所有 Docker 相关文件都会以 root 身份创建,后续清理起来权限纠缠会很痛苦。

5.4 拉取镜像慢或超时

镜像拉取慢主要有两个原因:网络链路问题和 DNS 解析问题。首选方案是配置镜像加速器,这是目前最直接有效的办法。配置方法在 3.4。

如果已经配了加速还是慢,试试修改 DNS:

sudo vim /etc/resolv.conf

把 nameserver 换成公共 DNS,比如223.5.5.5。改完记得保存,然后重新拉一次镜像。

另外一个容易被忽略的点是,有些网络环境下 IPv6 会导致 Docker 连接超时。可以试试强制走 IPv4,在/etc/docker/daemon.json里加:

{ "ipv6": false }

然后重启 Docker。这个方法不是万能的,但确实在一些双栈网络下有效。

5.5 磁盘空间不足与数据目录迁移

Docker 默认把所有数据放在/var/lib/docker,包括镜像、容器、数据卷。如果根分区不够大,跑一段时间就会发现df -h/已经 100% 了。

先看磁盘占用情况:

docker system df

这个命令会列出镜像、容器、数据卷分别占了多少空间。如果只是悬空资源多,执行:

docker system prune -a

可以清理掉所有未被容器使用的镜像和缓存。

如果清理完还是不够,就得考虑把整个 Docker 数据目录迁移到更大的分区:修改/etc/docker/daemon.json

{ "data-root": "/data/docker" }

重启 Docker,确认服务正常。注意迁移前要停掉所有容器和 Docker 服务,然后把原目录完整拷贝过去,避免丢数据:

sudo systemctl stop docker sudo rsync -av /var/lib/docker/ /data/docker/ sudo systemctl start docker

5.6 排查技巧速查表

故障现象排查命令常见解决办法
docker 命令提示无权限id查看所属组usermod -aG docker $USER
服务启动失败journalctl -u docker.service检查 daemon.json 格式
客户端连不上服务端systemctl status docker确认服务运行、检查 DOCKER_HOST
拉取镜像超时docker info查看 mirror配置镜像加速器、改 DNS
容器端口不通docker ps查看映射检查-p参数、确认容器内服务监听
根分区被占满docker system dfprune -a清理、迁移>

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

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

立即咨询