强曰为道

与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

第 3 章 · 基础语法:services、image、ports、volumes

第 3 章 · 基础语法

3.1 Compose 文件的基本结构

一个最小的 Compose 文件只需要一个 services 顶级键:

# compose.yaml(推荐文件名)
# 也可以是 docker-compose.yml 或 docker-compose.yaml

services:
  my-service:
    image: nginx:alpine

顶级键一览

顶级键必填说明
services定义应用的服务(容器)列表
networks自定义网络配置
volumes命名数据卷声明
configs配置对象(Swarm/独立)
secrets敏感信息声明

文件命名优先级

Compose 按以下顺序查找配置文件(找到第一个即停止):

  1. compose.yaml
  2. compose.yml
  3. docker-compose.yaml
  4. docker-compose.yml

💡 建议:新项目统一使用 compose.yaml,更简洁且是官方推荐。

多文件指定

# 指定自定义文件名
docker compose -f my-services.yaml up

# 多文件合并(后面的覆盖前面的)
docker compose -f compose.yaml -f compose.prod.yaml up

3.2 services 详解

services 是 Compose 的核心,每个键代表一个服务,对应一个或多个容器。

最小示例

services:
  web:
    image: nginx:alpine
    ports:
      - "8080:80"

服务名规则

规则示例
只能包含 a-zA-Z0-9_.-my-appweb_server
不能以数字开头1web
服务名即为容器的主机名容器内通过 web 访问同网络的其他服务

3.3 image 指令

指定服务使用的 Docker 镜像。

格式

services:
  app:
    image: <repository>[:<tag>][@<digest>]

示例

services:
  # 标准格式 - 仓库:标签
  web:
    image: nginx:1.27-alpine

  # 使用摘要锁定版本(不可变)
  db:
    image: postgres:16-alpine@sha256:abc123def456...

  # Docker Hub 官方镜像(省略仓库地址)
  cache:
    image: redis:7

  # 第三方镜像(完整路径)
  monitoring:
    image: grafana/grafana:11.0.0

  # 私有仓库镜像
  private-app:
    image: registry.example.com/myapp:latest

  # 本地构建的镜像(与 build 指令配合)
  backend:
    build: ./backend
    # 构建后镜像名自动为 <project>-backend

镜像标签最佳实践

做法推荐原因
image: nginx:latest每次拉取可能不同,不可复现
image: nginx:1.27⚠️次版本更新可能破坏兼容
image: nginx:1.27.0-alpine精确版本 + 轻量基础
image: nginx@sha256:...✅✅最安全,完全不可变

3.4 ports 端口映射

将容器内部端口暴露到宿主机。

格式

services:
  web:
    ports:
      - "HOST_PORT:CONTAINER_PORT"        # 短语法
      - target: 80                        # 长语法
        published: "8080"
        protocol: tcp
        host_ip: 127.0.0.1

短语法详解

services:
  web:
    ports:
      # 宿主机 8080 → 容器 80
      - "8080:80"

      # 仅暴露端口,宿主机随机分配
      - "80"

      # 指定协议
      - "53:53/udp"
      - "53:53/tcp"

      # 指定绑定地址(仅本地访问)
      - "127.0.0.1:8080:80"

      # 端口范围
      - "9090-9091:8080-8081"

      # 混合使用
      - "3000"
      - "8080:80"
      - "127.0.0.1:5432:5432"

长语法详解

services:
  web:
    ports:
      - target: 80           # 容器端口
        published: "8080"    # 宿主机端口(引号可选)
        protocol: tcp        # tcp 或 udp
        host_ip: 127.0.0.1   # 绑定地址,默认 0.0.0.0
        app_protocol: http   # 应用协议(Compose V2.20+)

      # 仅容器端口,不发布到宿主机
      - target: 9090
        published: false

端口映射对照表

