docker-composeでのサービスの開始順序の制御

5110 ワード

公式ドキュメント:https://docs.docker.com/compose/startup-order/
dependsでonはサービス間の依存関係を編成しますが、Webプロジェクトがデータベースに依存したりredisサービスに依存したりするなどの問題があります.データベースが完全に準備されてから、Webサービスがデータベースを起動して接続し始めるまで待たなければなりません.dockerのデフォルトの依存方式は、データベースサービスコンテナに依存して起動すればWebコンテナを起動します.データベースが準備されているかどうかを確認しません.
解決策の1つの態様は、mysql jdbcのような自動再接続ポリシーを接続レベルで使用することであり、auto reconnect自動再接続パラメータを持つことができる.あるいは、依存サービスが完全に準備されていることを検出するために、以下に提案されるスクリプト(wait-for-it.sh)を使用するか、または依存サービスの健康状態を検出するためにhealth checkスクリプトを自分で作成して、依存サービスが開始されたかどうかを判断する.
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:..." .
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.
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.
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.
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:
  • Use a tool such as wait-for-it, dockerize, 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:
    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