单机跑容器用 docker run 还行,但一旦服务多起来——web、数据库、缓存、消息队列——每次都要敲一串长命令,端口映射、网络、卷挂载都得一个个配,很容易搞乱。
Docker Compose 就是解决这个问题的。再往上,如果你有多台机器,想组成一个集群来跑容器,那就是 Docker Swarm 的事了。
Docker Compose
什么是 Compose
Docker Compose 用 YAML 文件定义一组容器的配置,一条命令就能把整套服务拉起来。
一个最简单的例子:
services:
web:
image: nginx:latest
ports:
- "8080:80"
跑起来:
docker compose up -d
就这么简单。下面看一个更完整的例子。
Compose 文件结构
services:
web:
build: .
ports:
- "8080:80"
environment:
- DB_HOST=db
depends_on:
- db
db:
image: mysql:8
environment:
MYSQL_ROOT_PASSWORD: example
volumes:
- mysql-data:/var/lib/mysql
volumes:
mysql-data:
组成 Compose 文件的三个顶层字段:
- services — 定义各个容器服务
- volumes — 声明要使用的数据卷
- networks — 声明要使用的网络
build
指定用当前目录下的 Dockerfile 构建镜像,而不是从仓库拉:
services:
web:
build: .
也可以指定 Dockerfile 路径和构建参数:
services:
web:
build:
context: .
dockerfile: Dockerfile.prod
args:
APP_VERSION: "1.0"
ports
端口映射,格式跟 docker run -p 一样:
services:
web:
ports:
- "8080:80"
- "443:443"
environment / env_file
环境变量:
services:
app:
environment:
- DEBUG=true
- DB_HOST=db
或者从文件加载:
services:
app:
env_file: .env
volumes
挂载卷或目录:
services:
db:
volumes:
- mysql-data:/var/lib/mysql # 具名卷
- ./init.sql:/docker-entrypoint-initdb.d/init.sql # 目录挂载
volumes:
mysql-data:
networks
指定容器加入哪个网络:
services:
web:
networks:
- frontend
db:
networks:
- backend
networks:
frontend:
backend:
不指定的话 Compose 会创建一个默认网络,所有服务自动加入。
depends_on
控制启动顺序:
services:
web:
depends_on:
- db
- redis
注意 depends_on 只控制启动顺序,不保证服务就绪——db 容器起来了不代表 MySQL 接受连接。需要就绪检查的话可以用 healthcheck。
restart
重启策略,跟 --restart 一样:
services:
web:
restart: always
常用命令
所有命令都在 docker compose 子命令下(注意新版去掉了连字符,是 docker compose 不是 docker-compose)。
up
创建并启动所有服务:
docker compose up -d
-d 后台运行,不加的话前台跑,能看到所有服务的日志合流。
down
停止并删除所有容器、网络:
docker compose down
加 -v 会连数据卷一起删:
docker compose down -v
ps
查看当前 Compose 项目里的容器状态:
docker compose ps
logs
查看所有服务的日志:
docker compose logs web
加 -f 实时跟踪:
docker compose logs -f
exec
在运行中的容器里执行命令:
docker compose exec web bash
build
重新构建镜像:
docker compose build
实战:WordPress + MySQL
一个完整的 Compose 示例:
services:
db:
image: mysql:8
volumes:
- db_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: rootpass
MYSQL_DATABASE: wordpress
MYSQL_USER: wpuser
MYSQL_PASSWORD: wppass
restart: always
wordpress:
image: wordpress:latest
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: wpuser
WORDPRESS_DB_PASSWORD: wppass
WORDPRESS_DB_NAME: wordpress
depends_on:
- db
restart: always
volumes:
db_data:
启动:
docker compose up -d
访问 http://localhost:8080 就能看到 WordPress 安装界面了。
Docker Swarm
什么是 Swarm
Compose 管的是单机上的多容器编排,Swarm 管的是多台机器组成的集群。Swarm 是 Docker 原生的容器编排工具,跟 Docker CLI 深度集成,不需要额外装东西。
核心概念
Swarm 里有几个基本概念,理解了它们就好上手了:
- Node(节点) — 集群里的每一台机器都是一个节点。节点分为两种角色:
- Manager(管理节点):负责集群管理、任务调度、维护集群状态。生产环境推荐部署奇数个(3 或 5)保证高可用
- Worker(工作节点):只负责跑容器,不参与管理。管理节点挂了不影响 worker 上已经在跑的服务
- Service(服务) — 定义要跑什么镜像、跑几个副本、暴露什么端口等。Swarm 会确保 service 声明的状态始终被满足,比如要 3 个副本,挂了一个就自动再拉一个
- Task(任务) — service 的每一次具体执行就是一个 task,对应一个容器。Swarm 把 task 调度到合适的节点上运行
它们的关系是:Service → Task(s) → Container。你定义 service,Swarm 创建对应数量的 task,每个 task 启动一个容器。
一个 Swarm 集群由管理节点和工作节点组成。管理节点负责调度和集群管理,工作节点负责跑容器。
初始化集群
选一台机器做管理节点:
docker swarm init --advertise-addr 192.168.1.100
执行后会输出一条加入命令,复制下来在其他节点上执行:
docker swarm join --token SWMTKN-1-xxxxxxxxxx 192.168.1.100:2377
只有一台机器也能玩,Swarm 默认允许在管理节点上跑任务。
查看集群里的节点:
docker node ls
Service
Swarm 里不叫容器,叫 service。一个 service 可以指定跑几个副本(replicas),Swarm 负责把副本分发到各个节点上。
docker service create --name web --replicas 3 -p 8080:80 nginx
--replicas 3— 跑 3 个副本-p 8080:80— 端口映射,Swarm 会自动做负载均衡
查看 service:
docker service ls
docker service ps web
滚动更新:
docker service update --image nginx:1.27 web
弹性伸缩
流量上来了,把副本数扩上去:
docker service scale web=5
流量下去了,再缩回来:
docker service scale web=2
Swarm 会自动把新增或减少的 task 调度到合适的节点上。缩容时会优先停掉负载较高的节点上的容器。
配合 docker service update 可以同时改镜像和副本数:
docker service update --image nginx:1.27 --replicas 5 web
在 Stack 里定义初始副本数,后续用 scale 命令弹性调整,不用改 YAML 文件。
Stack
Stack 是 Compose + Swarm 的结合——用 Compose 文件定义服务,用 Swarm 来跑。
docker stack deploy -c docker-compose.yml myapp
跟 docker compose up 的区别:
docker compose up | docker stack deploy | |
|---|---|---|
| 作用范围 | 单机 | 整个 Swarm 集群 |
| 副本支持 | 不支持 | 支持 deploy.replicas |
| 滚动更新 | 不支持 | 支持 |
| 配置管理 | 无 | 支持 Config / Secret |
Stack 的 YAML 和 Compose 基本一样,但 Stack 会忽略 build 指令(必须用已存在的镜像),同时能识别 deploy 字段。
services:
web:
image: nginx:latest
ports:
- "8080:80"
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure
管理节点高可用
Swarm 支持多个管理节点,避免单点故障。推荐部署奇数个(1、3、5):
docker node promote node2 node3
只有第一个管理节点是 leader,其他管理节点是 follower。leader 挂了之后 follower 会重新选举。
跟 K8s 的简单对比
Swarm 比 Kubernetes 简单很多,但也弱很多:
| Swarm | Kubernetes | |
|---|---|---|
| 安装 | Docker 自带 | 需要单独装 |
| 学习成本 | 低 | 高 |
| 功能丰富度 | 基本够用 | 非常丰富 |
| 生态 | Docker 原生 | 极其庞大 |
| 适用场景 | 小团队、小集群 | 大规模生产环境 |
如果你只有几台机器,不想折腾 K8s,Swarm 是个很轻量的选择。如果规模上去了,还是得 K8s。
