0

NAS中 Docker Compose 的进阶玩法

Share
  • 2 11 月, 2025

熟悉我的友友都知道我经常折腾NAS,而我属于也在NAS部署了很多自托管的服务,这其中Docker是必不可少的。不同的NAS系统针对Docker有不同的解决方案,而Docker Compose是目前适用性最广泛额一个。

标签说明

Docker Compose 配置文件是 YAML 格式的,通常是 docker-compose.yml 或 compose.yaml 文件。顶级标签定义了整个应用的服务、网络、存储卷等配置。以下是 Docker Compose 配置文件中常见且重要的顶级标签名称及其功能列表。这个列表是基于 Compose 规范(Compose Specification)的,它取代了旧版本的 v2 和 v3 格式,是现阶段推荐和广泛使用的标准。

version (已废弃)(在较新的 Compose 规范中已不推荐使用) 在旧的 Compose 文件格式(v2 和 v3)中用于指定配置文件版本。现在使用 Compose 规范时,此字段通常被省略或仅用于向后兼容。旧版本
services定义应用中的所有服务。 每个服务条目(如您提到的 imagecontainer_name 等)都作为这个键下的子配置。这是 Compose 文件的核心部分。必选
volumes定义命名存储卷(Named Volumes)。 这些存储卷可以在不同的服务之间共享,并且独立于容器的生命周期。可选
networks定义自定义网络。 允许服务连接到特定的网络,以便相互通信或与外部网络通信。可选
configs定义配置数据(Config Data)。 允许服务访问敏感或非敏感的配置数据,通常用于应用配置。可选
secrets定义敏感数据(Secrets)。 允许服务安全地访问敏感信息,如密码或 API 密钥。可选
include包含其他 Compose 文件。 允许将配置拆分为多个文件,便于管理和复用。可选
name指定项目名称。 用于覆盖目录名称作为项目名称的默认行为。可选

这些顶级标签中,服务标签(services) 是构建容器必不可少的,在其下也有很多常用的子标签。

image指定构建容器所使用的镜像。 可以是 Docker Hub 上的公共镜像,也可以是私有仓库或本地镜像。
build定义如何构建镜像。 如果不使用现有的 image,则用此指定 Dockerfile 路径和构建上下文。
container_name为容器指定一个固定的名称。 默认情况下 Compose 会生成一个名称(如 projectname-servicename-1)。
ports发布容器的端口到主机。 格式通常是 主机端口:容器端口
volumes挂载存储卷或主机路径到容器。 用于数据持久化或共享主机文件。格式可以是 主机路径:容器路径卷名称:容器路径
environment设置容器中的环境变量。 可以是键值对列表或文件引用。
env_file从文件中添加环境变量。
networks指定服务应连接到哪些网络。
depends_on定义服务之间的依赖关系。 确保依赖的服务在当前服务启动前启动。
restart定义容器退出时的重启策略。 例如 always, on-failure, unless-stopped
command覆盖容器启动时执行的默认命令。
entrypoint覆盖容器的默认入口点。
labels添加自定义元数据(标签)到容器。
healthcheck定义一个检查容器健康状态的命令。
logging配置服务的日志驱动和选项。
deploy指定部署和运行时约束(主要用于 Swarm 模式)。

样例

为了方便理解,我用两个样例来做说明。我会在每个标签旁边使用 # 符号添加注释(说明)。

以下这个示例展示了通过单个容器配置一个独立的 Web 服务器容器(使用 Nginx 镜像)的方案。

# Compose 文件的顶级配置键(标签)

# 推荐在新的 Compose 文件中省略 'version' 键,以遵循最新的 Compose 规范。
# 如果需要向后兼容,可以添加如下(但不再推荐):
# version: '3.8'

# 核心标签:定义应用中的所有服务
services:
  # 服务名称:可以是任何你想要的名字,它作为网络别名
  web_server:
    # 服务子标签:

    # 指定构建容器所使用的镜像
    image: nginx:latest

    # 为容器指定一个固定的名称
    container_name: my_single_nginx_container

    # 挂载存储卷或主机路径到容器
    # 格式:[主机路径或卷名称]:[容器内部路径]
    volumes:
      # 挂载本地的 ./html 目录到容器的 Nginx 默认网页目录
      - ./html:/usr/share/nginx/html:ro

    # 发布容器的端口到主机
    # 格式:[主机端口]:[容器端口]
    ports:
      # 将容器的 80 端口映射到主机的 8080 端口
      - "8080:80"

    # 设置容器中的环境变量
    environment:
      # 这是一个示例环境变量
      - TIMEZONE=Asia/Shanghai

    # 定义容器退出时的重启策略
    # 'unless-stopped' 表示除非手动停止,否则容器退出时都会重启
    restart: unless-stopped

    # 添加自定义元数据(标签)到容器
    labels:
      - "com.example.description=Single Nginx Web Server"

