【docker】docker-compose.yml 语法详解

文章目录

前面讲过Docker Compose的概念,如何安装、以及常用指令等。

这里重点介绍Docker Compose的语法,如何写一个正确的docker-compose.yml文件。

我们知道docker-compose指令(比如docker-compose up等)是运行它的脚本文件docker-compose.yml,那么docker-compose.yml内部到底有哪些语法要求呢!

一、相关文章

二、基本概念

docker-compose.yml文件是Docker Compose的核心,用于定义服务、网络和数据卷。

该文件使用YAML格式编写,其默认路径为./docker-compose.yml,可以使用.yml.yaml作为文件扩展名。在docker-compose.yml文件中,可以定义多个服务,每个服务可以包含一系列配置选项,例如镜像名称、容器端口、环境变量等。

此外,docker-compose.yml文件还可以定义网络和数据卷,以便在多个容器之间共享网络和数据。网络可以设置为公共或私有,数据卷可以设置为持久化或非持久化。

使用Docker Compose的基本步骤如下:

  1. 使用Dockerfile定义应用程序的环境。
  2. 使用docker-compose.yml定义组成应用程序的服务。
  3. 运行docker-compose up命令启动并运行应用程序。

三、Docker Compose语法介绍

Compose 文件是一个 YAML 文件,用于定义 Docker 应用程序的多个容器化服务。这个文件通常用于定义服务、网络、卷、配置和秘密等。

docker-compose.yml文件有以下6个顶级元素:

  1. version (可选)
    • 描述:指定 Compose 文件的版本。这有助于确保 Compose 工具与您的文件格式兼容。
    • 用途:当工具或库进行更新时,版本号可以帮助确保您的 Compose 文件与新版本的工具或库兼容。
  2. services (必需)
    • 描述:定义应用程序的各个服务。每个服务是一个独立的 Docker 容器,包含运行应用程序所需的配置信息。
    • 用途:在 Compose 文件中,您可以为应用程序的不同部分定义多个服务。例如,一个 Web 服务器和一个数据库可以作为两个不同的服务来管理。
  3. networks (可选)
    • 描述:定义自定义网络,以便容器可以相互通信。
    • 用途:默认情况下,Compose 会为您的应用创建一个网络,但您也可以定义自己的网络,以便容器可以与外部世界或其他容器通信。
  4. volumes (可选)
    • 描述:定义数据卷,以便持久化存储数据或共享数据。
    • 用途:数据卷允许您在容器之间共享和持久化数据。这对于确保数据的一致性和持久性非常有用。
  5. configs (可选)
    • 描述:定义配置,这些配置可以在服务中使用,但不应该直接在 Compose 文件中硬编码。
    • 用途:这是一个相对较新的功能,允许您将敏感信息(如密码、API 密钥等)从 Compose 文件中移出,以增加安全性。这些配置可以在运行时注入到服务中。
  6. secrets (可选)
    • 描述:类似于 Configs,Secrets 也用于定义敏感信息,但它们是专为敏感数据设计的,并具有特定的管理功能。
    • 用途:Secrets 是专为存储敏感信息而设计的,例如密码、API 密钥等。它们可以与 Configs 结合使用,以提供更完整和安全的解决方案来管理敏感数据。

这些配置项使 Docker Compose 成为一个功能强大的工具,用于定义、部署和管理复杂的 Docker 应用程序。

1、version

version 指定Docker Compose文件的版本。目前最新的版本是3。

参考 https://docs.docker.com/compose/compose-file/04-version-and-name/

2、Services

参考 https://docs.docker.com/compose/compose-file/05-services/

services 定义各个服务。每个服务都有一个唯一的名称,并且需要指定使用的镜像、端口映射、环境变量等信息。并包含以下属性

image

指定服务所使用的Docker镜像。

yml 复制代码
image: redis
image: redis:5
image: redis@sha256:0ed5d5928d4737458944eb604cc8509e245c3e19d02ad83935398bc4b991aac7
image: library/redis
image: docker.io/library/redis
image: my_private.registry:5000/redis

