控制docker-compose中服務的啓動順序

官方文檔:https://docs.docker.com/compose/startup-order/python

能夠經過depends_on來編排服務之間的依賴關係,可是有一個問題,好比一個web項目,依賴一個數據庫或者依賴一個redis服務,那麼要等到數據庫徹底準備好以後,才能讓web服務開始啓動並鏈接數據庫,docker默認的依賴方式是隻要依賴數據庫服務容器啓動就會啓動web容器,而不 檢查數據庫是否已經準備好。mysql

解決方法一個方面是在鏈接層面使用自動重連策略,好比mysql jdbc能夠有auto reconnect自動重連參數。或者使用下面建議的用一個腳本(wait-for-it.sh)來探測依賴服務已經徹底準備好,或者本身編寫一個health check腳原本檢測依賴服務的健康情況來判斷依賴服務是否啓動完成。git

 

You can control the order of service startup with the depends_on option. Compose always starts containers in dependency order, where dependencies are determined by depends_onlinksvolumes_from, and network_mode: "service:...".github

However, Compose will not wait until a container is 「ready」 (whatever that means for your particular application) - only until it’s running. There’s a good reason for this.web

The problem of waiting for a database (for example) to be ready is really just a subset of a much larger problem of distributed systems. In production, your database could become unavailable or move hosts at any time. Your application needs to be resilient to these types of failures.redis

To handle this, your application should attempt to re-establish a connection to the database after a failure. If the application retries the connection, it should eventually be able to connect to the database.sql

The best solution is to perform this check in your application code, both at startup and whenever a connection is lost for any reason. However, if you don’t need this level of resilience, you can work around the problem with a wrapper script:docker

  • Use a tool such as wait-for-itdockerize, or sh-compatible wait-for. These are small wrapper scripts which you can include in your application’s image and will poll a given host and port until it’s accepting TCP connections.數據庫

    For example, to use wait-for-it.sh or wait-for to wrap your service’s command:bash

    version: "2"
    services:
      web:
        build: .
        ports:
          - "80:8000"
        depends_on:
          - "db"
        command: ["./wait-for-it.sh", "db:5432", "--", "python", "app.py"]
      db:
        image: postgres

    Tip: There are limitations to this first solution; e.g., it doesn’t verify when a specific service is really ready. If you add more arguments to the command, you’ll need to use the bash shift command with a loop, as shown in the next example.

  • Alternatively, write your own wrapper script to perform a more application-specific health check. For example, you might want to wait until Postgres is definitely ready to accept commands:

    #!/bin/bash
    # wait-for-postgres.sh
    
    set -e
    
    host="$1"
    shift
    cmd="$@"
    
    until psql -h "$host" -U "postgres" -c '\q'; do
      >&2 echo "Postgres is unavailable - sleeping"
      sleep 1
    done
    
    >&2 echo "Postgres is up - executing command"
    exec $cmd

    You can use this as a wrapper script as in the previous example, by setting:

    command: ["./wait-for-postgres.sh", "db", "python", "app.py"]

 

注意若是你使用wait-for-it.sh腳本,若是你的基礎鏡像不包含bash命令(好比alpine鏡像)須要安裝bash,否則無法執行wait-for-it.sh腳本致使容器啓動失敗。

若是Dockerfile的基礎鏡像用的是alpine相關的基礎鏡像的話,記得添加以下指令安裝bash:

RUN apk update RUN apk upgrade RUN apk add --no-cache bash

相關文章
相關標籤/搜索