跳到主要内容

Docker Compose

  • 一键启动/停止多容器服务(如前端+后端+数据库)。
    • 比如:你有一个前端、一个后端、一个数据库,想让它们一起跑起来,只需要写一个配置文件,然后用一条命令就能全部启动,非常方便!
  • 用docker-compose.yml文件统一管理服务、网络、卷等。
  • 安装了Docker,内置了Compose

简单来说,通过Docker Compose可以管理多个Docker容器服务

Docker Compose 的核心概念​

  • 服务(service):每个服务就是一个容器,比如前端服务、后端服务、数据库服务。
  • 项目(project):一组相关的服务组成一个项目(就是你整个应用)。

常用Docker Compose命令​

  • 一键启动所有服务
    • 如果改了docker配置和项目代码等等,必须用--build重新构建
    • -d : --detach 的缩写,表示 以“后台模式”运行容器
      • detach意思是分离,表示在后台(分离模式)启动服务容器;
bash
# 启动服务(使用现有镜像)
docker-compose up -d
# 重新构建镜像后再启动服务
docker compose up -d --build
  • 查看服务状态
bash
docker-compose ps
  • 查看日志
bash
docker-compose logs
  • 停止所有服务
bash
# 停止容器 、删除容器,完全销毁环境
docker-compose down
# 停止容器,不删除容器,容器还在,可随时重启
docker-compose stop

命令汇总​

bash
# 查看docker compose版本
docker compose version
命令含义常用参数参数解释
docker compose up启动服务(构建并运行容器)-d, --build, --force-recreate, --no-deps-d:后台运行(detach 模式)--build:在启动前强制构建镜像--force-recreate:即使无改动也重新创建容器--no-deps:启动服务时不启动其依赖服务
docker compose down停止并删除所有容器、网络、卷等--volumes, --rmi all--volumes:删除卷--rmi all:删除所有构建的镜像
docker compose stop停止服务但不删除容器无参数容器还在本地,数据不会丢失,可通过 start 重启
docker compose start启动已停止的服务容器无参数不会重新构建或创建容器
docker compose restart重启服务--timeout--timeout:指定容器关闭前等待时间(默认10秒)
docker compose build仅构建镜像,不运行容器--no-cache, --pull--no-cache:不使用构建缓存--pull:始终尝试拉取最新基础镜像
docker compose logs查看容器日志-f, --tail-f:实时输出日志(follow)--tail=N:显示最后 N 行日志
docker compose ps查看当前运行的服务容器状态-a-a:显示所有服务(包括未运行)
docker compose exec进入指定服务容器内部<service>, bash, sh例如:docker compose exec web bash
docker compose run启动一个临时服务容器--rm, --entrypoint--rm:容器退出后自动删除--entrypoint:覆盖默认入口命令
docker compose config检查和展示合并后的 Compose 配置--services, --volumes可用于排查配置错误
docker compose pull拉取 docker-compose.yml 中定义的镜像无参数一般用于提前拉镜像,加快构建速度

常用配置​

  • image:用哪个镜像(比如 nginx、node)。
  • build:如果你有自己的 Dockerfile,可以用 build: . 来构建镜像。
  • ports:端口映射,格式是 "本机端口:容器端口"。
  • volumes:挂载本地文件/目录到容器里,方便数据持久化或配置同步。
  • command:容器启动时执行的命令。
  • depends_on:声明依赖关系

配置例子解释​

bash
version: '3'
services:
frontend:
build: .
ports:
- "8080:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
restart: always
depends_on:
- backend
backend:
image: node:16
working_dir: /app
volumes:
- ./server:/app
command: npm start
ports:
- "3000:3000"
  • build:指定 Dockerfile 路径 ,使用当前目录下的 Dockerfile 构建镜像
  • image:直接用已有镜像。
  • volumes:挂载本地文件/目录到容器。
  • depends_on:声明依赖关系,先启动 backend。
    • 保证先启动后端再启动前端
  • ports:端口映射, 宿主机的 3000 端口 映射到 容器内部的 3000 端口。
    • 宿主机:当前运行 Docker 的机器的端口
      • 也就是自己的本地电脑 或者云服务器
  • restart: 设置重启策略
    • 容器异常退出会自动重启(推荐用于生产)
  • networks: 多个服务在一个docker compose 可以互通容器内网
  • 是为了管理和控制容器之间的网络通信
  • 对于一些私有服务不想别人访问到但自己一个服务又想访问到做网络资源隔离挺有用的

部署例子​

