◾️はじめに
Docker compose の depends_on に関しては 知っていて使っていたが、これに関連したトラブルがあり depends_onに関する知識の上積み、切り分け手法、解決方法など ためになることが多かったので、メモ。
目次
【0】今回学べたこと 1)切り分け手法 2)depends_on / condition 3)docker compose up --build 【1】depends_on 1)depends_onの注意点 【2】トラブル:depends_onを指定したサービスが起動しない 1)調査手法 2)原因 3)解決案を行う上での注意点 4)解決案1:Healthチェックしてから起動させるBashを組む 5)解決案2:depends_on / conditionを使う
【0】今回学べたこと
1)切り分け手法
| Command | Explanations |
|---|---|
| docker ps -a | --all , -a: 全てのコンテナを表示(デフォルトは実行中のコンテナだけ表示) |
| docker compose logs [SERVICE]/docker logs [SERVICE] | サービスのログ表示(-fだとリアルタイム表示) |
| docker compose build [SERVICE] | サービスのビルド |
* 以下の関連記事にも更新しておく
Docker ~ トラブルシュート方法 ~
https://dk521123.hatenablog.com/entry/2023/12/12/034018
2)depends_on / condition
depends_on: db: # ★注目 condition: service_started
https://qiita.com/waniwaninowani/items/d43c4b8cea690a50581f
| Value of condition | Explanations |
|---|---|
| service_started | 指定したサービスが起動したら起動 |
| service_healthy | 指定したサービスが起動し、更にhealthcheck が通れば起動 |
| service_completed_successfully | 依存サービスを開始する前に、依存関係が正常に終了していることを指定 |
https://docs.docker.jp/compose/compose-file/
3)docker compose up --build
# build → run で実行 docker compose up --build # 注意点:docker compose up -d だけだと、 # Docker image構築まで行わないのでハマった
【1】depends_on
* サービス間の依存関係を指定し、コンテナ起動順序を制御 * e.g. DB -> Backend -> Frontend の順番で起動
1)depends_onの注意点
* depends_on のみだと、起動順序だけでヘルスチェックは行わない
【2】トラブル:depends_onを指定したサービスが起動しない
以下のdocker-compose.yamlで、 docker compose up -d し全てAll greenだったのだが、 backendが起動できておらず、全然docker psに表示されない。
docker-compose.yaml (一部抜粋)
https://github.com/dk521123/job-info-extractor/blob/develop/docker-compose.yml
services: db: image: postgres:15 container_name: postgres_db volumes: - volume_postgres:/var/lib/postgresql/data ports: - 5432:5432 env_file: - .env backend: build: ./backend container_name: backend_app ports: - 8000:8000 env_file: - .env depends_on: - db volumes: volume_postgres: name: v_postgres
1)調査手法
[1] docker ps -a を実行し、全てのコンテナ状況を表示してみる
# --all , -a: 全てのコンテナを表示(デフォルトは実行中のコンテナだけ表示) docker ps -a ... 276d899005a9 job-info-extractor-backend "uvicorn app.main:ap…" 22 seconds ago Exited (1) 16 seconds ago backend # Exited (1) でどっかで落ちていることが分かった
[2] docker compose logs [SERVICE]で落ちている箇所を特定
# docker logs [SERVICE] # docker compose logs [SERVICE] docker compose logs backend ... sqlalchemy.exc.OperationalError: (psycopg2.OperationalError) connection to server at "db" (172.20.0.2), port 5432 failed: Connection refused Is the server running on that host and accepting TCP/IP connections? (Background on this error at: https://sqlalche.me/e/20/e3q8) # => バックエンドが DB(PostgreSQL) に接続できずに落ちている
[3] docker compose build [SERVICE]で個別で実行できるか試す
# docker compose build [SERVICE] docker compose build backend # 再度、別途、backendのみ起動させると、問題なく起動する。 # (ってことは、DB接続情報に誤りがあるっと言ったことはなさそう)
2)原因
depends_on のみだと、起動順序だけでヘルスチェックは行なっておらず BackendでDB接続しようとした際に、DBのサービスは起動しているが、 まだPostgreSQLサービス自体は起動していなかったため、エラーになり 立ち上がらないままになっていた。
3)解決案を行う上での注意点
* 解決案1・2どちらで行うにしても、「docker compose up --build」する => そうしないと変更が反映されない可能性があるので。そこでめちゃくちゃハマった
4)解決案1:Healthチェックしてから起動させるBashを組む
backend/Dockerfile
FROM python:3.13-slim
RUN apt-get update && apt-get install -y --no-install-recommends \
tesseract-ocr \
tesseract-ocr-jpn \
fonts-noto-cjk \
poppler-utils \
build-essential \
gcc \
libgl1 \
# ★注目
postgresql-client \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY . /app
RUN mkdir -p /app/uploads
RUN pip install --no-cache-dir -r requirements.txt
# ★注目
COPY ./entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
backend/entrypoint.sh
#!/bin/sh set -e : "${DB_HOST:=db}" : "${DB_PORT:=5432}" : "${POSTGRES_USER:=postgres}" : "${WAIT_RETRIES:=60}" : "${WAIT_SLEEP:=1}" i=0 echo "Waiting for Postgres at ${DB_HOST}:${DB_PORT}..." while [ $i -lt "$WAIT_RETRIES" ]; do # pg_isready でHealthチェックしてから起動させる #. => https://www.postgresql.jp/docs/9.4/app-pg-isready.html if pg_isready -h "$DB_HOST" -p "$DB_PORT" -U "$POSTGRES_USER" >/dev/null 2>&1; then echo "Postgres is ready" break fi i=$((i+1)) echo "Postgres unavailable - sleeping ${WAIT_SLEEP}s ($i/$WAIT_RETRIES)" sleep "$WAIT_SLEEP" done if [ $i -ge "$WAIT_RETRIES" ]; then echo "Timed out waiting for Postgres" >&2 exit 1 fi exec uvicorn app.main:app --host 0.0.0.0 --port 8000
5)解決案2:depends_on / conditionを使う
docker-compose.yaml
services: db: image: postgres:15 container_name: postgres_db volumes: - volume_postgres:/var/lib/postgresql/data ports: - 5432:5432 env_file: - .env # ★注目 healthcheck: test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"] interval: 5s timeout: 3s retries: 5 backend: build: ./backend container_name: backend_app ports: - 8000:8000 env_file: - .env depends_on: db: # ★注目 condition: service_healthy
関連記事
Docker compose ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2022/05/21/222910
Docker compose ~ 基本編 ~
https://dk521123.hatenablog.com/entry/2020/04/11/000000
Docker ~ トラブルシュート方法 ~
https://dk521123.hatenablog.com/entry/2023/12/12/034018
Docker によるトラブルシューティング
https://dk521123.hatenablog.com/entry/2017/09/24/162257