1. 装了这么久,你可能还没搞懂 docker-compose 在装什么
先聊点实在的。我这两年处理过不少部署事故,最后排查下来,相当一部分不是 yaml 写错了,而是服务器上的 docker-compose 根本没装对。注意,我说的是“装对”,不只是“装上”。docker-compose 这个工具看起来很不起眼,但它的安装方式、版本来源、命令入口,水比很多人想象中深得多。
老版本 docker-compose 1.x 用 Python 写的,发布形态是独立二进制,装完以后命令是docker-compose,中间带横杠。2020 年以后,Docker 官方用 Go 重写了 compose 能力,改成 Docker CLI 的插件,命令是docker compose,中间是空格。这个变化是很多混乱的源头:同一个服务器上可能两个命令同时存在,但一个指向 v1、一个指向 v2,跑出来的结果完全不一样。
所以这篇文章不是一个单纯的“安装教程”,我把安装选型、Windows 环境下的基础服务部署、版本升级、国内下载受限和离线环境部署这四条线整个过一遍。适合两类人看:一类是刚入门、照着网上教程总是装不明白的;另一类是在生产环境维护多台机器、经常被版本问题坑的。
2. Linux 安装的三条路线:别再只会 curl GitHub 了
很多人一搜“docker-compose 安装”,出来的教程千篇一律都是 GitHub Release 拉二进制。这条路本身没错,但它不是唯一方案,而且在部分网络环境下根本走不通。我按实用程度把三条路线讲清楚。
2.1 官方二进制安装:通用但要注意两个细节
x86_64 的 Ubuntu 机器上,官方最原始的方法是:
sudo curl -SL https://github.com/docker/compose/releases/download/v2.23.3/docker-compose-linux-x86_64 \ -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose执行完以后测试一下:
docker-compose version看到Docker Compose version v2.23.3就算成功。这里有两个容易被忽视的细节。
第一个是架构。ARM 机器要把文件名换成docker-compose-linux-aarch64,这个不搞清楚,下载完一执行就会报Exec format error。判断架构用这个命令:
uname -m输出x86_64就下 x86_64,输出aarch64就下 aarch64。
第二个是插件目录。只把二进制扔进/usr/local/bin,只能激活docker-compose这个横杠命令。如果你想docker compose(空格版)也能用,得补一个软链接:
sudo mkdir -p /usr/local/lib/docker/cli-plugins sudo ln -sf /usr/local/bin/docker-compose /usr/local/lib/docker/cli-plugins/docker-compose很多教程不会讲这一步,但实际维护中,新版工具链(比如一些 CI 脚本、Portainer 的栈)调用的就是docker compose插件入口,不补这个链接,排查起来很抓狂。
2.2 包管理器安装:最省心但前置条件略多
如果你的机器已经配置了 Docker 官方 apt 源,安装 compose 变得极其简单:
sudo apt update sudo apt install docker-compose-plugin装完验证:
docker compose version这个包会自动把插件放到/usr/libexec/docker/cli-plugins/docker-compose,路径不用你操心,升级也用 apt 一把梭。CentOS 系对应命令是:
sudo yum install docker-compose-plugin但包管理器方案有个前置条件:你得先有 Docker 官方源。很多人装 Docker 的时候用的是发行版自带源或者一堆第三方脚本,这时候apt install docker-compose-plugin会直接报“找不到包”。碰到这种情况,要么先配好官方源,要么退回 2.1 的二进制方案。
2.3 指定特定版本安装的三招
“指定特定版本”这个需求,我在排查问题时遇到最多。要么是项目文档明确要求 compose 2.23,要么是生产环境不敢用最新版。这里给三个办法。
第一,二进制直接指定。GitHub Release 的 URL 结构是固定的,把版本号换成v2.23.0、v2.23.3都可以:
sudo curl -SL https://github.com/docker/compose/releases/download/v2.23.0/docker-compose-linux-x86_64 \ -o /usr/local/bin/docker-compose第二,apt 锁版本。先查可用版本:
apt-cache madison docker-compose-plugin输出会列出形如2.23.0-1~ubuntu.22.04~jammy的版本号,然后安装指定版本:
sudo apt install docker-compose-plugin=2.23.0-1~ubuntu.22.04~jammy第三,用 Docker 镜像拉取指定 tag(第五部分会展开),适合 GitHub 访问不顺畅的场景。
三种方式的取舍,我列个表:
| 安装方式 | 适用场景 | 缺点 |
|---|---|---|
| GitHub 二进制 | 所有 Linux,最通用 | 受网络限制,需手动管升级 |
| 包管理器 | 已配官方源的 Debian/RHEL | 源没配好会找不到包 |
| Docker 镜像提取 | 有 Docker 但拉不动 GitHub | 多一步容器文件拷贝 |
3. Windows 11 部署 Redis、PostgreSQL 基础服务实测
Windows 下搞 docker-compose 的场景这两年多了不少,很多本地开发环境、测试环境直接跑在 Windows 11 上。热搜词里“win11 部署 docker-compose 基础服务 redis、postgre”正好戳中这个需求。我实测了一条完整链路。
3.1 准备:WSL2 + Docker Desktop
Windows 上不需要单独安装 compose,Docker Desktop 里已经自带 compose v2。真正需要花心思的是 WSL2 后端。安装顺序别乱:
wsl --install装完重启,确认 WSL 版本:
wsl --list --verbose确保版本显示是 2。如果显示 1,执行wsl --set-version <发行版名> 2升级。然后安装 Docker Desktop,安装时保持默认的“Use WSL 2 based engine”勾选。开机后在 Settings -> Resources -> WSL Integration 里打开你要用的发行版开关。
这里有个细节容易踩坑:Docker Desktop 虽然默认集成 compose,但一些历史版本默认关闭了老命令docker-compose的兼容入口。如果你的脚本里写的是横杠命令,在 Docker Desktop 里老老实实升级到近一年内版本,大概率就解决了。
3.2 编写 redis + PostgreSQL 的 compose 文件
我直接给你一个能在 Windows 11 上跑起来的模板。新建一个目录,比如dev-stack,在里面创建docker-compose.yml:
services: redis: image: redis:7.2-alpine container_name: dev-redis ports: - "6379:6379" volumes: - redis-data:/data restart: unless-stopped command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD} networks: - dev-net postgres: image: postgres:15-alpine container_name: dev-postgres ports: - "5432:5432" environment: POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB} volumes: - pg-data:/var/lib/postgresql/data restart: unless-stopped networks: - dev-net volumes: redis-data: pg-data: networks: dev-net:注意三个细节。
第一,我没有在文件顶部写version: '3.8'。compose v2 已经不再需要这个字段,写上反而可能触发个别版本的警告,干脆删掉。
第二,Redis 的密码是通过command里${REDIS_PASSWORD}注入的,PostgreSQL 的用户、密码、库名都来自环境变量,不能真写死。所以同目录下必须建一个.env文件:
REDIS_PASSWORD=dev-redis-pass-2025 POSTGRES_USER=app POSTGRES_PASSWORD=dev-pg-pass-2025 POSTGRES_DB=appdb第三,卷我用的命名卷而不是./data这种本机路径。原因很现实:Windows 下 bind mount 的 I/O 性能有明显损耗,而且文件权限经常出幺蛾子,Redis 容器往./data写文件时,偶尔会报权限拒绝。命名卷由 Docker 自己管理,省心太多。
3.3 启动、验证、日常维护
在dev-stack目录下执行:
docker compose config这个命令会渲染出最终生效的配置,相当于“预检查”,非常建议养成先 config 再 up 的习惯。确认没问题后:
docker compose up -d docker compose ps验证 Redis:
docker exec -it dev-redis redis-cli -a dev-redis-pass-2025 ping看到PONG就通了。验证 PostgreSQL:
docker exec -it dev-postgres psql -U app -d appdb -c "select 1"日常维护就三条命令,docker compose logs -f看日志,docker compose restart重启,docker compose down -v连同卷一起清理。最后一个要慎重,加了-v会把数据删光。
4. 版本升级:安全升到 2.23 的两个姿势和回滚方案
很多开源项目部署时会检查 compose 版本,我就见过官方安装脚本输出一行“需要 docker-compose 2.20+,当前版本过低”然后退出。这种场景下,“升级到指定版本”就是硬需求。
4.1 升级前先把基线搞清楚
一上来就覆盖是不行的。我处理过的翻车事件里,有一半是没分清自己机器上到底有几个 compose。先执行:
docker compose version docker-compose version which docker-compose如果两个命令输出的版本不同,说明机器上同时存在多种安装。这时候别急着升,先确定你的脚本到底调用哪个入口。这一步确定不了,后边全白搭。
4.2 姿势一:二进制直接覆盖
如果当前是二进制安装,升级就是下载新版本覆盖旧文件:
sudo curl -SL https://github.com/docker/compose/releases/download/v2.23.3/docker-compose-linux-x86_64 \ -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose docker-compose version这里我想多提一句:2.23 这个版本号,在 GitHub Release 里实际上有v2.23.0、v2.23.1、v2.23.2、v2.23.3几个 patch 版本。如果项目文档只写了“2.23”,我通常建议选最后一个 patch,也就是v2.23.3。早期 patch 往往带着一些小毛病,晚几周的版本稳定不少。
4.3 姿势二:apt 升级 docker-compose-plugin
如果当初是用包管理器装的,升级更简单:
sudo apt update sudo apt install --only-upgrade docker-compose-plugin注意--only-upgrade这个参数很重要。它告诉 apt 只升级这个包,不要顺手把其他包也带上去。生产环境里批量升级依赖包,风险不可控。
升级完再看一眼版本:
docker compose version输出应该变成Docker Compose version v2.23.3之类的。
4.4 回滚与版本锁定
升级后如果发现新版本不兼容你的某个脚本,回滚是绕不开的动作。apt 方式指定旧版本装回去就行:
sudo apt install docker-compose-plugin=2.21.0-1~ubuntu.22.04~jammy二进制方式更简单,下载一份旧版本覆盖即可。这里我建议生产环境把两个版本号都记下来:一个是运行版本,一个是安装包版本。以后不管是审计还是排障,都有据可查。
5. 国内下载源与离线部署:从 GitHub 拉不动说起
“docker-compose 国内下载源安装”是热搜词里很有信息量的一个。GitHub Releases 在国内网络环境下确实时好时坏,这不是玄学,就是现实。我自己的处理逻辑分三层:先用包管理器,再换镜像办法,最后才考虑离线传输。
5.1 从 Docker 镜像里“抠”出 compose 二进制
如果你已经装了 Docker,但 GitHub 下载弹窗一直转圈,有一个很顺手的方案:用 docker/compose 官方镜像。Docker Hub 拉镜像一般能配上加速器,比直连 GitHub 稳得多。
docker pull docker/compose:2.23.3 docker container create --name compose-tmp docker/compose:2.23.3 sudo docker cp compose-tmp:/usr/local/bin/docker-compose /usr/local/bin/docker-compose sudo docker rm compose-tmp简单解释一下:docker/compose是官方维护的发行版镜像,里面已经打包好了对应版本的二进制。docker container create只是创建一个容器但不启动它,然后用docker cp从容器文件系统里把二进制拷出来。拷完之后容器删掉,干干净净。
这个思路也适用于离线环境,下面详细说。
5.2 离线部署的完整链路:以国产化系统为例
离线部署是很多运维同学头疼的事。尤其是部分国产化环境,像麒麟这类系统,默认软件源里不一定有 compose,网络又隔离,常规在线安装全失效。我实操过一套可行的链路,这里分成三步。
第一步,准备一台同架构的联网机器。所谓“同架构”很关键。目标机器是 aarch64,你在 x86_64 的机器上下载,拷过去一样用不了。用uname -m先确认两边的架构一致。
第二步,在联网机器上拉镜像并打包:
docker pull docker/compose:2.23.3 docker save -o compose-2.23.3.tar docker/compose:2.23.3然后把这个 tar 文件通过 U 盘、内网共享或者其他合规方式传到目标机器。
第三步,在目标机器上导入镜像并提取二进制:
docker load -i compose-2.23.3.tar docker container create --name compose-extract docker/compose:2.23.3 sudo docker cp compose-extract:/usr/local/bin/docker-compose /usr/local/bin/docker-compose sudo docker rm compose-extract sudo chmod +x /usr/local/bin/docker-compose docker-compose version如果目标机器连 Docker 也没有,那就要连 Docker 引擎的离线安装包一起解决,这就超出 compose 本身的范围了。至少目前这套方案覆盖了“有 Docker、没 compose”的常见情况。
5.3 镜像加速器的配置注意点
在线环境下,进程范围内的加速可以通过/etc/docker/daemon.json配置镜像加速:
{ "registry-mirrors": [ "https://docker.m.daocloud.io", "https://dockerproxy.com" ] }配置后重启 Docker:
sudo systemctl daemon-reload sudo systemctl restart docker必须提醒的是,第三方加速器的可用性变动很快,新配置是否生效用docker info查看Registry Mirrors字段。如果某个加速器失效,及时替换,不要把 daemon.json 写死成单一源。
6. 安装和运维中最常见的三个坑,我都替你踩过了
6.1 装完以后 command not found
最经典的问题。症状:docker-compose version提示命令找不到,但文件明明在/usr/local/bin下。原因基本就是 PATH 不包含/usr/local/bin,或者当前 shell 没有重新加载。
临时验证:
export PATH="$PATH:/usr/local/bin" docker-compose version确认能跑以后,把导出语句写进/etc/profile或~/.bashrc,以后再开 shell 就不会丢了。
6.2 项目自动命名导致的资源冲突
compose v2 默认用目录名作为项目名。如果你在/opt/app-redis和/opt/dev-redis两个目录分别部署 Redis,但端口都映射到宿主机 6379,第二个up的时候就会因为端口冲突而失败。这时候要么改端口,要么显式指定项目名:
docker compose -p dev up -d或者直接在 compose 文件顶层写:
name: dev这个name字段在 v2 才支持,老版本不认识,这也是为什么我建议新文件都直接写name。
6.3 老版本 yaml 里的 version 字段
网上大量旧教程的 compose 文件开头都写着version: '3.8'。在 compose v2 里这个字段会被忽略,不影响使用。但如果你同时混用了老版本 v1,文件又声明了较高的 version,旧版直接报语法错误。遇到历史遗留文件,最稳妥的处理就是删掉version字段,让工具自己判断。
我自己的习惯是:新项目从一开始就不写 version 字段,也不指定旧版兼容参数。这样不管机器上是 v2.20 还是 v2.29,行为都能保持一致。
最后说一个和版本强相关的经验。我在生产环境的部署脚本里固定了一行检查:
docker compose version || { echo "compose not found"; exit 1; }这行代码看起来简单,但它让我少接了很多“半夜部署失败”的救火电话。工具版本这种东西,平时没人管,出了问题全是坑。花十秒钟验证一下,值。