🚏

dockerのnginxがredisにアクセス出来ず起動できない件

2022/08/10に公開

タイトルについて

共感の得やすいタイトルにしたけれど、その実態はdockerのredisの立ち上がりが遅い件だ。

単純なdepends_on

docker-composeを使う時、多くは起動順序の設定のためにdepends_onを書く。しかしそれだけだとnginxredisを組み合わせた時に問題が発生する。redisが起動して準備完了する前にnginxの起動が始まってしまうので、redisを使ったupstreamを定義しようとするとエラーになってしまうのだ。
対応できずに各コンテナにipv4アドレス振って対応した人やupstreamの使用を諦めた人もいるのではないだろうか?

問題のあるdepends_on
    depends_on:
      - redis
      - memcached
      - mysql
問題のあるdocker-compose.yml
docker-compose.yml
version: "3.9"
services:
  redis:
    image: "redis:alpine"
  mysql:
    image: "mysql:8.0"
    environment:
      MYSQL_ROOT_PASSWORD: example
  adminer:
    image: adminer
    restart: always
    ports:
      - 8080:8080
  nginx:
    image: "openresty/openresty:alpine"
    ports: 
      - 80:80
    depends_on:
      - redis
      - memcached
      - mysql

拘ったdepends_on

このdepends_onを下記のように書き換える事で、nginxからredisへ投げるヘルスチェックが通ってからnginxを立ち上げてくれるようになる。

拘ったdepends_on
  nginx:
    depends_on:
      redis:
        condition: service_healthy

そしてredis側にはヘルスチェックの内容を追加する

ヘルスチェック
  redis:
    healthcheck:
      test: ["CMD", "redis-cli", "--raw", "incr", "ping", "|", "grep", "PONG"]
      timeout: 5s
      retries: 5
      start_period: 5s
改善されたdocker-compose.yaml
docker-compose
version: "3.9"
services:
  redis:
    image: "redis:alpine"
    expose:
      - 6379
    healthcheck:
      test: ["CMD", "redis-cli", "--raw", "incr", "ping", "|", "grep", "PONG"]
      timeout: 5s
      retries: 5
      start_period: 5s
  memcached:
    image: "memcached:alpine"
  mysql:
    image: "mysql:8.0"
    environment:
      MYSQL_ROOT_PASSWORD: example
  adminer:
    image: adminer
    restart: always
    ports:
      - 8080:8080
  nginx:
    image: "openresty/openresty:alpine"
    ports: 
      - 80:80
    depends_on:
      redis:
        condition: service_healthy
      memcached:
        condition: service_started
      mysql:
        condition: service_started

気をつけるところ

redisのhealthcheckでgrep PONGが無いと意図したチェック動作とならない。

Discussion