build

参考 https://docs.docker.com/compose/compose-file/build/

指定Dockerfile的路径,用于构建自定义镜像。

build 选项可以接受不同的参数,其中最常用的是 contextdockerfile

以下是一些常见的使用方法:

1)指定构建上下文(context) :

构建上下文是一个目录,包含了用于构建镜像的所有文件。当使用 build 选项时,Docker 会将该目录下的所有文件和子目录复制到 Docker 守护进程中,并在那里构建镜像。

yaml 复制代码
services:
  myservice:
    build:
      context: .

在上面的例子中,当前目录(.)被用作构建上下文。这意味着 Docker 将复制当前目录下的所有文件和子目录到 Docker 守护进程中,并在那里构建镜像。

2)指定 Dockerfile:

dockerfile 参数用于指定 Dockerfile 的位置。Dockerfile 是一个文本文件,其中包含了一系列指令,用于定义如何构建 Docker 镜像。

yaml 复制代码
services:
  myservice:
    build:
      dockerfile: ./path/to/Dockerfile

在上面的例子中,Docker 将使用位于 ./path/to/Dockerfile 的 Dockerfile 来构建镜像。

3)使用 Dockerfile 和构建上下文:

当你同时指定 contextdockerfile 时,context 是 Dockerfile 的位置的相对路径。这允许你在同一个构建上下文中使用多个 Dockerfile。

yaml 复制代码
services:
  myservice:
    build:
      context: ./path/to/context
      dockerfile: ./path/to/Dockerfile

在上面的例子中,Docker 将使用位于 ./path/to/context/path/to/Dockerfile 的 Dockerfile 来构建镜像。

4)使用其他构建选项:

除了 contextdockerfile 外,build 选项还可以接受其他一些参数,例如 args(用于传递构建参数),target(用于指定 Dockerfile 中的目标),等等。这些参数可以根据需要进行配置。

args 定义构建参数,即 Dockerfile 中的 ARG 值。

以以下 Dockerfile 为例:

yml 复制代码
ARG GIT_COMMIT
RUN echo "Based on commit: $GIT_COMMIT"

在 Compose 文件的 build 键下,可以使用 args 来定义 GIT_COMMIT。args 可以作为 map 或 list 进行设置:

yml 复制代码
build:
  context: .
  args:
    GIT_COMMIT: cdc3b19
yml 复制代码
build:
  context: .
  args:
    - GIT_COMMIT=cdc3b19

在指定构建参数时,可以省略值。在这种情况下,构建时间必须通过用户交互获取其值,否则在构建 Docker 镜像时将无法设置构建参数。

yml 复制代码
args:
  - GIT_COMMIT

5)使用自定义名称:

你可以为构建的镜像指定一个自定义名称。默认情况下,镜像名称与服务的名称相同,但你可以通过设置 image 参数来覆盖默认名称。

yml 复制代码
services:
  frontend:
    image: example/webapp
    build: ./webapp

  backend:
    image: example/database
    build:
      context: backend
      dockerfile: ../backend.Dockerfile

  custom:
    build: ~/custom

ports

指定服务的端口映射。

ports 不能与 network_mode: host 一起使用,否则会出现运行时错误。

Docker Compose中的ports配置项有两种语法格式:短语法和长语法。

1)短语法,比较常见

复制代码
[HOST:]CONTAINER[/PROTOCOL]
  • HOST :[IP:](port | range)
  • CONTAINER: port | range
  • PROTOCOL:将端口限制为指定协议。如 TCP和UDP

如果主机IP未设置,它将绑定到所有网络接口。端口可以是单个值或范围。主机和容器必须使用等效的范围。

要么指定两个端口(HOST:CONTAINER),要么只指定容器端口。在后一种情况下,Compose会自动分配主机上的任何未分配端口。

