LoginSignup
174
99

More than 1 year has passed since last update.

docker-composeでDBの起動完了を待ってからWebアプリを実行する

Last updated at Posted at 2016-12-17

はじめに

docker-composeで複数のコンテナを管理するとき、ほぼWebアプリとDBを一緒に使います。
大抵はWebアプリ側にdepends_onでDBのコンテナを指定して起動順序を制御しますが、あくまで起動順序だけなのでDBの起動完了前にWebアプリがDBにアクセスしてしまい起動失敗する事があります。

せっかくdocker-composeで1つにまとめて管理しているのに便利さが半減してしまうとモヤモヤしていたら、公式ではWebアプリ側でチェックせよと解説していました。

depends_on/condition

2021/07/21追記
depends_onで指定したサービスのhealthcheckが通ってから起動できるconditionが追加されました。これを使えばチェック用スクリプトを使わずにすみます。詳しくはDocker Compose の depends_on の使い方まとめを参照してください。

GitBucket + MySQLの場合

上述の公式の解説ではPostgreSQLを対象にしているのですが、MySQLをよく使うので書き換えてみました。

ファイル構成はこんな感じです。

files
docker-compose.yml
  + gitbucket/
      + Dockerfile
      + wait.sh

ベースイメージはalpine版なのでapkでmysql-clientをインストールしています。

gitbucket/Dockerfile
FROM java:8-jre-alpine
MAINTAINER shiena
ENV GITBUCKET_HOME /var/gitbucket
VOLUME ["${GITBUCKET_HOME}"]
EXPOSE 8080
RUN apk add --no-cache mysql-client
COPY wait.sh /wait.sh
ENV GITBUCKET_VERSION 4.7.1
ADD https://github.com/gitbucket/gitbucket/releases/download/${GITBUCKET_VERSION}/gitbucket.war /gitbucket.war

depends_on/condition版

  • versionを3にします。
  • dbにhealthcheck/testを追加してチェック用コマンドを追加します。
  • gitbucketのdepends_on/dbをリストから要素に変更してその子要素にcondition: service_healthyを追加します。

これでdbのhealtcheck/testで指定したコマンドが成功するとgitbucketが起動するようになります。

docker-compose.yml
version: '3'
services:
  gitbucket:
    build: gitbucket
    image: gitbucket:4.7.1
    ports:
      - "8080:8080"
    volumes:
      - ./var/gitbucket:/var/gitbucket
    depends_on:
      db:
        condition: service_healthy
    command: java -jar /gitbucket.war

  db:
    image: mysql:5.7
    ports:
      - "3306:3306"
    environment:
      - MYSQL_RANDOM_ROOT_PASSWORD=1
      - MYSQL_DATABASE=gitbucket
      - MYSQL_USER=gitbucket
      - MYSQL_PASSWORD=gitbucket
      - TZ=Asia/Tokyo
    command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci
    healthcheck:
        test: mysqladmin ping -h 127.0.0.1 -u$$MYSQL_USER -p$$MYSQL_PASSWORD

MySQLはmysqladmin コマンドでポートチェックできますが、httpやtcpなどは以下のような方法や他のコマンドも利用できます。

  • httpチェックを curl -f http://localhost:8080
  • tcpのチェックをbashで bash -c "echo > /dev/tcp/127.0.0.1/80"
  • tcpのチェックをnetstatで netstat -tnl | awk '$$1 ~ /^tcp/ && $$4 ~ /:80$$/{rc=1}END{exit !rc}'

チェックスクリプト版

今回のメインとなるwait.shは引数からDBのホスト名、ユーザ名、パスワードを受け取って生存チェック後にWebアプリを実行します。

gitbucket/wait.sh
#!/bin/sh

set -e

host="$1"
shift
user="$1"
shift
password="$1"
shift
cmd="$@"

echo "Waiting for mysql"
until mysql -h"$host" -u"$user" -p"$password" &> /dev/null
do
        >&2 echo -n "."
        sleep 1
done

>&2 echo "MySQL is up - executing command"
exec $cmd

最後にdocker-compose.ymlです。
wait.shにDBの情報を渡す必要があるため、commandでGitBucketを起動します。

docker-compose.yml
version: '2'
services:
  gitbucket:
    build: gitbucket
    image: gitbucket:4.7.1
    ports:
      - "8080:8080"
    volumes:
      - ./var/gitbucket:/var/gitbucket
    depends_on:
      - db
    command: sh /wait.sh db gitbucket gitbucket java -jar /gitbucket.war

  db:
    image: mysql:5.7
    ports:
      - "3306:3306"
    environment:
      - MYSQL_RANDOM_ROOT_PASSWORD=1
      - MYSQL_DATABASE=gitbucket
      - MYSQL_USER=gitbucket
      - MYSQL_PASSWORD=gitbucket
      - TZ=Asia/Tokyo
    command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci

以上、このようなスクリプトを挟む事でDBの起動完了を待ってからWebアプリを起動できるようになります。

参考

174
99
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
174
99