Skip to main content

Ubuntu 安装 Docker 完整教程:官方源、Compose 插件与常见报错排查

September 27, 2026
以官方 apt 源为主线讲解 Ubuntu 上安装 Docker Engine 与 Compose v2 插件的完整流程:免 sudo 运行的正确姿势与安全边界、镜像加速、开机自启、日志轮转治理,以及五个高频报错的排查路径。
Ubuntu 安装 Docker 完整教程:官方源、Compose 插件与常见报错排查

更新日期:2026-09-27

在 Ubuntu 上安装 Docker 看起来是一条 apt install docker.io 的事,但那条命令装的是发行版仓库里滞后的版本,缺少 Compose v2 插件,升级节奏也受制于发行版。生产与长期使用场景,官方 apt 源才是正确起点。

本篇覆盖:官方源的完整安装流程、无 sudo 运行 Docker 的正确姿势、Compose v2 插件、镜像加速配置、开机自启与日志治理,以及 Cannot connect to the Docker daemon、permission denied 等高频报错的排查。适用于 Ubuntu 20.04 / 22.04 / 24.04。

一、先卸载旧版本,避免冲突

Ubuntu 仓库自带的旧版包名(docker.io、docker-engine、containerd 等,以及 deprecated 的 docker-compose v1)会与官方源冲突,先清掉:

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

保留数据:/var/lib/docker/(镜像、容器、卷)不会被这次卸载删除,放心操作。

二、通过官方 apt 源安装(推荐路径)

1. 安装依赖与导入 GPG 密钥

sudo apt-get update
sudo apt-get install ca-certificates curl gnupg

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

2. 添加官方仓库

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") 会自动代入你的版本代号(jammy、noble 等)。如果系统代号在 Docker 官方支持列表之外(如某些 LTS 的初期),可以用相邻已支持版本代号替代,但要做好兼容评估。

3. 安装 Docker Engine 与 Compose 插件

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

这里一次装齐了引擎、CLI、containerd 运行时、BuildKit 构建插件和 Compose v2 插件——最后这个是官方源安装的核心优势之一:docker compose(v2 语法,无连字符)直接可用,不再需要单独安装 docker-compose。

4. 验证

sudo docker run hello-world
docker compose version

看到 hello-world 的欢迎输出与 Compose 版本号,安装闭环。

三、免 sudo 运行 Docker:正确姿势与安全边界

每次都 sudo docker 很烦。官方方案是把用户加入 docker 组:

sudo usermod -aG docker $USER
newgrp docker    # 或注销重登生效
docker ps        # 验证不再需要 sudo

必须知道的安全边界:docker 组等价于 root 权限。Docker 守护进程以 root 运行,组内用户可以挂载宿主任意文件系统到容器内读写(-v /:/host),等价于交出 root。因此:只把可信用户加入 docker 组;多人共用的服务器不要把 docker 组当作"方便"来发放;给不可信用户运行容器的能力时应考虑 rootless 模式或独立的 VM 边界。

四、开机自启与服务管理

安装包默认启用 systemd 服务,确认并设置开机自启:

sudo systemctl enable --now docker
sudo systemctl status docker

enable --now 一步完成"设为自启 + 立即启动"。反过来,如果不希望容器随机自启,注意 --restart 策略与 systemd 的 Restart=always 的叠加行为:容器的重启策略由 docker 管理,但守护进程不自启时一切无从谈起。

五、镜像加速配置

从国内网络拉取 Docker Hub 镜像慢或超时时,配置 registry mirror。编辑 /etc/docker/daemon.json:

{
  "registry-mirrors": [
    "https://<你选择的加速器地址>"
  ]
}

保存后重载生效:

sudo systemctl daemon-reload
sudo systemctl restart docker
docker info | grep -A 3 "Registry Mirrors"   # 确认配置加载

加速器地址随服务商政策变动频繁,选择当前可用的国内加速服务即可;阿里云等云厂商为自家 ECS 提供内网加速地址,走内网不限速。另注意:镜像加速只解决"拉取慢",构建过程中的 RUN apt-get 等外网访问需要在 Dockerfile 或构建参数里另行处理(换 apt 源、设代理)。

六、Compose v2 的日常用法

官方源安装后 Compose 以插件形式存在,命令从 docker-compose 变为 docker compose:

docker compose up -d        # 后台启动整个服务栈
docker compose ps           # 查看栈内容器状态
docker compose logs -f web  # 跟随某个服务的日志
docker compose pull && docker compose up -d   # 更新镜像并滚动重建
docker compose down         # 停止并移除(卷默认保留)

从 v1 迁移的注意点:命令从连字符改为空格、version: 顶层字段在较新的 compose 规范中已可省略、env_file 与变量的解析行为个别细节有差异。存量项目迁移成本低,但 CI 脚本里的命令名记得同步改。

七、日志治理:别让 JSON 日志撑爆磁盘