# 顶级标签:定义命名存储卷(如果需要)
# 在这个单容器示例中,我们使用了主机挂载,所以 volumes 标签可以省略。
# volumes:
#   my_data:

# 顶级标签:定义自定义网络(如果需要)
# 在这个单容器示例中,Compose 会使用默认的 bridge 网络。
# networks:
#   default:
#     driver: bridge

这个示例则是通过多个容器配置一个 Web 应用程序(使用 Node.js 示例)和一个数据库(使用 PostgreSQL),并配置它们之间的依赖和通信的方案。

# Compose 文件的顶级配置键(标签)

# 核心标签:定义应用中的所有服务
services:
  # 服务一:Web 应用程序
  app_service:
    # 服务子标签:

    # 指定如何构建镜像(从 Dockerfile 构建)
    # 'context' 指定 Dockerfile 所在的目录,'dockerfile' 指定 Dockerfile 文件名
    build:
      context: .
      dockerfile: Dockerfile.app

    # 为容器指定一个固定的名称
    container_name: web_app_container

    # 发布容器的端口到主机
    # 将容器的 3000 端口映射到主机的 3000 端口
    ports:
      - "3000:3000"

    # 设置容器中的环境变量
    environment:
      # 连接数据库所需的环境变量
      - DB_HOST=db_service  # 使用服务名称作为主机名进行连接
      - DB_PORT=5432
      - DB_USER=user
      - DB_PASSWORD=secret

    # 定义服务之间的依赖关系
    # 确保 db_service 容器启动并运行后才启动 app_service
    depends_on:
      db_service:
        condition: service_started

    # 指定服务应连接到哪些网络
    networks:
      - internal_network
      - public_network

  # 服务二:数据库服务
  db_service:
    # 服务子标签:

    # 指定使用的数据库镜像
    image: postgres:14-alpine

    # 为容器指定一个固定的名称
    container_name: postgres_db_container

    # 挂载存储卷到容器
    volumes:
      # 使用命名存储卷进行数据持久化,确保数据在容器重启后不会丢失
      - postgres_data:/var/lib/postgresql/data

    # 从文件中添加环境变量(更安全的方式来管理密码)
    # 假设存在一个名为 .env.db 的文件,包含 POSTGRES_USER 等变量
    env_file:
      - .env.db

    # 定义容器退出时的重启策略
    restart: always

    # 指定服务应连接到哪些网络
    # 注意:数据库服务通常不直接暴露到公网,只连接内部网络
    networks:
      - internal_network

# 顶级标签:定义命名存储卷
volumes:
  # 定义一个名为 'postgres_data' 的卷
  postgres_data:
    # 可以指定驱动和选项,这里使用默认驱动
    driver: local

# 顶级标签:定义自定义网络
networks:
  # 定义一个内部使用的网络,供 app 和 db 通信
  internal_network:
    driver: bridge
  # 定义一个可能需要对外连接的网络
  public_network:
    driver: bridge

NAS中使用

目前来说各个主流的NAS系统都支持Docker Compose,根据自己的需要找到对应项目的Docker Compose,复制粘贴到NAS中的Docker Compose,并根据自己的具体情况编辑一下中即可。

需要特别说明的是在自己的NAS中使用时,修改Docker Compose文件中的路径。前文中提到的 挂载标签volumes变量文件env_file 标签都会涉及到路径设置。大部分NAS系统在添加Docker Compose时都需要设置路径,这个路径就是容器项目在NAS中储存文件的位置。

在Docker Compose文件中,每个标签下的项目用“:”来分割,第一个冒号前的是映射的宿主机端口或地址,第一个冒号后则是容器内的端口或地址,第二个冒号后则是读写权限等设置项。

根据不同的开发者编辑代码习惯不同,映射挂载地址时,有的开发者会写绝对地址,有的则是相对地址,以上面的样例参考:

绝对地址:/volume1/docker/Test/html

相对地址:./html

上面的例子中, html 文件夹是映射挂载的文件夹,前面的“ ./ ”则表示 html 这个文件夹是在 /docker/Test 目录下的。我个人是偏好使用相对路径的,如果容器或docker目录发生位置调整时,不会使容器因目录失联而失效。

另一个就是端口,上面的例子中,是将容器中的80端口映射到宿主机的8080端口上,如果在NAS中有多的Docker容器运行,一定要注意哪些端口已经被占用了,避免在不同的容器中映射了同样的端口,这样也会导致容器无效。