HOST:CONTAINER应始终作为(带引号的)字符串指定,以避免与yaml基数-60浮点数发生冲突。

  • "3000":主机自动分配未被占用的端口。
  • "3000-3005":端口范围规则和上边相同。
  • "8000:8000":容器端口8000对应主机端口8000。
  • "9090-9091:8080-8081":端口范围规则和上边一天相同。
  • "6060:6060/udp":限制为指定的协议udp。
yml 复制代码
ports:  
  - "9200:9200"  
  - "9300:9300"  

2)长语法格式

长语法可以实现短语法无法实现的功能,配置项如下:

  • target:80:容器端口。
  • published:8080:物理主机的端口。
  • protocol: tcp:端口协议(tcp或udp)。
  • mode: host:host和ingress两种模式,host用于在每个节点上发布主机端口,ingress用于被负载平衡的swarm模式端口。
yml 复制代码
ports:  
  - target: 9200  
    published: 9200  
    protocol: tcp  
    mode: host  
  - target: 9300  
    published: 9300  
    protocol: tcp  
    mode: host  

networks

定义服务容器所连接的网络,关联到顶级networks的配置。

yml 复制代码
services:
  some-service:
    networks:
      - some-network
      - other-network

volumes

指定服务的卷挂载。

卷(volumes)定义了可由服务容器访问的主机路径或命名卷。您可以使用volumes来定义多种类型的挂载,如 volume, bind, tmpfs, 或 npipe。

如果挂载是主机路径并且仅由单个服务使用,则可以在服务定义中声明它。要在多个服务之间重复使用卷,必须在顶级 volumes 键中声明一个命名卷。

以下示例显示了由后端服务使用的命名卷(db-data),以及为单个服务定义的绑定挂载。

yml 复制代码
services:
  backend:
    image: example/backend
    volumes:
      - type: volume
        source: db-data
        target: /data
        volume:
          nocopy: true
      - type: bind
        source: /var/run/postgres/postgres.sock
        target: /var/run/postgres/postgres.sock

volumes:
  db-data:

1)短语法

使用单个字符串与冒号分隔的值来指定卷挂载(VOLUME:CONTAINER_PATH)或访问模式(VOLUME:CONTAINER_PATH:ACCESS_MODE)。

  • VOLUME:可以是容器所在平台上的主机路径(绑定挂载)或卷名称。
  • CONTAINER_PATH:卷在容器中挂载的路径。
  • ACCESS_MODE:逗号分隔的选项列表:
    • rw:读写访问。如果没有指定,则为默认值。
    • ro:只读访问。
    • z:SELinux选项,指示绑定挂载主机内容在多个容器之间共享。
    • Z:SELinux选项,指示绑定挂载主机内容对其他容器来说是私有的并且不共享。

2)长语法

长语法形式允许配置无法在短语法中表示的其他字段。

  • type:挂载类型。可以是 volume、bind、tmpfs、npipe 或 cluster。
  • source:挂载的源,对于绑定挂载是主机上的路径,或是在顶级 volumes 键中定义的卷的名称。不适用于 tmpfs 挂载。
  • target:容器中卷挂载的路径。
  • read_only:将卷设置为只读。
  • bind:用于配置其他绑定选项:
    • propagation:用于绑定的传播模式。
    • create_host_path:在主机上源路径处创建目录,如果路径不存在。如果路径存在,Compose 不会做任何操作。这是为了向后兼容 docker-compose 遗留版本而自动隐含的短语法。
    • selinux:SELinux 重新标记选项 z(共享)或 Z(私有)。
  • volume:配置其他卷选项:
    • nocopy:禁用在创建卷时从容器复制数据的标志。
  • tmpfs:配置其他 tmpfs 选项:
    • size:tmpfs 挂载的大小,以字节为单位(可以是数字或字节单位)。
    • mode:tmpfs 挂载的文件模式,作为 Unix 权限位作为八进制数。
  • consistency:挂载的一致性要求。可用的值是平台特定的。

environment

指定服务的环境变量。

1)Array 语法:

yml 复制代码
environment:
 - VAR1=value1
 - VAR2=value2

2)Map 语法