Docker 默认用 json-file 日志驱动且不限制大小,长期运行容器的日志会把磁盘写满。生产环境建议在 /etc/docker/daemon.json 统一配置轮转:

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

重启 docker 生效(仅对新建容器生效,存量容器需重建)。已被打爆的磁盘:du -sh /var/lib/docker/containers/*/ 定位大日志容器,truncate 清理后重建容器让配置生效。

八、高频报错速查

Cannot connect to the Docker daemon at unix:///var/run/docker.sock:守护进程没起来。sudo systemctl status docker 看状态与日志;常见根因是 daemon.json 写了非法 JSON(改完配置文件务必用 python3 -m json.tool 或 jq 校验再重启)。

permission denied while trying to connect to the Docker daemon socket:当前用户不在 docker 组,回第三节;或组变更后没有重新登录会话。

port is already allocated:宿主端口被占用。sudo ss -tlnp | grep <端口> 找到占用进程;也常见于"旧容器还占着端口但 compose down 只清了新栈"的场景,docker ps -a 清理遗留容器。

E: Unable to locate package docker-ce:官方源没加成功。回第二节核对 sources.list.d/docker.list 内容与 apt-get update 输出里是否出现 download.docker.com。

拉取镜像超时/tls handshake timeout:网络问题,配置第五节的镜像加速;公司网络考虑代理配置(systemd 的 drop-in 给 docker.service 注入 HTTPS_PROXY 环境变量)。

九、装完之后的三件事

  1. 配置日志轮转(第七节),这是新装机器最容易遗漏、半年后最疼的一步;
  2. 跑一次真实 workload 验证:docker compose up 一个带卷映射和端口映射的服务栈,确认数据卷持久化与端口访问都符合预期;
  3. 决定更新策略:Docker 引擎跟随官方源 apt upgrade 即可;容器镜像的更新节奏由 Compose 的 pull 与重启策略决定,关键服务建议锁定镜像 tag 而不是用 latest。

阿里云等国内云服务器上的安装与镜像加速的更多细节,可参考站内的 Alibaba Cloud Linux 安装 Docker 一文,思路相通。

十、数据卷与持久化:容器的数据放哪里

容器是易失的,"重建容器数据还在"依赖卷的正确使用。两种主要形态:命名卷(docker volume create appdata 后 -v appdata:/var/lib/data)由 Docker 管理生命周期与存储位置,适合数据库文件等需要持久化但无需直接浏览的数据;绑定挂载(-v /host/path:/container/path)把宿主目录直接映射进容器,适合配置文件与开发时的代码热更新。备份数据库容器的稳妥姿势是 docker run --rm -v 容器卷:/data -v $PWD:/backup alpine tar czf /backup/appdata.tgz /data 这类一次性容器方案,不进容器内部操作。Compose 栈里卷的声明与引用集中在 services.volumes 与顶层 volumes 两处,down 不删卷、down -v 才删——后者是"数据没了"事故的经典来源,敲之前默念三遍。

十一、最小 Dockerfile 与构建实践

FROM node:22-bookworm-slim
WORKDIR /app

# 先拷依赖清单再装依赖——利用层缓存,代码变更不触发重装
COPY package.json pnpm-lock.yaml ./
RUN corepack enable && pnpm install --frozen-lockfile

# 再拷源码
COPY . .
RUN pnpm build

CMD ["node", "dist/main.js"]

这段骨架的重点是层的顺序:Docker 按层缓存构建结果,依赖清单变化才重装依赖,日常改代码只重建最后的源码层,构建时间从分钟级回到秒级。配套习惯:写 .dockerignore 排除 node_modules、.git 与构建产物——上下文越小,构建越快,意外泄露越少。

十二、引擎升级与版本策略

官方 apt 源的好处在这里兑现:升级只需 sudo apt-get update && sudo apt-get install --only-upgrade docker-ce docker-ce-cli containerd.io。升级前两个动作:确认关键容器有重启策略(升级引擎必然重启守护进程,容器随之重启);记下当前版本(docker version)以便回退。生产主机不必追最新版,跟随官方稳定版的节奏、错峰在业务低峰窗口升级即可。Ubuntu 自带仓库的 docker.io 并非不能用,只是版本滞后且不含 Compose v2 插件,新机器直接走官方源少一次未来迁移。

十三、云服务器上的额外注意事项

在阿里云、腾讯云等云服务器上部署,三个本地没有的变量:镜像加速走内网——云厂商提供的加速地址在 ECS 内网访问不限速,配置时优先选同区域内网端点;磁盘配额——镜像与容器日志共用系统盘,小规格机器记得给 /var/lib/docker 留足空间或把数据盘挂过来(daemon.json 的 data-root 可改存储位置,改动需迁移存量数据);安全组——容器映射的端口要在云安全组放行才可达,"容器跑通了外网访问不了"的第一排查点就是安全组而不是 Docker。国内云上拉取 Docker Hub 的完整流程与加速器配置细节,可结合站内的 Alibaba Cloud Linux 安装 Docker 一文阅读。

十四、常用命令速查表

# 安装与自启
sudo apt-get install docker-ce docker-ce-cli containerd.io \
  docker-buildx-plugin docker-compose-plugin
sudo systemctl enable --now docker

# 日常操作
docker ps                                   # 运行中容器
docker ps -a                                # 含已退出容器
docker images                               # 本地镜像
docker logs -f --tail 100 <容器>             # 跟日志
docker exec -it <容器> bash                  # 进容器
docker system df                            # 磁盘占用总览
docker system prune -a                      # 清理无用镜像与缓存(慎用 -a)

# Compose v2
docker compose up -d                        # 启动服务栈
docker compose ps / logs -f <服务>           # 状态与日志
docker compose pull && docker compose up -d # 更新镜像
docker compose down                         # 停止并移除(保留卷)

多阶段构建要不要用? 要。构建阶段依赖的编译链、devDependencies 不应出现在最终镜像里:FROM builder AS build 完成构建后,FROM runtime 只 COPY 产物——镜像体积常见降幅超过一半,攻击面同步收窄。上面第十节的骨架是单阶段,生产镜像建议改造成 builder + runtime 两段。

网络模式 host 和 bridge 怎么选? 默认 bridge 配合 -p 映射满足绝大多数场景;host 模式(容器直接用宿主网络栈)省一次转发、性能略好,但失去端口隔离,仅在性能敏感且可信负载下考虑。跨主机通信则属于 overlay 网络与编排层的课题,单机教程不展开——需要跨主机时,你的问题通常已经不是"装 Docker"而是"要不要上编排"了。

十五、容器网络三十秒入门

容器端口映射(-p 8080:80)是最常用也最常被误解的网络配置:它把宿主的 8080 转发到容器的 80,容器之间则不走这条路径。同一 Compose 栈内的容器互相访问用的是服务名(Compose 自动创建内部网络,http://web:3000 这样的地址直接可用),不需要映射端口——"数据库端口要不要 -p 出去"的正确答案通常是"不要",仅栈内访问的容器不暴露宿主端口是最小暴露面原则的直接应用。需要跨栈访问时,把容器接到同一个外部网络(external network)即可。调试连通性顺序:容器内 curl 服务端口 → 栈内服务名解析 → 宿主端口映射 → 安全组,从里往外逐层排除。

十六、更多高频问答

docker.io 和 docker-ce 能共存吗? 不建议,两者是同一软件的不同打包,混装会互相覆盖二进制。新装直接走 docker-ce,旧装先卸干净(第一节)。

镜像怎么导出到离线机器? docker save 镜像名 -o image.tar 导出、docker load -i image.tar 导入,跨网段部署与备份镜像都用这对命令;批量导出用 Compose 栈的镜像清单跑循环。

容器时区不对怎么改? 环境变量 TZ=Asia/Shanghai 加 -v /etc/localtime:/etc/localtime:ro 双保险,多数官方镜像即可正确显示本地时间;改完重建容器生效。

怎么看容器占了多少资源? docker stats 实时查看 CPU/内存/网络,排查"容器把机器拖慢"的第一工具;配合 docker system df 看磁盘侧的镜像、容器、卷、缓存四类占用。

restart 策略怎么选? 常驻服务用 --restart unless-stopped(手动停止的不随守护进程复活),一次性任务不加策略;always 与 unless-stopped 的差异就在"手动停止后重启守护进程是否复活容器"这一处。

多阶段构建要不要用? 要。构建阶段依赖的编译链、devDependencies 不应出现在最终镜像里:FROM builder AS build 完成构建后,FROM runtime 只 COPY 产物——镜像体积常见降幅超过一半,攻击面同步收窄。前面第十一节的骨架是单阶段示例,生产镜像建议改造成 builder + runtime 两段。

网络模式 host 和 bridge 怎么选? 默认 bridge 配合 -p 映射满足绝大多数场景;host 模式(容器直接用宿主网络栈)省一次转发、性能略好,但失去端口隔离,仅在性能敏感且可信负载下考虑。跨主机通信则属于 overlay 网络与编排层的课题,单机教程不展开——需要跨主机时,你的问题通常已经不是"装 Docker"而是"要不要上编排"了。

装 Docker Desktop 行不行? Ubuntu 服务器场景不推荐:Docker Desktop 面向桌面开发体验(自带 GUI、与本地工具深度集成),服务器上它占资源、按许可条款还可能需要付费订阅;原生 Engine + 插件组合才是服务器的正解。桌面 macOS/Windows 用户倒是可以让 Desktop 与本地开发愉快共存——那已经超出本篇的 Ubuntu 范围了。

下一步该学什么? 装好只是起点,建议按需递进:先熟练 Compose 管理多容器应用(第六节),再学 Dockerfile 把自己的应用容器化(第十一节),然后是卷与备份策略(第十节),最后按兴趣进入多主机编排的广阔世界——那是另一个(且大得多的)教程了。

官方资料与继续阅读