RitoLabo

Laravel&DockerizeでDBコンテナの起動を待ってマイグレーションを行なう

  • 公開:
  • カテゴリ: PHP Laravel
  • タグ: PHP,Laravel,Docker,DockerCompose,Dockerize

開発環境を docker-compose を用いて構築する場合に複数のコンテナを起動しますが、一方のコンテナの起動を待って何らかの処理を行いたい場合があります。

今回は Dockerize を用いて、それらの流れを実現していきます。

アジェンダ
  1. Dockerize
  2. コンテナの起動を確認・待機する
    1. Dockerfile
    2. docker-compose.yml
    3. Dockerizeを実行する
  3. DBコンテナの起動を待ってLaravelのマイグレーションを行なう

Dockerize

Dockerize は、Dockerコンテナの制御の為のユーティリティです。

jwilder/dockerize
https://github.com/jwilder/dockerize

今回はコンテナ起動確認の為に使いますが、それ以外にも色々とできるようです。

以下のような説明が書かれています。

  • コンテナの起動時に、テンプレートとコンテナ環境変数からアプリケーション構成ファイルを生成します
  • 複数のログファイルをstdoutまたはstderrにテールします。
  • メインプロセスを開始する前に、TCP、HTTP(S)、unixを使用して他のサービスが利用可能になるのを待ちます。

dockerizeの一般的な使用例は、1つ以上の構成ファイルを持つアプリケーションがあり、環境変数を使用して値の一部を制御する場合です。

コンテナの起動を確認・待機する

今回は例として、DBコンテナの起動を待機してみます。

Dockerfile

Dockerize のコンテナを作成するための Dockerfile を作成します。

Dockerfile
FROM centos:latest

RUN yum -y install wget

ENV DOCKERIZE_VERSION v0.6.1
RUN wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz \
&& tar -C /usr/local/bin -xzvf dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz \
&& rm dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz

やっている事は Dockerize をダウンロードして展開しているだけです。

なお、サンプルなので専用のコンテナを立てますが、例えばWEBサーバのコンテナに Dockerize を仕込んで使う、みたいな事ももちろん可能で、おおよそはそういう想定で使われる事が多いかなと思います。(つまりLaravelアプリケーションもコンテナ上で動作させるみたいな構成)

要は起動を待機する動作を行ないたいサーバ(コンテナなど)に Dockerize を導入すればOKです。

docker-compose.yml

コンテナを定義します。今回は DBコンテナと Dockerizeコンテナです。

docker-compose.yml
version: '3'

services:
db:
image: mysql:latest
container_name: sample_db
command: mysqld --default-authentication-plugin=mysql_native_password
environment:
- MYSQL_DATABASE=sample
- MYSQL_ROOT_PASSWORD=root
ports:
- "3333:3306"
dockerize:
container_name: sample_dockerize
build: ./dockerize/
image: sample_dockerize
links:
- db
stdin_open: true
tty: true
depends_on:
- db

特別な事は何もしていなくて、シンプルに両方のコンテナをを定義しています。

ここの定義でパスなども記述したので、わかりやすいように今のディレクトリ構成を記すと以下のようになっています。

/
├── docker-compose.yml
├── dockerize
│   └── Dockerfile

Dockerizeを実行する

定義ができたので、Dockerize を実行してみます。まずはコンテナを起動します。

# コンテナ起動
docker-compose up -d

コンテナが起動したら、以下のコマンドを叩いて Dockerize を実行します。

# dockerize 実行
docker-compose exec dockerize dockerize -wait tcp://db:3306 -timeout 10s
  • コンテナの外から実行させるので docker-compose コマンドで叩きます。
  • [docker-composeコマンド] [コンテナ指定] [dockerizeコマンド] の構成になっています。

すると、dbコンテナに対して接続が試みられ、接続できればコンテナが起動したとみなされ、処理を停止します。

# コンテナ起動
$ docker-compose up -d
Creating network "sample_default" with the default driver
Creating sample_db ...
done
Creating sample_dockerize ...
done