yml 复制代码
environment:
  RACK_ENV: development
  SHOW: "true"
  USER_INPUT:

deploy

定义服务的部署配置。可以设置副本数、更新策略等

参考 https://docs.docker.com/compose/compose-file/deploy/

replicas:设置副本数量,默认是1

yml 复制代码
services:
  frontend:
    image: example/webapp
    ports:
      - "8080:80"
    deploy:
      mode: replicated
      replicas: 2
      endpoint_mode: vip

depends_on

指定服务依赖的其他服务。

yml 复制代码
services:
  web:
    build: .
    ports:
      - "80:80"
    environment:
      - ENV=production

command

command 会覆盖容器镜像声明的默认 command ,例如通过Dockerfile的CMD。

yml 复制代码
command: bundle exec thin -p 3000

该值也可以是列表,与Dockerfile类似:

yml 复制代码
command: [ "bundle", "exec", "thin", "-p", "3000" ]

如果值为null,则使用镜像中的默认命令。

如果值为[](空列表)或''(空字符串),则忽略镜像声明的默认命令,即将其覆盖为空。

restart

定义服务的重启策略。可以设置为"no"、"always"、"on-failure"或"unless-stopped"。

yml 复制代码
restart: "no"
restart: always
restart: on-failure
restart: unless-stopped

3、networks 使用

networks 定义应用程序使用的网络。可以通过网络名称将不同的服务连接在一起。

Docker Compose Networks 可以不预先创建好网络,默认情况下,这个网络的名字是 "<project_name>_default"。如果 Compose 文件位于名为 "my_project" 的目录中,那么默认网络名称将是 "my_project_default"。

详细参考 https://docs.docker.com/compose/compose-file/06-networks/

以下是使用 Docker Compose Networks 的基本步骤:

1、使用已有网络

1)创建网络:在开始使用现有网络之前,需要先创建一个 Docker 网络。可以使用以下命令来创建一个网络:

复制代码
docker network create <network-name>

2)编写 Docker Compose 文件:接下来,需要编写一个 Docker Compose 文件,来定义服务和网络。在 Compose 文件中,可以定义一个或多个服务,每个服务都可以连接到同一个网络。以下是一个示例的 docker-compose.yml 文件:

yaml 复制代码
version: '3'
services:
  web:
    image: nginx
    networks:
      - my-network
  db:
    image: mysql
    networks:
      - my-network
networks:
  my-network:
    external: true

在上述示例中,定义了两个服务,web 和 db。这两个服务都使用同一个网络 my-network。请注意,在 networks 部分,使用了 external: true,表示使用的是现有的外部网络。

2、自动创建网络

不指定external: true,在容器启动的时候,会自动创建网络 "<project_name>_my-network"

yml 复制代码
version: '3'  
services:  
  web:  
    image: nginx:latest  
    ports:  
      - "80:80"  
    networks:  
      - my-network  
  db:  
    image: mysql:latest  
    ports:  
      - "3306:3306"  
    networks:  
      - my-network  
networks:  
  my-network:  
    driver: bridge

在上面的示例中,创建了一个名为my-network的自定义网络,并将web和db服务连接到该网络。使用driver参数可以指定网络的驱动程序,默认为bridge。

docker 网络驱动类型

Docker的网络驱动程序有bridge、host、overlay、macvlan等几种,每种驱动程序都有其特点和应用场景。

  1. bridge(桥接模式):这是Docker默认的网络模式,它将每个容器都连接到本机主机的独立网络中,实现容器之间的网络隔离。Docker创建了一个桥接网络,并为每个容器分配了一个IP地址。容器可以互相通信,也可以与宿主机通信,但不能直接访问其他网络。
  2. host(主机模式):在这种模式下,容器将直接使用宿主机的网络命名空间,因此容器将拥有与宿主机相同的IP地址和端口号。容器可以与宿主机和其他容器通信,但它们之间的通信不受Docker的网络隔离和安全限制。
  3. overlay(覆盖网络模式):这是一种跨主机网络的网络驱动程序,它将多个主机上的容器连接到同一个网络中,并提供了跨主机的容器间通信的能力。它使用VxLAN技术来实现跨主机网络的通信。
  4. macvlan(MACvlan网络模式):这是一种基于MAC地址的容器网络模式,它将每个容器的网络接口绑定到一个MAC地址上,实现了容器之间的网络隔离。这种模式下,每个容器都会分配一个独立的IP地址,并且可以与其他容器进行通信。