Nuxt3​

  • Nuxt 3 + pnpm + pm2 + nginx + Docker Compose 项目
  • 定义nuxt服务(启动node)、nginx服务(转发、代理配置)
文件 / 文件夹用途
Dockerfile构建 Nuxt + pm2 运行环境
ecosystem.config.jspm2 启动配置
docker-compose.yml启动 nuxt 服务 + nginx 服务
nginx/default.confNginx 转发配置
.dockerignore忽略不需要进入镜像的文件
pnpm-lock.yamlpnpm 依赖锁
app.vue / pages/index.vue简单 Nuxt 页面示例
nuxt.config.tsNuxt 配置

ecosystem.config.cjs​

js
// pm2 start ecosystem.config.cjs --name demo
module.exports = {
apps: [
{
name: 'demo',
port: '3000',
exec_mode: 'cluster',
instances: 'max',
script: './.output/server/index.mjs',
ignore_watch: ['node_modules', '.nuxt', '.output'],
env: {
NODE_ENV: 'production',
},
},
],
}

Dockerfile​

bash
# 第1阶段:构建镜像 (指定node基础镜像)
FROM node:20-alpine as build

# (设置工作目录) 设置容器中的工作目录为 /app,之后的命令都会在这个目录中运行。
WORKDIR /app

# (复制文件) 将当前目录下的所有文件复制到容器中的 /app 目录 (格式是 "当前目录:容器目录路径")
COPY . .

RUN npm install -g pnpm
RUN pnpm install
RUN pnpm build


# 第2阶段:部署运行
FROM node:20-alpine

WORKDIR /app

# (复制文件) 将第1阶段构建的输出文件复制到容器中的 /app 目录 (格式是 "当前目录:容器目录路径")
COPY --from=build /app/.output ./.output
COPY --from=build /app/ecosystem.config.cjs ./

# (运行脚本安装PM2) 用于启动node服务
RUN npm install -g pm2

# 暴露容器端口3000
EXPOSE 3000

# (指定Nuxt服务监听地址) 通常 Nuxt 会监听 localhost,这里强制监听 0.0.0.0 以便外部访问
ENV HOST=0.0.0.0

# (指定Nuxt服务监听端口) 应用监听的端口, 设置Node服务的PORT环境变量为3000
ENV PORT=3000

# (启动应用) 使用 PM2 启动 Nuxt 应用 (pm2-runtime是Docker运行PM2方式)
CMD ["pm2-runtime", "start", "ecosystem.config.cjs"]

docker-compose.yml​

bash
# 使用 Docker Compose 的 v3 版本语法
version: '3'

# 定义服务
services:
# (服务名称) 定义nuxt-app服务
nuxt-app:
# 使用当前目录下的 Dockerfile 构建镜像
build: .
# 指定容器名为 my-nuxt,便于识别和管理
container_name: my-nuxt
# 将宿主机的 3000 端口映射到容器的 3000 端口。 (格式是 "本机端口:容器端口")
ports:
- "3000:3000"
# 设置环境变量 (Node.js运行环境变量 => production => 启用压缩、缓存、关闭热更新、提高性能)
environment:
- NODE_ENV=production
# 挂载日志目录, 实现日志持久化 (格式是 "本机目录:容器目录")
volumes:
- ./logs:/app/logs
# 设置重启策略
restart: always
# 设置网络
networks:
- app-network

# 定义网络
networks:
# 定义网络名称为 app-network
app-network:
driver: bridge

启动服务​

bash
# 构建并启动容器
docker-compose up -d --build
# 构建成功之后访问
http://127.0.0.1:3000

集成nginx服务​

本地不需要安装nginx,只需要在docker中集成nginx服务,nginx运行在容器内部的,docker会去拉取nginx的镜像

  • 为了扩展,有些项目需要转发路径和配置代理
    • 如希望访问 www.demo.com/ads.txt 当访问ads.txt转发到其他目录中
    • 实现了代理转发这样就不需要把所有文件目录都配置在当前项目中,可以分发在不同项目目录
bash
# 进入nginx容器中的终端
docker exec -it my-nginx sh
nginx.conf​
  • 这样通过127.0.0.1就能访问nuxt服务了
bash
# 必须块。虽然这里没有配置内容,但 Nginx 要求必须有 events 块。
events {}

