• docker-compose 中 depends_on 的作用


    depends_on 介绍

    在 Docker Compose 中,depends_on 是一个用于定义服务之间依赖关系的关键字。它允许您指定一个或多个服务依赖于其他服务,以确保在启动或重新创建容器时,所依赖的服务先于依赖它们的服务启动。

    以下是一些关于 depends_on 的详解:

    1. 启动顺序:通过在服务的配置中使用 depends_on,您可以告诉 Docker Compose 在启动容器时按照指定的顺序启动服务。例如,如果服务 A 依赖于服务 B 和服务 C,则在启动时,Docker Compose 会先启动服务 B 和服务 C,然后才会启动服务 A。
    2. 仅表示依赖关系:depends_on 只表示依赖关系,而不会等待依赖的服务完全可用。它只确保在依赖的服务启动后再启动当前服务。因此,依赖的服务可能仍在进行初始化或准备阶段,而不一定已经完全可用。如果需要等待服务完全可用,可以结合使用其他工具或技术,例如健康检查或等待脚本。
    3. 无法保证健康状态:depends_on 并不能保证依赖的服务在启动后处于健康状态。它只负责在启动时按照指定顺序启动服务,但并不检查服务的健康状态或等待服务变为可用状态。对于检查服务健康状态,可以使用其他机制,例如使用健康检查命令或工具。
    4. 并行启动:默认情况下,Docker Compose 会尽可能并行启动服务,而不是完全按照 depends_on 指定的依赖关系顺序启动。这是因为 Docker Compose 会尝试最大化容器的并发启动,以提高启动效率。如果需要强制按照依赖关系顺序启动,请使用 depends_on 结合 restart 关键字的 condition: ["service_started"] 选项。

    综上所述,depends_on 关键字允许您定义 Docker Compose 服务之间的依赖关系,但它并不能保证服务的可用性或健康状态。

    docker-compose.yml 样例文件

    version: '3'
    
    services:
      rabbitmq:
        hostname: rabbitmq_host
        container_name: 'mq'
        image: rabbitmq:3.9.11-management
        restart: always
        ports:
          - "5772:5672"  # AMQP
          - "15772:15672"  # Web UI
        networks:
          - app-network
        environment:
          RABBITMQ_DEFAULT_USER: root
          RABBITMQ_DEFAULT_PASS: pwd
          RABBITMQ_DEFAULT_VHOST: /
        volumes:
          - rabbitmq_data:/var/lib/rabbitmq/mnesia
    
        healthcheck:
          test: [ "CMD", "rabbitmq-diagnostics", "ping" ]
          interval: 50s
          timeout: 5s
          retries: 3
    
    
      selenium:
        container_name: 'selenium'
        image: selenium/standalone-chrome
        restart: always
        ports:
          - "4444:4444"
    
        networks:
          - app-network
    
        healthcheck:
          test: [ "CMD", "curl", "-f", "http://localhost:4444/wd/hub/status" ]
          interval: 30s
          timeout: 5s
          retries: 3
    
    
      db:
        container_name: 'mysql8'
        image: mysql:8.0.32
    #    hostname: mysql_host
        user: root
        command:
          --default-authentication-plugin=mysql_native_password
          --character-set-server=utf8mb4
          --collation-server=utf8mb4_unicode_ci
    
        environment:
          LANG: C.UTF-8
          MYSQL_ROOT_PASSWORD: pwd
          MYSQL_DATABASE: yinlian
    
        ports:
          - "3306:3306"
    
        volumes:
          - "./data/db/data:/var/lib/mysql"
          - "./data/db/mysql-files:/var/lib/mysql-files"
          - "./build/docker/mysqldb/my.cnf:/etc/my.cnf"
    
        networks:
          - app-network
    
        healthcheck:
          test: [ "CMD", "mysqladmin", "ping", "-h", "localhost" ]
          interval: 30s
          timeout: 5s
          retries: 3
    
      app-producer:
        container_name: 'producer'
        build:
          context: .
          dockerfile: Dockerfile
        ports:
          - "8001:8001"
    
        command: ['echo','hello world, Frank']
        depends_on:
          - db
          - rabbitmq
          - selenium
    
        networks:
          - app-network
    
    
    networks:
      app-network:
        driver: bridge
    
    volumes:
      rabbitmq_data:
        driver: local
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101

    上面的 文件中定义了 rabbitmq , db, selenium ,以及 app-producer , 其中 app-producer 服务 依赖于 其他三个服务, 这个时候如何进行配置呢?

    depends_on 只能保证启动的顺序.

    那么如何解决 保证 服务启动后,才启动app-producer 服务呢? 为此需要 使用长定义模式

    depends_on 有一个长定义模式

    Long syntax

    The long form syntax enables the configuration of additional fields that can’t be expressed in the short form.

    • restart: When set to true Compose restarts this service after it updates the dependency service. This applies to an explicit restart controlled by a Compose operation, and excludes automated restart by the container runtime after the container dies.
    • condition: Sets the condition under which dependency is considered satisfied
      • service_started: An equivalent of the short syntax described above
      • service_healthy: Specifies that a dependency is expected to be “healthy” (as indicated by healthcheck) before starting a dependent service.
      • service_completed_successfully: Specifies that a dependency is expected to run to successful completion before starting a dependent service.
    • required: When set to false Compose only warns you when the dependency service isn’t started or available. If it’s not defined the default value of required is true.

    condition 说明

    下面的文件中 我定义了一个web , db 服务, 此时 web 服务 启动就需要等待 db启动 并且成功后,才能启动.

    condition 的含义 service_healthy 做健康检查

    service_completed_successfully 表示 容器正常退出了, 之后 才进行启动.

    service_started 只保证启动顺序, 并不做任何检查.

    services:
      web:
        build: .
        depends_on:
          db:
            condition: service_healthy
    
      db:
        image: mysql:latest
        healthcheck:
          test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
          interval: 5s
          timeout: 3s
          retries: 3
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    service_completed_successfully 参数是长定义语法中的一个字段,用于指定依赖服务在成功完成后,才启动相关的服务。

    当将 service_completed_successfully 设置为 true 时,它表示依赖服务必须完全运行并成功完成(即退出状态码为 0),才能启动相关的服务。

    让我们通过一个示例来说明该参数的含义。假设我们有一个应用程序,其中包含一个 worker 服务和一个 db_migration 服务。我们希望在启动 worker 服务之前,先运行 db_migration 服务,并确保 db_migration 服务成功完成数据库迁移操作。

    使用长定义语法,我们可以将 depends_on 部分扩展为以下形式:

    services:
      worker:
        build: .
        depends_on:
          db_migration:
            condition: service_completed_successfully
    
      db_migration:
        build: .
        command: ./run_migration.sh
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在上述示例中,我们在 worker 服务的 depends_on 部分使用长定义语法来定义 db_migration 服务的依赖。通过将 condition 字段设置为 service_completed_successfully,我们指定了 worker 服务依赖于 db_migration 服务成功完成。

    当我们使用 Docker Compose 启动应用程序时,Compose 将先运行 db_migration 服务,并等待其成功完成(即退出状态码为 0)。一旦 db_migration 服务成功完成,Compose 将启动 worker 服务。

    通过使用 service_completed_successfully 参数,我们可以确保依赖服务在成功完成后,再启动相关的服务。这对于需要在依赖服务成功完成后才能进行后续操作的场景非常有用,如数据库迁移、初始化脚本等。

    service_started 这个只是表示启动顺序,并不能保证健康状态.

    service_healthyservice_completed_successfully 是长定义语法中用于定义依赖服务的两个不同条件。

    • service_healthy:这个条件要求依赖服务处于健康状态(由健康检查指定),才会启动相关的服务。通过设置 condition: service_healthy,Compose 将等待依赖服务的健康状态后再启动相关服务。健康状态通常是通过在容器中运行健康检查命令或脚本来确定的,例如检查 HTTP 响应或数据库连接等。
    • service_completed_successfully:这个条件要求依赖服务成功完成(即退出状态码为 0),才会启动相关的服务。通过设置 condition: service_completed_successfully,Compose 将等待依赖服务成功完成后再启动相关服务。这通常用于需要确保特定操作或任务在依赖服务完成后才能进行的情况,例如数据库迁移、初始化脚本等。

    总结一下它们的区别:

    • service_healthy 关注依赖服务的健康状态,它要求依赖服务处于健康状态才能启动相关服务。
    • service_completed_successfully 关注依赖服务的成功完成,它要求依赖服务在成功完成后(即退出状态码为 0)才能启动相关服务。

    required 说明

    在长定义语法中,required 字段用于指定依赖服务是否是必需的。它控制了当依赖服务未启动或不可用时的行为。

    • required 设置为 true默认值),如果依赖服务未启动或不可用,Compose 将阻止启动相关的服务,并显示警告信息。
    • required 设置为 false,Compose 仍会显示警告信息,但不会阻止启动相关的服务。相当于它是可选的,即使依赖服务未启动或不可用,相关服务仍会尝试启动。
    services:
      web:
        build: .
        depends_on:
          database:
            required: false
    
      database:
        image: mysql:latest
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    下面看看一个完整的例子 docker-compose-test.yml:

    version: '3'
    
    services:
      rabbitmq:
        hostname: rabbitmq_host
        container_name: 'mq'
        image: rabbitmq:3.9.11-management
        restart: always
        ports:
          - "5772:5672"  # AMQP
          - "15772:15672"  # Web UI
        networks:
          - app-network
        environment:
          RABBITMQ_DEFAULT_USER: root
          RABBITMQ_DEFAULT_PASS: pwd
          RABBITMQ_DEFAULT_VHOST: /
        volumes:
          - rabbitmq_data:/var/lib/rabbitmq/mnesia
    
        healthcheck:
          test: [ "CMD", "rabbitmq-diagnostics", "ping" ]
          interval: 50s
          timeout: 5s
          retries: 3
    
    
      selenium:
        container_name: 'selenium'
        image: selenium/standalone-chrome
        restart: always
        ports:
          - "4444:4444"
    
        networks:
          - app-network
    
        healthcheck:
          test: [ "CMD", "curl", "-f", "http://localhost:4444/wd/hub/status" ]
          interval: 30s
          timeout: 5s
          retries: 3
    
    
      db:
        container_name: 'mysql8'
        image: mysql:8.0.32
    #    hostname: mysql_host
        user: root
        command:
          --default-authentication-plugin=mysql_native_password
          --character-set-server=utf8mb4
          --collation-server=utf8mb4_unicode_ci
    
        environment:
          LANG: C.UTF-8
          MYSQL_ROOT_PASSWORD: pwd
          MYSQL_DATABASE: yinlian
    
        ports:
          - "3306:3306"
    
        volumes:
          - "./data/db/data:/var/lib/mysql"
          - "./data/db/mysql-files:/var/lib/mysql-files"
          - "./build/docker/mysqldb/my.cnf:/etc/my.cnf"
    
        networks:
          - app-network
    
        healthcheck:
          test: [ "CMD", "mysqladmin", "ping", "-h", "localhost" ]
          interval: 30s
          timeout: 5s
          retries: 3
    
      app-producer:
        container_name: 'producer'
        build:
          context: .
          dockerfile: Dockerfile
        ports:
          - "8001:8001"
    
        command: ['echo','hello world, Frank']
        depends_on:
          db:
            condition: service_healthy
    
          rabbitmq:
            condition: service_healthy
    
          selenium:
            condition: service_healthy
    
        networks:
          - app-network
    
    
    networks:
      app-network:
        driver: bridge
    
    volumes:
      rabbitmq_data:
        driver: local
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106

    请添加图片描述

    请添加图片描述

    如果 依赖服务启动失败了, app-producer 就不会启动 ,直接退出了

    请添加图片描述

    参考文档

    depends_on

    分享快乐,留住感动. '2023-09-13 19:17:03' --frank
  • 相关阅读:
    网页脚本语言第一节课9.19
    LCR 001. 两数相除
    一例恶搞的样本的分析
    什么是热部署?Spring Boot如何进行项目热部署?
    MQTT协议
    10.Java集合汇总
    网上商店商城购物系统(asp.net,sqlserver,三层架构)
    golang之基础库
    基于JAVA智慧物业管理系统计算机毕业设计源码+系统+mysql数据库+lw文档+部署
    11-JVM调优实战-1
  • 原文地址:https://blog.csdn.net/u010339879/article/details/132869044