# dockerize 実行
$ docker-compose exec dockerize dockerize -wait tcp://db:3306 -timeout 10s
2019/12/14 06:54:52 Waiting for: tcp://db:3306
2019/12/14 06:54:52 Problem with dial: dial tcp 172.21.0.2:3306: connect: connection refused. Sleeping 1s
2019/12/14 06:54:53 Problem with dial: dial tcp 172.21.0.2:3306: connect: connection refused. Sleeping 1s
2019/12/14 06:54:54 Problem with dial: dial tcp 172.21.0.2:3306: connect: connection refused. Sleeping 1s
2019/12/14 06:54:55 Problem with dial: dial tcp 172.21.0.2:3306: connect: connection refused. Sleeping 1s
2019/12/14 06:54:56 Problem with dial: dial tcp 172.21.0.2:3306: connect: connection refused. Sleeping 1s
2019/12/14 06:54:57 Problem with dial: dial tcp 172.21.0.2:3306: connect: connection refused. Sleeping 1s
2019/12/14 06:54:58 Problem with dial: dial tcp 172.21.0.2:3306: connect: connection refused. Sleeping 1s
2019/12/14 06:54:59 Problem with dial: dial tcp 172.21.0.2:3306: connect: connection refused. Sleeping 1s
2019/12/14 06:55:00 Problem with dial: dial tcp 172.21.0.2:3306: connect: connection refused. Sleeping 1s
2019/12/14 06:55:01 Connected to tcp://db:3306

ここまでが、基本的な Dockerize の待機動作です。

DBコンテナの起動を待ってLaravelのマイグレーションを行なう

Laravelを使ってPHPアプリケーションを構築するためにDockerを使って開発環境を構築した際に、いちいち docker-compose やって、それから php artisan migrate --seed やって、、みたいな事が煩わしかったりします。

この辺も、Dockerizeを用いると解消できたりします。

例えば、以下のような構成の場合

/
├── docker-compose.yml
├── dockerize
│   └── Dockerfile
└── laravel
  • Dockerfile と docker-compose.yml は先程と同じもの
  • Laravel のソースディレクトリはローカルに設置

ルートディレクトリに適当なシェルファイルを作成します。

/
├── docker-compose.yml
├── dockerize
│   └── Dockerfile
├── laravel
└──
start.sh // 作成

シェルスクリプトを以下のように定義します。

start.sh
#!/usr/bin/env bash

# コンテナ起動
docker-compose up -d

# dockerize 実行
docker-compose exec dockerize dockerize -wait tcp://db:3306 -timeout 20s

# Migrate & Seeding
php ./laravel/artisan migrate --seed

そして実行します。

$ sh start.sh
Creating network "sample_default" with the default driver
Creating sample_db ...
done
Creating sample_dockerize ...
done
2019/12/14 07:21:25 Waiting for: tcp://db:3306
2019/12/14 07:21:25 Problem with dial: dial tcp 172.22.0.2:3306: connect: connection refused. Sleeping 1s
2019/12/14 07:21:26 Problem with dial: dial tcp 172.22.0.2:3306: connect: connection refused. Sleeping 1s
2019/12/14 07:21:27 Problem with dial: dial tcp 172.22.0.2:3306: connect: connection refused. Sleeping 1s
2019/12/14 07:21:28 Problem with dial: dial tcp 172.22.0.2:3306: connect: connection refused. Sleeping 1s
2019/12/14 07:21:29 Problem with dial: dial tcp 172.22.0.2:3306: connect: connection refused. Sleeping 1s
2019/12/14 07:21:30 Problem with dial: dial tcp 172.22.0.2:3306: connect: connection refused. Sleeping 1s
2019/12/14 07:21:31 Problem with dial: dial tcp 172.22.0.2:3306: connect: connection refused. Sleeping 1s
2019/12/14 07:21:32 Problem with dial: dial tcp 172.22.0.2:3306: connect: connection refused. Sleeping 1s
2019/12/14 07:21:33 Problem with dial: dial tcp 172.22.0.2:3306: connect: connection refused. Sleeping 1s
2019/12/14 07:21:34 Problem with dial: dial tcp 172.22.0.2:3306: connect: connection refused. Sleeping 1s
2019/12/14 07:21:35 Connected to tcp://db:3306
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_000000_create_users_table (0.03 seconds)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated: 2014_10_12_100000_create_password_resets_table (0.03 seconds)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated: 2019_08_19_000000_create_failed_jobs_table (0.02 seconds)
Database seeding completed successfully.

このように、コンテナ起動からマイグレーションまでが一回で実行できるようになります。

ちなみに Dockerize を用いない場合にこうした一連の処理を自動化すると、大抵、DBコンテナが立ち上がる前にマイグレーションが実行されるのでDBに接続できずに処理が失敗します。(大抵は)

まとめ

コンテナの良いところは、何度でもスクラップアンドビルド(立てて壊して)ができる事だと思いますが、だからこそ環境構築は簡単に済ませたいですよね。

便利なツールがあれば組み合わせて、いつでも簡単に実行環境を用意できるようにしておきたいものです。