news 2026/9/18 11:19:11

Ubuntu安装Docker与Docker Compose全攻略:从原理到实战避坑

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Ubuntu安装Docker与Docker Compose全攻略:从原理到实战避坑

最近这阵子好几个朋友都在折腾Ubuntu,要么是给老笔记本装了双系统,要么是在虚拟机上开了一台纯净的服务器版做实验。结果装完系统后第一个动作几乎都一样:跑来问我Docker怎么装。确实,现在很多服务的标准交付方式就是容器,不管是搭个个人博客、跑个MySQL、还是部署一套GitLab,Docker基本绕不开。而Ubuntu又是很多人的首选Linux发行版,所以“Ubuntu上把Docker和Docker Compose装好”这个需求,几乎可以算是现代Linux玩家的入门必修课。

这篇内容我会把自己实际操作中验证过的完整流程、安装方式选型的底层逻辑、以及各种奇奇怪怪的坑都写出来。适合刚接触Linux的人跟着一步步操作,也适合已经装过Docker但被版本问题、镜像拉取慢、Compose用不了等问题卡住的老手直接跳到对应章节抄答案。我的目标很简单:不管你用Ubuntu 20.04、22.04、24.04还是最新的26.04(如果你已经勇敢地用上了),看完之后都能得到一个干净、能用、配置合理的Docker环境。

1. 整体设计与思路拆解

1.1 为什么我建议在Ubuntu上使用原生Docker Engine,而不是Docker Desktop

经常有人问,为什么不在Ubuntu上装Docker Desktop?毕竟Windows和macOS上大家习惯用Docker Desktop,图形界面操作起来很直观。但这里有个关键区别:Docker Desktop在Linux上其实是“套娃”方案,它本质上还依赖底层的Docker Engine,但多加了一层虚拟机管理逻辑(现在新版本虽然可以不用虚拟机了,但仍然和你直接装原生Docker没有本质区别)。更重要的是,生产环境、服务器场景下几乎没人用Docker Desktop,所有人都是直接部署Docker Engine。既然你想认真学Linux下的容器,那就一步到位,直接使用命令行操作的原生Docker Engine。

另外,Ubuntu官方软件源里的docker包很老,甚至在一些版本里压根没有独立的Docker Engine包(之前有个叫docker.io的包是Debian维护的,但版本滞后)、所以最合理的方式是使用Docker官方维护的apt源。这样做的好处是:Docker官方源会即时更新、支持你指定安装特定版本、能够同时安装Compose插件。虽然国内访问Docker官方源偶尔有网络波动,但可以通过配置镜像站点的方式解决,这个我后面会详细说。

1.2 安装方式选型:官方apt源、get.docker.com脚本还是二进制包

Docker Engine在Linux上常见的安装方式就那么几种:

  • 官方apt源安装:最推荐,便于用apt管理、升级,因为到时候你执行apt upgrade就能顺带更新Docker。
  • get.docker.com脚本:官方提供的一键脚本,实际就是给你配置好apt源然后安装,适合不想手动敲太多命令的人,但脚本内部对系统会做很多自动判断,出问题时不太好控制。
  • 二进制包/离线包:适合完全离线的内网环境,需要自己去下载对应架构的二进制压缩包,然后手动配置systemd服务,比较繁琐,不推荐新手。

个人装过几十台机器后的结论是:如果你能联网,老老实实用官方apt源配合软件源里提供的 docker-ce、docker-ce-cli、containerd.io 和 docker-compose-plugin 这四个套件。这套组合几乎覆盖了所有日常需求。这里的docker-compose-plugin至关重要,因为新版Docker Compose已经变成Docker CLI的一个插件,命令是 docker compose(中间有空格),而不是以前独立的 docker-compose 命令。很多人装完发现 docker-compose 不存在,多半就是不清楚这个插件机制。

1.3 版本规划:Docker Engine 与 Docker Compose 版本对应关系