写法宿主机绑定宿主机端口容器端口
"8080:80"0.0.0.0808080
"127.0.0.1:8080:80"127.0.0.1808080
"80"0.0.0.0随机80
"80/tcp"0.0.0.08080 (TCP)
published: false不发布80

⚠️ 安全提示:端口映射到 0.0.0.0 意味着所有网络接口都可访问。生产环境建议绑定到 127.0.0.1 或使用防火墙。


3.5 volumes 数据卷

数据卷用于持久化数据共享文件

三种挂载方式

services:
  db:
    volumes:
      # 1. Named Volume(命名卷)— 推荐用于持久数据
      - pgdata:/var/lib/postgresql/data

      # 2. Bind Mount(绑定挂载)— 用于开发时同步代码
      - ./src:/app/src

      # 3. tmpfs Mount(内存挂载)— 用于临时数据
      - type: tmpfs
        target: /tmp/cache
        tmpfs:
          size: 100000000    # 100MB

短语法详解

services:
  app:
    volumes:
      # 命名卷
      - mydata:/data

      # 绑定挂载 — 只读
      - ./config/app.conf:/etc/app/app.conf:ro

      # 绑定挂载 — 读写(默认)
      - ./logs:/var/log/app

      # 命名卷 + 指定容器内路径
      - uploads:/var/www/uploads

长语法详解

services:
  app:
    volumes:
      - type: volume           # 命名卷
        source: mydata
        target: /data

      - type: bind             # 绑定挂载
        source: ./config
        target: /etc/app
        read_only: true

      - type: tmpfs            # 内存挂载
        target: /tmp
        tmpfs:
          size: 104857600      # 100MB

顶级 volumes 声明

使用命名卷时,必须在顶级 volumes 中声明:

services:
  db:
    image: postgres:16
    volumes:
      - pgdata:/var/lib/postgresql/data

volumes:
  pgdata:    # 声明命名卷
    # 可选配置
    name: my_project_pgdata   # 自定义卷名(覆盖默认命名)
    external: false           # 是否为外部卷

卷命名规则

如果不指定 name 属性,命名卷的全名格式为 <项目名>_<卷名>

# 项目目录名为 myapp
# 卷名 pgdata → 实际卷名 myapp_pgdata

# 查看卷
docker volume ls

# 查看卷详情
docker volume inspect myapp_pgdata

💡 建议:生产环境显式指定卷名(name 属性),避免因项目目录名变化导致卷名不一致。


3.6 完整示例:LAMP 环境

将以上概念组合,搭建一个经典的 LAMP(Linux + Apache + MySQL + PHP)环境:

# compose.yaml
services:
  # Apache + PHP
  web:
    image: php:8.3-apache
    ports:
      - "8080:80"
    volumes:
      - ./www:/var/www/html:ro    # 挂载网站代码
    depends_on:
      - db

  # MySQL 数据库
  db:
    image: mysql:8.0
    ports:
      - "127.0.0.1:3306:3306"    # 仅本地访问
    volumes:
      - mysql_data:/var/lib/mysql
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro
    environment:
      MYSQL_ROOT_PASSWORD: rootpass
      MYSQL_DATABASE: myapp
      MYSQL_USER: appuser
      MYSQL_PASSWORD: apppass

  # phpMyAdmin
  adminer:
    image: adminer:latest
    ports:
      - "8081:8080"
    depends_on:
      - db

volumes:
  mysql_data:

使用流程

# 创建项目结构
mkdir lamp-demo && cd lamp-demo
mkdir www

# 创建测试页面
cat > www/index.php << 'EOF'
<?php
echo "<h1>Docker Compose LAMP Demo</h1>";
echo "<p>PHP Version: " . phpversion() . "</p>";

try {
    $pdo = new PDO('mysql:host=db;dbname=myapp', 'apppass', 'apppass');
    echo "<p>✅ MySQL 连接成功</p>";
} catch (PDOException $e) {
    echo "<p>❌ MySQL 连接失败: " . $e->getMessage() . "</p>";
}
?>
EOF