每种网络驱动程序都有其适用的场景,可以根据具体的需求选择不同的网络驱动程序来实现不同的容器网络配置。

4、volumes 使用

volumes 定义应用程序的卷。可以创建卷,并将其挂载到服务中。

Docker Compose 中使用数据卷(Volumes)可以通过 volumes 关键字在服务定义中进行指定。

详细参考:https://docs.docker.com/compose/compose-file/07-volumes/

具体用法如下:

docker-compose.yml 文件中,针对要使用数据卷的服务,添加 volumes 配置块。例如:

yaml 复制代码
version: "3"
services:
  web:
    image: nginx
    volumes:
      - ./app:/app

在上面的示例中,我们定义了一个名为 web 的服务,使用 image 关键字指定了镜像 nginx。然后通过 volumes 关键字将宿主机目录 ./app 挂载到容器内的 /app 目录上。

另外,如果需要在服务中定义卷标(Volume),可以使用 - 开头的短横线表示卷标名称。例如:

yaml 复制代码
version: "3"
services:
  web:
    image: nginx
    volumes:
      - data:/var/lib/nginx
volumes:
  data:

在上面的示例中,我们定义了一个名为 data 的卷标,并将其挂载到容器内的 /var/lib/nginx 目录上。这样,容器内的 /var/lib/nginx 目录将持久化存储在名为 data 的卷标中。

四、和环境变量文件.env结合使用

环境变量文件 .env 用于定义应用程序所需的环境变量。这些环境变量可以在 docker-compose.yml 文件中引用,以配置容器的行为。

默认情况下,.env文件必须和 docker-compose.yml文件在同一个目录中。也可以使用env_file指定文件。

复制代码
env_file: .env

将 Docker Compose 和环境变量文件 .env 结合使用,可以让你更方便地管理和配置应用程序的环境。以下是一些步骤,说明如何结合使用这两个工具:

  1. 创建 .env 文件,在其中定义你的环境变量。每个变量一行一个,例如:
makefile 复制代码
DATABASE_URL=postgres://user:password@localhost/dbname
SECRET_KEY=my-secret-key
  1. 创建 docker-compose.yml 文件,并在其中引用 .env 文件中的环境变量。例如:
yaml 复制代码
version: '3'
services:
  web:
    image: my-web-app
    ports:
      - "8080:80"
    environment:
      - DATABASE_URL=${DATABASE_URL}
      - SECRET_KEY=${SECRET_KEY}

在上面的示例中,${DATABASE_URL}${SECRET_KEY} 是对 .env 文件中定义的变量的引用。Docker Compose 会自动将这些值填充到容器的环境变量中。

  1. 在命令行中运行 docker-compose up 命令来启动应用程序。Docker Compose 将读取 docker-compose.yml 文件,并使用 .env 文件中定义的环境变量来配置各个容器。
  2. 如果需要修改环境变量,只需编辑 .env 文件,然后重新运行 docker-compose up 命令即可。Docker Compose 将自动加载最新的环境变量值。

通过这种方式,你可以轻松地管理和配置应用程序的环境,同时利用 Docker Compose 的功能来简化容器化应用程序的部署和管理。

五、使用示例

1、基本使用

以下是一个简单的 docker-compose.yml 示例,它创建并运行一个基于 Nginx 的 web 服务器和一个基于 Redis 的数据库:

yaml 复制代码
version: '3'
services:
  web:
    image: nginx:alpine
    ports:
      - "8080:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
    networks:
      - app-net
    command: ["nginx", "-g", "daemon off;"]
  redis:
    image: redis:latest
    networks:
      - app-net
    command: ["redis-server"]