Docker Engine的版本号目前是24.x、25.x、26.x、27.x这样滚动的,而Docker Compose插件是单独发布版本号,两者并不强制绑定。但有个实用经验:同一时间安装的Docker Engine和Compose插件版本最好保持在一定的新旧范围内,避免出现docker compose命令不可用或API版本不匹配的问题。

更准确地说,docker compose(V2插件)依赖Docker Engine的API版本,虽然V2插件会自动协商API版本,但如果你用的是非常老旧的Docker Engine(比如18.09、19.03)、新版的Compose V2可能跑不起来,我在旧机器上就遇到过类似情况。所以我的原则是:尽量使用当前主流的Docker Engine版本,并且通过docker compose version命令查看Compose版本,确保它是2.20.0以上。后面我会给出具体更新到2.23以及指定特定版本的方法。

另外需要提一下,很多网络教程还停留在让你去GitHub下载 docker-compose-linux-x86_64 这个二进制的时代。现在完全没必要这样干了。从Docker 20.10开始,Compose V2已经以插件形式内置发布,你用apt装Docker的时候顺便就能装好。直接从GitHub下载二进制的方式容易踩权限、架构、路径的坑,而且后续升级麻烦。我建议把它当成备用方案来理解,但不要作为首选操作。

2. 核心细节解析与实操要点

2.1 Ubuntu系统准备:更新软件源、安装依赖和基础工具

准备工作看似简单,但很多安装失败都是因为这一步偷懒导致的。在开始之前,你需要确保系统能够正常访问Ubuntu软件源,并更新到最新的软件包信息。

首先要做的是:

sudo apt update sudo apt upgrade -y

这里的apt update是刷新软件包索引,apt upgrade则是把系统已有的软件包升级到软件源中的最新版。升级耗时可能比较久,取决于你网络速度和系统原有包的数量。千万别跳过upgrade直接装Docker,否则可能因为依赖库版本旧导致Docker无法启动。

接下来安装一些常用的基础工具:

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

这些工具是干嘛的呢?ca-certificates用来验证HTTPS证书,curl用来下载GPG密钥,gnupg用来导入和验证密钥,lsb-release用于识别当前系统的发行版版本代号。而这些正是添加Docker官方apt源所必需的前置条件。后面在添加源时我们会用到它们的。

如果你的Ubuntu是24.04或更新版本,系统默认可能已经装了curl和ca-certificates,但多执行一遍也无妨。

2.2 Docker Engine安装的三种方案对比

在动手之前,先把方案对比清楚,这样你就明白自己正在执行的操作到底在做什么。

方案命令/方式优点缺点建议
官方apt源添加Docker源后安装docker-ce版本新、升级方便、官方支持需要先配置GPG密钥和源文件首选
一键脚本curl -fsSL https://get.docker.com | sh命令少、适合快速安装不便于控制版本、脚本逻辑不透明仅限临时体验
手动二进制下载压缩包解压、配systemd可离线安装、可定制步骤多、升级麻烦不推荐新手

我强烈推荐方案一。虽然需要多敲几条命令,但对系统侵入更可控,后面升级维护也简单。而且脚本方式安装的Docker源和方案一其实是同一个,只是它自动帮你配置好了,如果你能接受它自动添加源的行为,其实也无妨。但我见多了脚本执行到一半网络断开导致残留垃圾的情况,所以还是手动来吧。

2.3 Docker Compose 插件安装与升级的核心逻辑

前面说到新版Docker Compose是Docker CLI插件,所以安装Docker Compose最优雅的方式就是安装Docker官方源里那个docker-compose-plugin包。

安装命令非常简单:

sudo apt install -y docker-compose-plugin

安装后执行:

docker compose version

如果输出了类似Docker Compose version v2.24.2的内容,说明已经成功。注意这里输出的版本号前缀是v2.x.x,这一点很重要。

但很多人会遇到一种情况:系统里本身已经有一个名为docker-compose的旧版二进制文件(通常是V1版本,Python编写,版本号是1.29.2之类),或者是之前通过pip安装的docker-compose。此时你执行docker compose和docker-compose可能会得到完全不同的版本,甚至相互冲突。我的建议是,确定部署环境中的主要版本,最好是统一使用V2插件,并把旧V1二进制卸掉:

