Appearance
Docker Compose
简介
docker-compose 是用于定义和运行多容器 Docker 应用的工具,通过一个 docker-compose.yml 文件统一管理多个服务的启动、网络和数据卷。
Docker Compose V2 已内置于 Docker CLI,使用
docker compose(无连字符)命令
安装
Docker Desktop(macOS/Windows)已内置 Docker Compose V2,无需单独安装。
Linux 服务器推荐通过插件方式安装(随 Docker CE 一起带入):
bash
# CentOS/RHEL(添加 Docker CE 源后)
yum install -y docker-compose-plugin
# Ubuntu/Debian
apt-get install -y docker-compose-plugin
# 验证
docker compose version如需手动安装独立二进制文件(备选):
bash
# 自动获取当前系统架构对应的二进制文件
curl -SL "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" \
-o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
docker-compose --versionDocker Compose V1(
docker-compose,有连字符)已于 2023 年 7 月停止维护,推荐使用 V2(docker compose)
常用命令
bash
# 启动
docker compose up # 前台启动所有服务
docker compose up -d # 后台启动所有服务
docker compose up -d <服务名> # 后台启动指定服务
# 重建并启动(代码变更后使用)
docker compose up -d --build
docker compose up -d --build <服务名>
# 查看
docker compose ps # 查看服务状态
docker compose logs -f # 跟踪所有服务日志
docker compose logs -f <服务名> # 跟踪指定服务日志
# 进入容器(交互式 shell)
docker compose exec <服务名> bash
# 在容器内执行单条命令(不进入交互模式)
docker compose exec <服务名> <命令>
docker compose exec nginx nginx -s reload # 平滑重载 Nginx 配置(不中断连接)
# 停止 / 删除
docker compose stop # 停止所有服务(保留容器和网络)
docker compose start # 重新启动已停止的服务
docker compose down # 停止并删除容器、网络
docker compose down -v # 同时删除数据卷
# 删除指定服务容器(网络不会删除)
docker compose rm <服务名>配置文件说明
yml
services: # 服务集合,每个服务对应一个容器
app: # 服务名,自定义,同网络内其他服务通过此名访问
image: node:22 # 使用现有镜像(与 build 互斥)
build: # 从 Dockerfile 构建镜像
context: ./app # 构建上下文目录
dockerfile: Dockerfile
restart: unless-stopped # 重启策略:always / no / on-failure / unless-stopped
# 生产建议用 unless-stopped 代替 always,避免错误状态下无限重启
ports:
- '3000:3000' # 宿主机端口:容器端口
volumes:
- ./app:/code # 绑定挂载(宿主机目录:容器目录)
- app_logs:/var/log # 具名数据卷,卷名对应下方 volumes 顶级声明
environment:
- NODE_ENV=production
- TZ=Asia/Shanghai
command: node index.js # 覆盖默认 CMD
depends_on: # 仅控制启动顺序,不保证依赖服务已就绪
- db
# 若需等待依赖服务真正就绪(如等 MySQL 启动完毕),用 condition 写法:
# depends_on:
# db:
# condition: service_healthy # 需要依赖服务配置 healthcheck
networks:
- app_net
volumes: # 顶级声明,等同于提前执行 docker volume create
app_logs: # 值为空表示使用默认驱动(local),Docker 自动管理存储位置
# 若需指定驱动或选项:
# app_logs:
# driver: local
networks: # 声明自定义网络(等同于 docker network create)
app_net:
driver: bridge
external_net: # 引用外部已存在的网络(如另一个 compose 创建的)
external: true
name: shared_network # compose down 时不会删除此网络同一 compose 网络内,服务之间直接通过服务名 + 端口访问,如
mysql:3306、redis:6379
服务间通信(关键)
同一 compose 项目内,服务之间以服务名作为主机名,以容器内端口(非宿主机映射端口)互相访问。
Nginx 反向代理到 Node 服务(nginx/config/default.conf):
nginx
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://server:3000; # server 是 compose 服务名,3000 是容器内端口
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}应用服务通过服务名连接数据库:
yml
services:
server:
environment:
- MYSQL_HOST=mysql # "mysql" 是 compose 服务名
- MYSQL_PORT=3306 # 容器内端口,不是宿主机映射端口
- REDIS_HOST=redis # "redis" 是 compose 服务名
- REDIS_PORT=6379更改服务名时,所有通过该服务名访问它的地方(nginx 配置、环境变量等)都需要同步修改
restart 重启策略
| 值 | 行为 | 适用场景 |
|---|---|---|
no | 容器退出后不自动重启(默认值) | 开发调试 |
always | 无论何种退出原因,始终重启;docker 重启后也会启动 | 需要开机自启的服务 |
on-failure | 仅在非零退出码(错误退出)时重启,正常退出不重启 | 批处理任务 |
unless-stopped | 与 always 类似,但手动 docker stop 后不再自启 | 生产服务(推荐) |
生产环境推荐
unless-stopped:手动停止容器维护时不会被自动拉起,而always会在重启 Docker 服务后强制恢复所有容器。
完整配置示例
Node 服务 + Nginx + MySQL + Redis 的典型生产配置:
yml
services:
server:
build:
context: ./server
dockerfile: Dockerfile
restart: always
networks:
- myweb
env_file:
- .env # 从 .env 文件读取环境变量,避免密码明文写入版本控制
environment:
- TZ=Asia/Shanghai
- MYSQL_HOST=mysql
- MYSQL_USERNAME=root
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
- MYSQL_DATABASE=mydb
- REDIS_HOST=redis
- REDIS_PASSWORD=${REDIS_PASSWORD}
nginx:
image: nginx:stable
restart: always
ports:
- '80:80'
- '443:443'
networks:
- myweb
volumes:
- ./nginx/config:/etc/nginx/conf.d
- ./nginx/cert:/etc/nginx/cert
- ./nginx/logs:/var/log/nginx
- ./nginx/html:/usr/share/nginx/html
environment:
- TZ=Asia/Shanghai
depends_on:
- server
mysql:
image: mysql:8.4
restart: always
ports:
- '3306:3306'
networks:
- myweb
volumes:
- ./mysql/data:/var/lib/mysql
- ./mysql/log:/var/log/mysql
- ./mysql/init:/docker-entrypoint-initdb.d
environment:
- MYSQL_ROOT_PASSWORD=${MYSQL_PASSWORD}
- TZ=Asia/Shanghai
healthcheck:
test: ['CMD', 'mysqladmin', 'ping', '-h', 'localhost', '-u', 'root', '-p${MYSQL_PASSWORD}']
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
redis:
image: redis:7
restart: always
ports:
- '6379:6379'
networks:
- myweb
volumes:
- ./redis/conf/redis.conf:/etc/redis/redis.conf
- ./redis/data:/data
command: redis-server /etc/redis/redis.conf
networks:
myweb:
driver: bridge关于
.env文件: 在docker-compose.yml同目录创建.env文件,Docker Compose 会自动加载其中的变量。.env应加入.gitignore,避免密码泄露。
bash
# .env 文件示例
MYSQL_PASSWORD=你的密码
REDIS_PASSWORD=你的密码跨 compose 服务通信
当多个 docker-compose.yml 分别管理基础服务和应用服务时,可通过引用外部网络实现跨 compose 通信:
yml
# 基础服务的 compose(先启动)
networks:
myweb:
driver: bridgeyml
# 应用服务的 compose
networks:
myweb:
external: true
name: myweb # 引用基础服务创建的网络通信时同样使用服务名,如 Nginx 反向代理到 Node 服务:
nginx
location / {
proxy_pass http://server:3000; # server 是 compose 中的服务名
}项目目录结构建议
project/
├── docker-compose.yml
├── server/ # Node 服务
│ ├── Dockerfile
│ ├── package.json
│ └── src/
├── nginx/
│ ├── config/ # nginx 配置文件
│ │ └── default.conf
│ ├── cert/ # SSL 证书
│ └── logs/
├── mysql/
│ ├── data/ # 数据持久化
│ ├── log/
│ └── init/ # 初始化 SQL 文件
└── redis/
├── conf/
│ └── redis.conf
└── data/如果服务较多,建议将 MySQL、Nginx、Redis 等基础服务拆分为一个
docker-compose.base.yml,应用服务单独一个,通过外部网络连通
Vue 项目部署
Vue 是静态页面,推荐用多阶段构建直接产出 Nginx 镜像,无需在服务器安装 Node 环境:
dockerfile
# 构建阶段
FROM node:22-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# 生产阶段
FROM nginx:stable-alpine
COPY --from=builder /app/dist /usr/share/nginx/html
# 若使用 Vue Router history 模式,需拷贝自定义 nginx 配置
# COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]若使用 Vue Router history 模式,需创建以下 nginx.conf:
nginx
server {
listen 80;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri $uri/ /index.html; # 关键:所有路由回退到 index.html
}
}bash
# 构建并运行
docker build -t my-vue-app .
docker run -d -p 80:80 my-vue-app
try_files $uri $uri/ /index.html是 Nginx 支持 Vue Router history 模式的关键配置,使用哈希模式(createWebHashHistory)则不需要
待补充
- [ ] Compose 与 Docker Swarm 的关系
- [ ]
depends_on: condition: service_healthy等待依赖就绪