networks:
  app-net:

这个 docker-compose.yml 文件定义了两个服务:web 和 redis。每个服务都有自己的配置。

  • web 服务使用 nginx:alpine 镜像,这是 Nginx 的一个轻量级版本。它将容器的 80 端口映射到主机的 8080 端口。它还将当前目录下的 nginx.conf 文件挂载到容器的 /etc/nginx/nginx.conf,这样我们就可以在主机上修改 Nginx 的配置。最后,它使用 daemon off; 命令来确保 Nginx 在容器退出时停止运行。
  • redis 服务使用最新的 Redis 镜像。它连接到名为 app-net 的网络,并使用 redis-server 命令启动 Redis。
  • app-net 网络允许这两个服务相互通信。

你可以根据需要修改这个文件来适应你的应用和环境。例如,你可能需要安装不同的软件或挂载不同的卷,这都可以在服务配置中完成。

2、结合Springboot项目使用

以下是一个基于 Spring Boot 项目的 docker-compose.yml 示例:

yaml 复制代码
version: '3'
services:
  backend:
    build:
      context: ./backend/
      dockerfile: Dockerfile
    image: backend:latest
    ports:
      - "8080:8080"
    networks:
      - app-net
    environment:
      - spring-boot-app-port=8080
  frontend:
    image: frontend:latest
    networks:
      - app-net
    ports:
      - "80:80"
    environment:
      - FRONTEND_URL=http://backend:8080/
networks:
  app-net:

这个 docker-compose.yml 文件定义了两个服务:后端(backend)和前端(frontend)。

  • backend 服务使用 Dockerfile./backend/ 目录下构建镜像。这个 Dockerfile 应该包含构建 Spring Boot 应用程序所需的步骤。构建完成后,该服务将容器的 8080 端口映射到主机的 8080 端口,并连接到名为 app-net 的网络。它还设置了 spring-boot-app-port 环境变量,用于指定 Spring Boot 应用程序监听的端口。
  • frontend 服务直接使用名为 frontend:latest 的镜像。该服务连接到 app-net 网络,并将容器的 80 端口映射到主机的 80 端口。它还设置了 FRONTEND_URL 环境变量,用于指定前端应用程序与后端服务的通信地址。
  • app-net 网络允许这两个服务相互通信。

请注意,你需要根据你的项目结构和需求进行相应的修改。例如,你可能需要修改端口映射、环境变量或网络配置。此外,你还需要确保你的 Spring Boot 项目已经正确配置并能够运行。

参考

相关推荐
川石教育3 小时前
测试工程师如何学会Kubernetes(k8s)容器知识
云原生·容器·kubernetes·kubernetes容器·kubernetes教程
THMAIL5 小时前
mac M芯片运行docker-desktop异常问题
macos·docker·容器
两点王爷6 小时前
IDEA中springboot项目中连接docker
spring boot·docker·intellij-idea
家庭云计算专家6 小时前
还没用过智能文档编辑器吗?带有AI插件的ONLYOFFICE介绍
服务器·人工智能·docker·容器·编辑器
云手机管家8 小时前
CDN加速对云手机延迟的影响
运维·服务器·网络·容器·智能手机·矩阵·自动化
孤的心了不冷9 小时前
【Docker】CentOS 8.2 安装Docker教程
linux·运维·docker·容器·eureka·centos
头疼的程序员10 小时前
docker学习与使用(概念、镜像、容器、数据卷、dockerfile等)
学习·docker·容器
IT小郭.10 小时前
使用 Docker Desktop 安装 Neo4j 知识图谱
windows·python·sql·docker·知识图谱·database·neo4j
淡水猫.10 小时前
hbit资产收集工具Docker(笔记版)
运维·docker·容器
水淹萌龙15 小时前
k8s 中使用 Service 访问时NetworkPolicy不生效问题排查
云原生·容器·kubernetes