sudo apt remove docker-compose

如果你确实需要把Compose插件更新到指定新版本(比如热搜里面出现的2.23版本),可以通过如下方式:

sudo apt install -y docker-compose-plugin=2.23.0~ubuntu-~jammy

不过具体版本号需要先通过apt-cache policy docker-compose-plugin查看可用版本列表。例如:

apt-cache madison docker-compose-plugin

根据你使用的Ubuntu版本,前缀会不一样,比如jammy对应22.04,noble对应24.04。照着输出的版本号选择即可。

顺带提一下,当你只需要更新Compose插件时,直接执行:

sudo apt install -y --only-upgrade docker-compose-plugin

这个命令会只升级Compose插件,不动Docker Engine本体,适合在不确定的情况下安全更新。

2.4 配置镜像加速器:解决Docker镜像下载慢的核心手段

刚装好Docker,很多人兴致勃勃想拉一个镜像,结果发现速度惨不忍睹。这里的原因不用多说,但解决方法非常明确:给Docker daemon配置一个国内的镜像加速地址。这个地址可以是云服务商提供的加速器地址,比如“你自己的加速器地址”;由于加速器地址每个人不一样,需要在相关云服务商的控制台获取。如果你没有云服务商账户,也可以用一些公共的镜像源,但公共源可能不稳定,我更推荐你在自己的云服务商控制台找到专属地址。

关键是配置文件格式。Docker守护进程会读取 /etc/docker/daemon.json 文件,如果这个文件不存在就新建。内容如下:

{ "registry-mirrors": ["https://你的加速地址"] }

保存后重启Docker:

sudo systemctl daemon-reload sudo systemctl restart docker

验证是否生效:

docker info

在输出中找“Registry Mirrors”这一行,如果列出了你配置的地址就代表成功了。注意,这里的daemon.json还可以同时配置日志大小、存储驱动等参数,我后面会分享一个比较实用的组合配置。

3. 实操过程与核心环节实现

3.1 从头开始:逐步安装Docker Engine(基于官方apt源)

假定你的Ubuntu已经完成了系统更新和基础工具安装,现在开始正式的安装流程。

第一步,添加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

这里解释一下每个动作:首先创建 /etc/apt/keyrings 目录,如果目录已经存在不会报错;然后用curl下载Docker官方GPG公钥,并通过 gpg --dearmor 命令把公钥转换为二进制存储格式,放到指定路径;最后给这个文件添加读权限,让apt可以读取。

第二步,添加Docker的apt软件源。这一步很关键,建议使用下面的方式,它根据你的Ubuntu版本自动选择对应代号:

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

$(dpkg --print-architecture) 会自动识别系统架构(amd64、arm64等),$(lsb_release -cs) 会自动识别Ubuntu版本代号(如jammy、noble)。这样写的好处是,将来系统升级或在不同机器上复制粘贴时不需要手动改。

第三步,更新源并安装Docker套件:

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

这里我加了docker-buildx-plugin,它用于构建多架构镜像,属于现代Docker的标准配置。如果你只打算跑别人的镜像,buildx可以不装,但我建议还是装上,免得到时候用Dockerfile构建镜像时发现缺少指令。

安装完成后,启动Docker并设置开机自启:

sudo systemctl enable docker --now

上面的命令等效于先执行systemctl enable docker再执行systemctl start docker,一条命令搞定。通过systemctl status docker查看状态,看到active (running)就对了。

3.2 安装和验证Docker Compose插件

如果你按照上面的命令执行了,docker-compose-plugin已经一并装好了,无需再单独操作。此时执行:

docker compose version

正常情况下输出类似:

Docker Compose version v2.30.3

注意,我当前环境是Ubuntu 24.04,Docker官方源提供的版本会随时间变化。如果你看到的是2.20或更早,建议通过 apt update 升级源后再安装,或者用前面提到的指定版本方式。

