Docker Compose 中的项目名、服务名、容器名与数据卷名

前言

在同一台机器上跑多份 Compose 时

  • 项目名决定容器、网络、卷等资源的前缀是否冲突。
  • 服务名既是 compose.yaml 里的键,也常常作为默认网络上的 DNS 名称
  • 容器名docker ps 里看到的 宿主机维度的唯一名字,默认由 Compose 按 项目名 + 服务名 + 副本序号生成,也可用 container_name 写死。
  • 数据卷名若在文件里写的是「逻辑卷键」,运行时往往会带上项目前缀,除非你用了 外部卷name 固定全名。

项目名

默认值与优先级

Compose 会为本次编排计算一个 项目名(project name),用于拼接容器名、默认网络名、未显式命名的命名卷等。
常见优先级(由高到低)如下。

  1. 命令行 -p--project-name
  2. 环境变量 COMPOSE_PROJECT_NAME
  3. Compose 文件顶层的 name 字段(Docker Compose V2 开始支持)。
  4. 若以上皆无,则使用 Compose 文件所在目录的目录名

下面是一段仅用于说明「文件中声明项目名」的示例,把 myshop 换成你的工程名即可。

1
2
3
4
5
name: myshop

services:
web:
image: nginx:alpine

查看版本

1
docker-compose version

注意点

项目名里建议避免空格与特殊符号,使用和 DNS 标签兼容的 [a-z0-9_-] 一类字符更省事。
改项目名往往意味着一整套新前缀的网络与卷(除非卷用了 外部name),迁移数据前要核对 docker volume ls
同一项目名重复执行 docker compose up 会沿用同一前缀下的资源命名空间,适合做「这一套栈」的幂等拉起。

项目名建议直接在docker-compose.yml中设置,默认的容器名数据卷名都依赖项目名。

项目名如果没设置会默认使用所在的文件夹名。

服务名

设置

services: 下的 即为服务名,例如 webdb

1
2
3
4
5
services:
web:
image: nginx:alpine
db:
image: postgres:16-alpine

该键用于 docker compose up dbdocker compose exec web sh 等子命令的定位。

命名习惯与约束

服务名应视为 稳定的逻辑名称:与镜像名、运行态容器名区分开。
后者见下文 容器名 一节。
用户自定义网络上,同一网络内容器可用 服务名DNS 解析(例如在 web 里 ping db)。
具体行为以 Compose 为该网络配置的 aliasdepends_on 与网络模式为准。
建议使用 小写字母、数字、下划线或连字符,并避免与镜像仓库地址、端口等概念混淆。

容器名

默认命名

不显式写 container_name 时,容器名一般由 项目名、服务名、实例序号 依次拼接而成。
单实例时序号也常为 1
常见形式为 {项目名}-{服务名}-{序号}(例如 myshop-web-1)。

容器名不建议自己命名,如果要自己命名最好前面带上项目名,否则在查找容器的时候不好区分。

显式 container_name

需要 固定宿主机上的名字(例如给外部脚本、旧版编排或监控探针用)时,可在服务下写 container_name

1
2
3
4
services:
web:
image: nginx:alpine
container_name: myshop_nginx_edge

container_name 在整台 Docker 宿主机上必须 全局唯一;与别的 Compose 栈、手工 docker run --name 也不能撞名。
一旦写死 多副本deploy.replicas > 1scale)通常会 冲突不再被支持,因此 有状态单实例边缘代理这类场景更常见。
未写 container_name 时,Compose 仍可用 服务名在默认网络上做服务发现。
写了 container_name 并不等于把 DNS 查询名强行改成该字符串,别名仍以 Compose 网络配置为准。

与项目名、服务名的关系

项目名变更会牵动 默认容器名前缀,容易让日志与告警里的 旧名失效。

服务名是 Compose 子命令与 默认 DNS 的入口;容器名更多是 运维与排障视角的 实例标签

同一服务多次 up / recreate容器 ID会变,默认容器名往往仍遵循同一模式。

若依赖 固定容器名做自动化,优先评估是否应改成 标签网络别名编排级服务名

数据卷名

默认命名

volumes: 顶层下的 卷在项目内的逻辑名;挂载到服务里时使用 逻辑名:容器路径

1
2
3
4
5
6
7
8
services:
db:
image: postgres:16-alpine
volumes:
- pgdata:/var/lib/postgresql/data

volumes:
pgdata:

未指定 external、也未写 name,Docker 创建的 实际卷名通常是 ${项目名}_${逻辑卷键}(例如 myshop_pgdata)。
逻辑键仅在本 Compose 文件内用来引用这份卷。

显式命名

若你希望卷名 固定、且不随项目前缀变化,在该卷定义下使用 name

1
2
3
4
5
6
7
8
9
volumes:
pgdata:
name: corp_pg_prod_01

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

此时宿主上的卷名一般为 corp_pg_prod_01(与 name 一致),适合做 跨项目共用或与运维命名规范对齐。
改用 name 后要警惕:旧前缀卷若仍存在,会变成「新卷空目录」,看起来像数据丢失。

外部卷 external

卷已 docker volume create 或由别的栈创建时,应在 Compose 里声明 external: true,必要时用 name 指向真实卷名。

1
2
3
4
5
6
7
8
9
10
11
volumes:
legacy_data:
external: true
name: oldstack_mysql_data

services:
importer:
image: alpine:latest
volumes:
- legacy_data:/data:ro
command: ["sleep", "infinity"]

外部卷的 name 必须是 宿主已存在的卷名,否则 up 会报错。

bind mount 不算命名卷

形如 ./data:/app/data 的挂载是 bind mount,不产生 volumes: 顶层键意义上的「命名卷」。
匿名卷tmpfs 等也不与本节的「命名卷前缀」混在一起讨论。

命名建议

项目名建议指定名称。

服务名始终自己起简短稳定的名字。

其余交给默认容器名命名卷(不写卷级 name)用自动生成即可。

小结

项目名决定默认前缀:-pCOMPOSE_PROJECT_NAME 与文件 name 优先于目录名推断。
服务名是编排与 DNS(用户定义网络) 中的稳定键,应与 容器名、镜像名区分开。
容器名默认常含 项目名、服务名、序号container_name 可写死但须 全局唯一,且不利多副本。
命名卷未写 name 时多为 项目名_逻辑键;要写死全名或接外部卷则用 name / external
调整项目名、container_name 或卷 name 前,先在 docker ps -adocker volume lsdocker network ls 里核对,避免接上空白数据卷或名称冲突。