# http:开启 HTTP 服务配置
http {
server {
listen 80;

location / {
# nuxt-app 是 Docker Compose 中定义的服务名,相当于容器内的DNS名
proxy_pass http://nuxt-app:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
docker-compose.yml​
  • 增加了nginx服务
yml
# 使用 Docker Compose 的 v3 版本语法
version: '3'

# 定义服务
services:
# (服务名称) 定义nuxt-app服务
nuxt-app:
# 使用当前目录下的 Dockerfile 构建镜像
build: .
# 指定容器名为 my-nuxt,便于识别和管理
container_name: my-nuxt
# 将宿主机的 3000 端口映射到容器的 3000 端口。 (格式是 "本机端口:容器端口")
ports:
- "3000:3000"
# 设置环境变量 (Node.js运行环境变量 => production => 启用压缩、缓存、关闭热更新、提高性能)
environment:
- NODE_ENV=production
# 挂载日志目录, 实现日志持久化 (格式是 "本机目录:容器目录")
volumes:
- ./logs:/app/logs
# 设置重启策略
restart: always
# 设置网络
networks:
- app-network

nginx:
image: nginx:alpine
container_name: my-nginx
ports:
- "80:80" # 宿主机80端口映射到nginx
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- nuxt-app
networks:
- app-network

# 定义网络
networks:
# 定义网络名称为 app-network
app-network:
driver: bridge

配置nginx资源路径映射​

在 Nginx 中,root 和 alias 都可以用于静态资源的路径映射

  • 当访问其他资源的时候,通过nginx可以转发指向到指定的目录
  • 1、访问http://127.0.0.1/demo.txt 转发到访问容器内的其他目录
  • 2、挂载静态文件到 Nginx 容器
    • 在 docker-compose.yml 的 nginx 服务下添加volumes卷
    • 把本地(服务器)上的目录资源挂载到容器指定的目录中
  • 3、当挂载后,nginx.conf 的 alias、root转发配置才会生效

检查nginx容器,是否有挂载的文件

bash
# 进入nginx容器终端
docker exec -it my-nginx sh
# app/static是挂载的目录
ls /app/static/

每次修改nginx的配置,都需要重启nginx容器

bash
docker restart my-nginx
nginx.conf​
  • 配置转发
  • 使用root或者alias来配置目录的指向
  • 使用$uri来匹配请求的路径,如127.0.0.1/demo.html, 则请求的路径为 /demo.html
bash
# 必须块。虽然这里没有配置内容,但 Nginx 要求必须有 events 块。
events {}

# http:开启 HTTP 服务配置
http {
server {
listen 80;

# 代理转发(具体某文件目录) 当访问127.0.0.1/demo.txt 时,会代理转发到 /app/static/demo.txt
location = /demo.txt {
alias /app/static/demo.txt;
}

# 代理转发(匹配更多文件,如以html后缀结尾的文件) $uri 是 Nginx 的内置变量,代表当前请求的 URI 路径
location ~ \.html$ {
alias /app/static$uri;
}

location / {
# nuxt-app 是 Docker Compose 中定义的服务名,相当于容器内的DNS名
proxy_pass http://nuxt-app:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}

}
}
docker-compose.yaml​
  • 核心nginx服务的volumes目录挂载配置
  • 把本地服务器的目录挂载到nginx容器目录中
yaml
# 使用 Docker Compose 的 v3 版本语法
version: '3'

# 定义服务
services:
# (服务名称) 定义nuxt-app服务
nuxt-app:
# 使用当前目录下的 Dockerfile 构建镜像
build: .
# 指定容器名为 my-nuxt,便于识别和管理
container_name: my-nuxt
# 将宿主机的 3000 端口映射到容器的 3000 端口。 (格式是 "本机端口:容器端口")
ports:
- "3000:3000"
# 设置环境变量 (Node.js运行环境变量 => production => 启用压缩、缓存、关闭热更新、提高性能)
environment:
- NODE_ENV=production
# 挂载日志目录, 实现日志持久化 (格式是 "本机目录:容器目录")
volumes:
- ./logs:/app/logs
# 设置重启策略
restart: always
# 设置网络
networks:
- app-network

nginx:
image: nginx:alpine
container_name: my-nginx
ports:
- "80:80" # 宿主机80端口映射到nginx
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
# 本地路径 d:/a-frontEnd/my-test/static
# 挂载目录 d:/a-frontEnd/my-test/static 到容器内 /app/static
- /d/a-frontEnd/my-test/static:/app/static
depends_on:
- nuxt-app
networks:
- app-network

# 定义网络
networks:
# 定义网络名称为 app-network
app-network:
driver: bridge

SPA应用​

  • Dockerfile + nginx