如果你更习惯传统用法,也可以创建一个别名,让自己既能用docker compose也能用docker-compose:

echo "alias docker-compose='docker compose'" >> ~/.bashrc source ~/.bashrc

不过这不是必须的,只是为了照顾肌肉记忆。

3.3 配置用户组:让当前用户免sudo使用Docker

每次敲docker命令都要带sudo,非常烦人。而且更麻烦的是,在Compose文件中如果宿主机文件权限处理不当,sudo执行和普通用户执行会产生不同的文件归属,容易让人困惑。

解决办法是将当前用户加入docker用户组:

sudo usermod -aG docker $USER

然后关键的一步是:你必须重新登录系统,或者执行newgrp docker命令切换用户组,否则当前shell不会生效。最简单的方式是注销重新登录,或者重启虚拟机。执行完后用id命令验证:

id

输出中应该包含docker字样。然后直接执行:

docker ps

如果不再提示permission denied,就说明成功了。

这里有个安全提醒:加入了docker组的用户相当于拥有了root权限,因为docker的socket控制能力极强。所以请只把自己信任的用户加入docker组,不要在多人共享的服务器上随意给用户加这个权限。

3.4 首次运行验证:用hello-world和Nginx确认环境OK

安装完成之后,第一件事就是跑一个hello-world镜像验证Docker引擎是否能正常工作。

docker run hello-world

如果一切正常,会看到一段英文提示,说明你的安装是成功的。但hello-world只是一个很小的测试镜像,我建议再拉一个Nginx镜像并启动容器来做一次更实际的测试,同时验证网络和端口映射是否正常:

docker run -d --name test-nginx -p 8080:80 nginx:alpine

然后执行docker ps,如果看到STATUS为Up,就可以用浏览器访问 http://你的UbuntuIP:8080,看到Nginx欢迎页就算大功告成。测试完删除容器:

docker rm -f test-nginx

这样你就完成了一个完整的“拉镜像→创建容器→访问服务→清理容器”的流程。接下来可以放心去玩其他镜像了。

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

4.1 添加Docker源时GPG报错、依赖无法安装

这个问题在我帮别人排查时出现频率最高。现象通常是执行apt update后,apt提示:

The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 4D1A8B5D...

原因很简单:你系统中缺少Docker官方源的GPG公钥。解决方法是手动下载并导入这个公钥。注意不要再用旧的sudo apt-key add方式了,那是被废弃的。正确的做法是重新执行前面添加GPG密钥的那三步,或者从报错里拿到KEY_ID手动添加:

sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg <(curl -fsSL https://download.docker.com/linux/ubuntu/gpg)

还有一个常见错误是执行apt install时报依赖不满足,比如“需要containerd.io >= 1.4.3”但系统里的版本更低。这种通常是因为没有先执行apt update,导致apt看到了老的索引。解决办法:

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

如果还是不行,可以尝试清理本地apt缓存再更新:

sudo apt clean sudo apt update

4.2 镜像拉取超时、加速器不生效

拉取镜像时卡住不动,或者报“dial tcp: i/o timeout”,基本可以确定是网络访问镜像仓库的问题。如果你已经按照2.4节配置了daemon.json,但docker info里还没看到Registry Mirrors,就要检查文件路径和JSON格式是否正确。比如我见过有人把 daemon.json 写成了 daemon.json.txt,或者用记事本编辑保存后带上了BOM头,都会导致Docker无法解析。

配置完加速器之后,记得重启:

sudo systemctl daemon-reload sudo systemctl restart docker

如果你用的是云服务器,由于安全组策略,部分对外访问端口可能被限制,但这不影响主动拉取镜像。此外,如果你配置了多个镜像加速地址,Docker会按顺序尝试,当前面的地址连接不上时自动切换。我建议至少配置两个或三个,防止某个地址抽风。

不过也得说明白一点:即使配置了加速器,某些特殊镜像(比如超大的AI模型镜像)拉取速度依然可能不乐观,这是正常的。可以适当调整镜像拉取的并发数,不过这属于进阶调优,日常使用没必要折腾。

4.3 Docker Compose版本更新到指定版本的方法

我已经在前面提到,可以通过apt安装或升级docker-compose-plugin。但如果你确实想用传统方式手动更新到2.23版本,也可以这么做。先在GitHub官方Release页面找到对应版本,然后根据你的CPU架构下载二进制文件,比如x86_64的机器:

sudo curl -L "https://github.com/docker/compose/releases/download/v2.23.0/docker-compose-linux-x86_64" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose

然后验证:

docker-compose --version

这种方法其实是V2的独立二进制形态,安装后可以使用docker-compose命令。但我建议优先用插件方案,因为在apt体系下,Compose、Engine、CLI等组件版本可以互相协调。手动下二进制虽然也能用,但容易和插件方式并存,导致你执行docker compose和docker-compose输出不同版本,后面维护时容易混乱。

如果你只是想更新插件到2.23版本,可以这样:

sudo apt update sudo apt-cache madison docker-compose-plugin

找到对应版本后安装:

sudo apt install -y docker-compose-plugin=2.23.0~ubuntu-~jammy

具体的版本号字符串以apt-cache从输出为准,不要抄我这里的示例,因为不同Ubuntu版本对应不同的后缀。

试过几次后你会发现,用apt管理Docker的好处就是,无论怎么更新都不会把系统搞乱,这一点非常省心。

4.4 Docker启动失败、daemon.json配置导致无法启动

如果你修改了/etcdocker/daemon.json后,执行systemctl start docker发现启动失败,可以先查看具体报错:

journalctl -u docker --no-pager | tail -50

最常见的错误是JSON格式错误。一个很简单的校验方式是在本地执行:

python3 -m json.tool /etc/docker/daemon.json

如果输出的是格式化后的JSON内容,说明格式没问题;如果报错,会提示具体的行和列。再比如,有时候你配置了 "iptables": false,会导致容器网络无法正常通信,我遇到过有人为了“优化”照抄网上的配置,最后所有容器都不能联网。请先搞清楚每个参数的含义再改,不要盲目配置。

下面给出一份比较实用的daemon.json配置,包含了镜像加速、日志大小限制和存储驱动设置:

{ "registry-mirrors": ["https://你的加速地址"], "log-driver": "json-file", "log-opts": { "max-size": "100m", "max-file": "3" }, "storage-driver": "overlay2" }

这段配置的意义是:限制单个容器日志文件最大100MB、最多保留3个文件,防止Docker日志把磁盘占满;存储驱动使用overlay2,这是目前性能和兼容性比较好的方案。如果你不确定某个参数的含义,宁可不写,也不要乱写。

4.5 用docker-compose快速部署一个MySQL实例(扩展练习)

Docker本身安装好了,Compose也有了,如果不来点实际场景,总觉得少了点什么。这里我分享一个非常常见的场景:用docker-compose跑一个MySQL 8.0,并设置好密码和数据库。

创建一个项目目录并进入:

mkdir -p ~/mysql-demo && cd ~/mysql-demo

创建一个docker-compose.yml文件:

services: mysql: image: mysql:8.0 container_name: mysql-demo restart: always environment: MYSQL_ROOT_PASSWORD: yourpassword MYSQL_DATABASE: demo ports: - "3306:3306" volumes: - ./data:/var/lib/mysql command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci

然后启动:

docker compose up -d

等待拉取镜像和启动容器完毕后,用如下命令验证:

docker ps docker exec -it mysql-demo mysql -uroot -p

输入你设置的密码后,就能进入MySQL控制台了。

这里有几个细节值得说明。volumes把宿主机当前目录下的data挂载到容器内的/var/lib/mysql,这样即使删掉容器,数据库文件也不会丢。command后的参数是设置MySQL默认字符集为utf8mb4,避免出现中文乱码。restart: always保证Docker重启后MySQL容器自动拉起,省去手工启动。

如果你发现“3306端口被占用”,说明宿主机上已经有一个MySQL或MariaDB服务占用了这个端口。可以修改ports为“3307:3306”,然后用3307端口访问容器内的MySQL。

这个例子很小,但足够让你体会docker-compose带来的便利:一个yaml文件,一条命令,整个应用环境就起来了。后面你部署Redis、GitLab、Jumpserver等都能用同样的思路。

最后再分享一个我在实际使用中踩过的坑:刚装好Docker,不要急着把一堆容器全部用--restart=always跑起来,先在一个临时目录里测试Compose文件语法是否正确。可以执行:

docker compose config

这个命令会校验并打印最终的Compose配置,不会启动任何容器,相当于语法检查。每次改完YAML,先执行这个命令再up,能帮你省下大量调试时间。另外,如果你在虚拟机或云服务器上装Docker,记得确保硬件虚拟化没有把CPU的虚拟化功能关掉,否则某些需要嵌套虚拟化的容器(比如Android模拟器)可能跑不起来,但这和Docker本体安装无关,就不展开说了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/18 11:18:16

脑数据资产化:技术实现与隐私保护方案

1. 脑数据资产化的技术实现路径作为一名在数据安全领域工作多年的工程师&#xff0c;我最近深入研究了一个极具争议性的话题——如何将人类脑数据转化为可交易的数字资产。这个看似科幻的概念&#xff0c;实际上已经具备了初步的技术可行性。让我们从技术栈的构建开始&#xff…

作者头像 李华
网站建设 2026/9/18 11:16:51

【ComfyUI】SD3.5 + ControlNet 模糊引导图生图

今天展示的案例是一个基于 Stable Diffusion 3.5 与 ControlNet 的 ComfyUI 工作流,整个流程通过加载预训练模型、结合文本提示、图像输入以及控制网络,实现了对复杂画面的精准生成与细节控制。 该工作流特别适合需要在保持画面结构稳定的前提下,对生成效果进行多维度约束和…

作者头像 李华
网站建设 2026/9/18 11:16:23

Unity发热优化实战:GC、Draw Call与Canvas重建的CPU陷阱

手机厂家这些年把散热堆得再猛&#xff0c;也架不住游戏内几个毫秒的CPU峰值负载把机身烤成暖手宝。很多团队查发烫问题时习惯性把矛头指向GPU&#xff0c;但拿Unity出的包在真机上跑一遍Profile&#xff0c;你会发现CPU经常比GPU更忙。尤其是GC、Draw Call和Canvas重建这三个隐…

作者头像 李华
网站建设 2026/9/18 11:16:19

Unity Shader实现UI流光效果:原理、参数调优与移动端性能优化

你可能在游戏里见过这种效果&#xff1a;一张卡牌上有一道亮光从左下扫到右上&#xff0c;然后过几秒又来一次&#xff1b;或者一个武器图标上&#xff0c;高光条不停从表面滑过。这个就是典型的“流光效果”&#xff0c;在UI界面、装备图标、技能按钮上非常常见。很多人第一反…

作者头像 李华
网站建设 2026/9/18 11:16:02

深入Storybook架构:Monorepo设计与模块化系统

深入Storybook架构&#xff1a;Monorepo设计与模块化系统 Storybook采用先进的Monorepo架构设计&#xff0c;通过精心组织的目录结构和现代化的工具链&#xff0c;实现了高度模块化和可扩展的开发模式。该架构使用Yarn Workspaces和Nx构建系统管理多个包&#xff0c;包含core/核…

作者头像 李华
网站建设 2026/9/18 11:14:46

CSS Grid 核心概念与实战:从网格线到响应式布局一文讲透

做前端这几年&#xff0c;如果让我评一个“文档看过、真到用时就怂”的 CSS 模块&#xff0c;CSS Grid 网格布局绝对排第一。不少人都在教程里见它炫技&#xff0c;什么九宫格、双飞翼、瀑布流&#xff0c;看起来无所不能&#xff0c;可真到自己写页面&#xff0c;手指头还是习…

作者头像 李华