# 启动
docker compose up -d

# 查看状态
docker compose ps

# 查看日志
docker compose logs -f web

# 浏览器访问 http://localhost:8080

3.7 常用管理命令

生命周期命令

# 启动所有服务(前台,Ctrl+C 停止)
docker compose up

# 启动所有服务(后台)
docker compose up -d

# 停止并删除容器、网络
docker compose down

# 停止并删除容器、网络 + 数据卷
docker compose down -v

# 停止并删除容器、网络 + 本地镜像
docker compose down --rmi local

# 重启服务
docker compose restart
docker compose restart web    # 重启指定服务

# 停止服务(不删除容器)
docker compose stop

# 启动已停止的服务
docker compose start

# 暂停/恢复服务
docker compose pause
docker compose unpause

查看状态

# 查看运行中的服务
docker compose ps

# 查看所有服务(含已停止的)
docker compose ps -a

# 查看资源使用情况
docker compose top

# 查看日志
docker compose logs
docker compose logs -f            # 实时跟踪
docker compose logs -f web        # 跟踪指定服务
docker compose logs --tail 50     # 最后 50 行
docker compose logs -f --since 5m # 最近 5 分钟

执行命令

# 在运行中的容器内执行命令
docker compose exec web bash
docker compose exec db mysql -uroot -prootpass

# 执行一次性命令(创建新容器)
docker compose run --rm web python manage.py migrate
docker compose run --rm web npm test

镜像管理

# 拉取所有服务的镜像
docker compose pull

# 构建所有服务的镜像
docker compose build

# 拉取 + 构建 + 启动
docker compose up -d --build

# 查看服务配置(解析后的 YAML)
docker compose config

# 查看镜像
docker compose images

3.8 服务的生命周期状态

              docker compose up
                    │
    ┌───────────────▼───────────────┐
    │          Creating             │
    │    (创建容器、网络、卷)         │
    └───────────────┬───────────────┘
                    │
    ┌───────────────▼───────────────┐
    │          Starting             │
    │      (启动容器进程)            │
    └───────────────┬───────────────┘
                    │
    ┌───────────────▼───────────────┐
    │          Running              │
    │       (正常运行中)             │
    └───────┬───────────────┬───────┘
            │               │
      docker compose    容器退出
        stop/down           │
            │         ┌─────▼──────┐
    ┌───────▼──────┐  │   Exited   │
    │   Stopped    │  │  (已退出)    │
    └───────┬──────┘  └─────┬──────┘
            │               │
      docker compose   docker compose
        down               up
            │               │
    ┌───────▼──────┐        │
    │   Removed    │        │
    │  (已删除)     │   (重新创建)
    └──────────────┘

3.9 实战:快速搭建 WordPress

# compose.yaml — 一键部署 WordPress
services:
  wordpress:
    image: wordpress:6-php8.3-apache
    ports:
      - "8080:80"
    volumes:
      - wp_data:/var/www/html
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: wordpress_pass
      WORDPRESS_DB_NAME: wordpress
    restart: unless-stopped

  db:
    image: mysql:8.0
    volumes:
      - db_data:/var/lib/mysql
    environment:
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: wordpress_pass
      MYSQL_ROOT_PASSWORD: root_secret
    restart: unless-stopped

volumes:
  wp_data:
  db_data:
docker compose up -d
# 访问 http://localhost:8080 完成 WordPress 安装

3.10 小结

概念要点
servicesCompose 核心,每个服务对应一组容器
image指定镜像,建议使用精确版本标签
ports宿主机:容器 端口映射,生产环境注意绑定地址
volumes三种挂载方式,命名卷用于持久化,绑定挂载用于开发
管理命令up -d / down / logs -f / exec / ps

扩展阅读


上一章:第 2 章 · 安装 ← | 下一章:第 4 章 · 网络 →