皆で使うサーバー上にDockerで開発環境を作る

課題と特徴、構成図

課題と特徴

PHPのWEBアプリ用の開発環境を作りました。

  • 開発環境をデザイナーを含む各スタッフのデスクトップに置かない。つまりVirtualboxは使わず、全員アクセス可能なサーバーで稼動させます。
    • なぜなら、他スタッフが別の場所(県)にいるからやり方を伝えたりするのが面倒そう。
    • なぜなら、デザイナーはフォトショップとかイラストレーターとかメモリをもりもり使っているのでさらに仮想環境を起動させるのはちょっと。
    • なぜなら、gitを使えないスタッフ居る。git覚えてもらうよりサーバー上で代わりにコミットしたほうが手っ取り早かったり。
  • 既存のレガシーWEBアプリを扱う場合が多い。設定が混乱しているので、設定を極力変えたくない。変えるのはデータベースの接続くらい。
  • 開発環境へのアクセスは本番環境と関係ない任意のドメインでアクセスできます。
  • データベースはDockerのホストで動かしている共通のもの。

残念な点

  • 実は2年くらい前の情報です。またDockerを使うのは初めてだったので詳しくありません。他にもっと良いやり方があると思います。
  • 設定することが多く、説明漏れもあると思います。正確性についても疑いつつ読んで下さい。
  • Dockerで残念だったのは、CentOSのカーネルをアップデートしてしまってDockerが動かなくなったこと。なんとか動くようにしたもののどう対処したか忘れました。

構成図とリクエストの流れ

ブラウザからのリクエストをDockerのホストサーバーのApacheが受け取り、mod_proxyで、Dockerのポートに送る。Docker内ではポート「本番機ドメイン:80」にアクセスされる、という流れになります。

ブラウザからのリクエストはワイルドカードでゾーン設定するなどして、スタッフ毎に割り振り、Dockerの待ち受けポートもスタッフ毎に割り振ります。

二人分の環境を作る場合に人によって異なる設定値は以下のものだけです。PHPアプリケーション内部では人によって違う設定をする必要はありません。

ホストマシン上でのURL 内部の80番にフォワードされる外部のポート ホスト上の作業ディレクトリ
staff1.example.com 10080 /home/staff1/workdir
staff2.example.com 10081 /home/staff2/workdir

設定

Apache

ホストサーバー上のApache mod_proxyでリバースプロキシしてそれぞれのDockerのポートにリクエストを転送

ホスト側のApacheで各ユーザー毎のテストURLからDockerコンテナのポート(Dockerで指定したもの)にリバースプロキシ設定。

<VirtualHost *:80>
        ServerName   [STAFF1の開発機ドメイン]
        ProxyPass / http://[STAFF1の開発機ドメイン]:10080/
        ProxyPassReverse / http://[STAFF1の開発機ドメイン]/
        ProxyPassReverseCookieDomain [STAFF1の開発機ドメイン]  [本番機のドメイン]
    ErrorLog "logs/staff1.test-domain-error.log"
    CustomLog "logs/staff1.test-domain-access.log" combined
</VirtualHost>

転送先URLは本番のURLにするが、ホストサーバー /etc/hosts で自身に向ける

ホストサーバーの /etc/hosts で本番環境用のドメインのIPをローカルホストにする。

127.0.0.1 [本番機のドメイン]

Dockerの設定

ホストのファイルシステムをDockerから読み書きする

ホストのファイルシステムをDockerから読み書きできるように個人毎の開発用のディレクトリをDockerの中で本番機と同じ場所に割り当てます。

このシェルスクリプトと、Docker内部のApacheの設定を書いたファイルは共通のものなので、各個人別のディレクトリとは別のディレクトリを割り当ます。

これらを次のようにシェルスクリプトでDockerコンテナに適用します。

Dockerコンテナ起動時に設定用シェルスクリプトを実行

これがDockerの起動時に渡すコマンドであり、内部で上記の設定ファイルをApacheに設定し、Apacheを起動します。

やっているのは、

  • Apacheの設定ファイルをDocker内のhttpd.confに追記
  • Apacheの起動
  • デーモン化

です。これを次で説明するDockerのコンテナ起動時にパラメータとして渡して実行します(exe_on_container.sh)。

#!/bin/sh
# Name: exe_on_container.sh
# アプリケーション用のApache設定を適用
cat /mnt/httpd_application1.conf >>/etc/httpd/conf/httpd.conf

# Apache起動
/sbin/service httpd start

# デーモン化
while true
do
    sleep 10
done

このシェルスクリプトの最後はデーモン化の処理です。ちゃんとした感じではないのですが、一番シンプルなのでこれにしています。以下を参考にしました、なにぶん古い話なので今現在はDockerがもっと良いやり方を提供しているかも知れません。

Dockerコンテナ起動スクリプト

以下のような設定が基本となります。あとは各スタッフ毎にループするなりすると良いと思います。

例)boot_container.sh

#!/bin/sh

# Name: boot_contaner.sh
# Dockerで実行するスクリプトなどを配置するディレクトリ
common_dir='/home/docker_common:/mnt'
# Dockerイメージ
image="myimage/centos:dev207"


#
staffname=hoge
http=10080
ssh=10022  # execが出来るようになったので不要?

# Dockerの中で /etc/hosts を編集する必要がある場合、Docker内の/etc/hostsが編集できないので起動オプションで指定
hosts='--add-host=SOMEDOMAIN1_IN_DOCKER:127.0.0.1 --add-host=SOMEDOMAIN1_IN_DOCKER:127.0.0.1'

#
sudo docker run -d -p ${httpd}:80 -p ${ssh}:22 -v $common_dir -v /home/${staffname}/application1_working_dir:/production/application1  $hosts $image /mnt/exe_on_container.sh

アプリケーションの作業ディレクトリをDockerコンテナ内の本番機と同じ場所にマウントしていますが、複数のアプリケーションがある場合は、一つ上の階層をマウントしてそれぞれの作業ディレクトリをexe_on_contaner.sh の中でシンボリックしてもよいと思います。

PHPでアプリの実行前と実行後に処理を足す。

Docker内のApacheのVirtualHostディレクティブ内に以下のように記述すると、アプリが実行される前とされた後に指定したファイルが実行されます。HTMLソース内のURLの書き換えを行います。

php_value auto_prepend_file /web/somedomain1/filter_pre_execute.php
php_value auto_append_file /web/somedomain1/filter_post_output.php

filter_pre_execute.phpの中身。

<?php
ob_start();
// 開発環境であることを定義。
define('IS_DEV',true);
// HTTP_HOSTにDockerのホスト側で使われるポート番号が出るので修正する。Wordpressでは必要。
$_SERVER['HTTP_HOST'] = $_SERVER['SERVER_NAME'];

filter_post_output.phpの中身。

<?php
$replaced = ob_get_contents();

// 本番機のドメインを開発機のドメインに置換してブラウザに出力する
$replaced =  str_replace('[本番機ドメイン]', '[開発機ドメイン]' , $replaced);
ob_end_clean();
echo $replaced;

ワードプレスなどでは、バッファリング内容が置換する前に出力されたりするので、Apache側でやる方法もあります。「Apache フィルター」などで検索するとみつかると思います。そのうちここに追記します。

「皆で使うサーバー上にDockerで開発環境を作る」への1件のフィードバック

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です