読者です 読者をやめる 読者になる 読者になる

Fusicきばんブログ

Fusic基盤ユニットの非公式技術ブログ

mockmock × Google Cloud Platform( × Slack)

こんにちは。Fusic 基盤ユニットの濱野です。
今日は、先日 4/6 に正式リリースされた 弊社サービス mockmock を使ってみた話を書いてみようと思います。

mockmock とは?

- mockmockはIoTの開発支援サービス。
- クラウド上に仮想デバイスを作成し、開発中のサーバーに疑似データを送ってくれる。
- デバイスの制約を受けずにIoTのサーバーアプリの開発が進められるので、とっても楽。

というサービスです。

目標

mockmock から Google Cloud Platform(以下、GCP) に作ったAPI を叩き、
Slack に通知を飛ばす
とりあえず、シンプルにWeb API を叩けるようになる!!!

まず最初に、GCPにAPI サーバーを作ります。

使用したのは、永年無料で使用できると噂の f1-microです(※1)。
こちらのサイト https://blog.apar.jp/web/6966/ を参考にさせて頂きました。

環境は、

$ nginx -v
nginx version: nginx/1.10.2

$ php -v
PHP 7.0.17 (cli) (built: Mar 14 2017 15:14:30) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies

です。

ちなみに、f1-micro では、メモリが 0.6 GB しかありません。
docker の mysql image をrun しようとしましたが、
メモリ不足で起動すらできませんでした。
後日、省メモリについても調べます。。。

PHP のコード

docroot に、2種類のファイルを作成しました。

1つめ
index.php

<?php
if ($_SERVER['REQUEST_METHOD'] == 'GET') {
  echo json_encode(['key' => '鍵']);
}

こちら、後ほど説明しますが、
mockmock のプロジェクトを作る際に必要になる処理です。
‘鍵’ と書いたところに、mockmock のプロジェクト作成時に提示される 認証キー を入れます。

2つめ
success.php

<?php
function send_to_slack($message) {
  $webhook_url = 'https://hooks.slack.com/services/カスタムインテグレーションのURL';
  $options = array(
    'http' => array(
      'method' => 'POST',
      'header' => 'Content-Type: application/json',
      'content' => json_encode($message),
    )
  );
  $response = file_get_contents($webhook_url, false, stream_context_create($options));
  return $response === 'ok';
}
$message = array(
  'username' => 'mockmock',
  'text' => 'fooooo!!!',
);
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
  // request body に json が送られてくる際、$_POST は空になるので、この処理が必要。
  $json = file_get_contents('php://input');
  $array = json_decode($json, true);
  if ($array['status'] == 'success') {
    $date = new DateTime();
    $now = $date->format('Y-m-d\TH:i:s.u');
    $message['text'] = 'success'.$now;
  } else {
    $message['text'] = 'error';
  }
   send_to_slack($message);
} else {
  echo send_to_slack($message);
}

とりあえず動くことを目標に頑張りました。
slack 通知の送り方は、この辺を参考にしました。ありがとうございます。
http://qiita.com/hoto17296/items/621a6e16f23785a543f3 http://qiita.com/gorogoroyasu/items/a73ba2180d0934f51485 (これ、自分の記事です。)

これで、サーバー側完成です。

(file_get_contents(‘php://input’) を知らなくて、結構ハマリました。 普段はCakePHPを使って開発しているので、素書きのPHPが難しい。。。)

mockmock 側の設定

次に、mockmock 側の設定の話を書いていきます。

公式のヘルプ
を参考にさせていただきました。

ヘルプに沿って、こんな感じの設定を書きます。

f:id:adiboy:20170409233749p:plain

そして、疎通確認を行います。 注意点は、mockmockからのリクエストが GETで飛んでくることです。 まあ、URL にアクセスしてるだけだから当たり前といえば当たり前なのですが。。。

次に、mockグループの新規作成を行います。

と言っても、適当に名前をつけるだけです。

そのあと、mockステータス を設定します。 新規作成を押したあと、 f:id:adiboy:20170409233829p:plain こんな感じで設定します。 f:id:adiboy:20170409233842p:plain

データテンプレート というのは、どのようなデータを送信するか のテンプレートのことです。
ヘルプが参考になります。 https://console.mock-mock.com/help#help_data_template
デフォルトで、 {'hello': 'world'} というデータを送るようなテンプレートがセットされます。
ここを自由にカスタマイズできる仕組みです。

その後、 mock のタブを開き、新規登録を押すと、準備完了です。
f:id:adiboy:20170409233915p:plain

あとは、操作 ボタンから、 起動 を選択するだけ。
数秒 ~ 数十秒 したら、 mockからAPI にデータが飛んできます。

ということで

mockmock は、本来IoT のデバイスの代わりとして使うものですが、 任意のデータをWebAPIに送れるので、GCPに作ったAPI を叩き、Slack に通知を飛ばしてみました。 ハローワールドすることはできたかな? と思います。
少しでもとっつきやすいと思っていただけたら幸いです。

次回は、もう少し mockmock を掘り下げてみようと思います。
楽しい週末でした(※3)!

Slack のスクショ f:id:adiboy:20170409234915p:plain

※1
GCP を使うのは、完全に今回が初めてです。
SSH するのが大変でした。
普通に ~/.SSH/authorized_keys に公開鍵を設定するだけではだめらしい。
http://qiita.com/kosuke_nishaya/items/3d9a95f559d0c22d8134
のような設定が必要らしいです。

※2
もともと、 AWS の API Gateway を叩いて、 Lambda からSlack に通知を飛ばす的な、
サーバーレス的なやつをしたかったのですが、
どうもうまく行きませんでした。

まあ、AWS の知識は皆無に等しいので、詳しい方々は問題ないと思いますが。。。
それで、こんな感じでGCP を使うことにしたのです。

※3
http://ghostshell.jp/ を見に行く予定だったのに、
予定が大幅にずれ込んだため、泣く泣く延期します。
ネタバレはしないでください。

CakePHP3の負荷テストでの落とし穴

基盤ユニットの貞方(@sadapon2008)です。

CakePHP3のアプリをApacheBenchで負荷テストした際にはまった落とし穴をご紹介します。

前提

  • CentOS 7.3 + Apache 2.4 + PHP 7.0.17(remi版のmod_php)

落とし穴:ApacheBenchでCakePHP3の負荷テストをやってみたら全く性能が出ない

非常に簡単な負荷テストとして、静的HTML、素のPHP、CakePHP3.4.3でGETに対して簡単なHTMLを返すだけのものを用意し、 下記のコマンドでApacheBenchを実行してRequests per secondを測ってました。

$ ab -t 10 -c 20 -n 1000000 http://a.b.c.d/

すると、CakePHP3だけ3桁以上性能が悪い結果が出て(´・ω・`)となりました。 CakePHP3のデバッグモードはオフにしています。

  • 静的HTML: 約 8,000 req/s
  • 素のPHP: 約 7,500 req/s
  • CakePHP3: 約 2 req/s

原因

さすがにこの結果はおかしいだろうと原因を調査したところ、下記の記事を見つけました。

stackoverflow.com

PHP 5.4以上ではHTTPのリクエストのConnectionヘッダを指定しないとheader()が非常に遅くなるとのことでした。 CakePHP3のソースを見てみると↓の箇所で使っているheader()がまさに該当していました。

https://github.com/cakephp/cakephp/blob/3.4.3/src/Http/ResponseEmitter.php#L144

ワークアラウンド

前述の記事を参考にab -kを指定してConnection: keep-aliveが有効になるようにしてみました。

$ ab -t 10 -c 20 -n 1000000 -k http://a.b.c.d/

その結果、かなり改善しました!

  • CakePHP3 before: 約 2 req/s
  • CakePHP3 after: 約 700 req/s

元記事によるとクローラーなど行儀の悪いクライアントはConnectionヘッダが欠落していることもあるとのことなので、例えばApacheなら以下のような設定を行うことで、Connectionヘッダを強制することが可能です。

※ (2017/3/28追記)HTTP/1.1ではConnectionヘッダを指定しない場合はkeep-aliveをデフォルトとするようでしたのでプロトコルのバージョンをHTTP/1.0に絞り込む設定に変更しました。

<If "%{SERVER_PROTOCOL} =~ m#^HTTP/1\.0#i">
SetEnvIfNoCase Connection "^(keep-alive|close)$" APP_CONNECTION=1
RequestHeader set Connection close env=!APP_CONNECTION
</If>

↑の設定をすると-kを指定せずとも同じくらいの結果が得られました。

Rust言語でゆるくツールを作ってみるお話

Fusicの中野です。

最近、弊社の東京事務所内で人気のRust(プログラミング言語)について。

Rust言語

Rust言語についてのイメージは

  • 所有権と借用
  • 難しい
  • GCがない
  • 速いっぽい

とかでしょうか。

特に、所有権と借用のメモリ管理まわりの概念が、少し難しい言語かなと思います。

しかし、パターンマッチ・型推論・総称型・マクロなど、とても魅力的な要素がたくさん ある言語なので、今回はRust言語の勉強用にちょっとしたツールを作ってみました。

作ってみたツール

ということで、

github.com

主な機能として

  • $HOME/.ssh/config をパースする
  • Host <何か> の何か部分を取り出して、tmuxのパネルを分割してSSHで接続
  • それぞれの接続先にコマンドを送りつける

です。

使用したライブラリとして、

$HOME/.ssh/configのパース => rust版parsecのnom
readlineっぽいやつ => liner

を使わせていただきました。

nomはparsecとそっくりだったので、exampleとガヴリールドロップアウトを見ながら、 さくっと利用する事ができました。

感想として

Rustは難しい部分もあるかと思いますが、コンパイルが通れば気持ちいいですし そこそこ想定通りの動きをしてくれます。

rustup・rustfmt・racerなどの開発用ツールや、Rustの日本語記事や日本語訳ドキュメントなど、 簡単に利用するための環境が充実してきました。

Rust言語が気になっている人は、軽く試してみてはいかがでしょうか?

障害対応の裏側で何をやっているかの話

Fusic 平田です。
基盤ユニットの追加モジュール的な何かになりました。

何書こうかなーと思い、最近あったtypoとの悲しい戦い*1をまとめなおすとかでも良かったんですが、せっかくなので違う話を。

サイトが閲覧できない!な時に何をやっているか

障害対応なんかに遭遇しやすい、あるいは呼ばれやすい性質でして。
その時何やっているのかって話を少し。

あわてない、さわがない、はしらない

まあとりあえず。
何もいい結果に繋がらないので。

起きている状況をなるべく正確に知る

「全く閲覧できない」なのか、「閲覧できるけどすごく重い」なのか、それだけでも大きな違いなので、状況確認は正確に。

ネットワーク的に到達できるのか、サーバにログインできるのか

これすらできない場合は、

  • ネットワーク起因だったりするので周辺の状況(経路でネットワークダウンの障害報が出てないかなど)を確認する
  • OSがハングしている場合は、再起動を試みる

といった対応にシフトします。

リソースの使用状況の確認

dstatで確認することが多いです。
リソース監視を行っているのであれば、そのグラフ状況を見るなどして、リソースの使用状況を確認します。

  • メモリが枯渇している
  • CPUを使い過ぎている
  • I/O待ちが発生しまくっている

といった感じで、ボトルネックを特定します。

ログを見る

/var/log/ 以下であったり、アプリケーションのログであったりを確認して、特異な(OOM Killerなんかは特異の典型)ログが出ていないかを確認します。
特異点の判断ポイントとしては

  • 明らかに普段出ないログが出力されている
  • ログの量が普段より明らかに多い

といった観点になるでしょうか。

ただ目で追うのもさすがに辛いので、grepなりwcなり、コマンドと組み合わせて原因を探る感じです。

あと、アクセスログを精査するのであれば、Kataribeが便利です。
ISUCON御用達ツールですが、負荷の高い箇所だったりアクセス増だったりの一次調査で使えます。

対策を決めて実行する

原因が明確に特定できたのであれば、対応する内容も明確になります。
アプリケーションの修正であったり、ミドルウェアの設定値変更であったり。
緊急度と対応時間とを天秤にかけて、場合によっては一次対応(応急処置)と二次対応(抜本的な対策)を分けるケースもあります。

原因が分からないケース

というのも当然あるので、その際は出力するログを増やすなどして網を張るようにしています。

実例だとこんな感じ

1ヶ月ほど前に起きた事例ですが。

  1. 状況としては「繋がるけどすごく重い」 → OSがハングしているとか、全く手が付けられないわけではなさそう
  2. ssh繋いでみたところ、接続できた → 障害報もないし、ネットワークはあまり関係なさそう
  3. リソースを確認するとロードアベレージが異様に高い → CPU起因だから、どこかで重い処理が走っているとか?
  4. ログを確認すると、httpサーバのログが大量に出ている → アクセスが相当増えた?
  5. アクセスログを精査する → 特定のページに対してアクセスが集中していることが分かった(原因判明)
  6. 特定のページと関連リソース(ページ内の画像)に対して一時的にキャッシュするよう設定変更(対策)

実例その2

こんなケースも。

  1. 「サイトに繋がらない」 → あらゆる可能性あり
  2. ssh繋いでみたところ、接続できた → ネットワークはあまり関係なさそう、OSも大丈夫そう
  3. リソースはどれもおおむね問題なし → 明確な原因が不明
  4. ログを確認するが、どれも平常通り → 明確な原因が不明だけど、httpのプロセスがうまく動作しなくなっているのかもしれない
  5. 応急措置としてhttpサーバを再起動(一時対応)したら復旧した → 引き続き注視しつつ、ログを精査するなどして調査
  6. 特定の処理が重くて落ちた可能性がある → 開発環境で再現するかを検証(原因判明)
  7. 再現したのでアプリケーションを修正してリリース(抜本的な対策)

というわけで

何かものすごいことをやっている話ではないので恐縮なのですが、こんな感じで障害対応していますって話でした。

余談: ログをもっといい感じに可視化して集中管理したい

可視化 + 集中管理の仕組みを設ければ、調査系で呼ばれる回数が減りそうだなーと。
前時代感なまま過ごしていたんですが、この辺をKibanaに集めるような仕掛けをぼちぼち組まねばな、と。

って書いてしまったので、今年の前半はその辺を整備していきます。

*1:100以上のコミットを経て、ようやく落ち着いた。と思う。

cakephp/cakephp にPR 出してmerge された話

(Fusic Advent Calendar 24日目)http://qiita.com/advent-calendar/2016/fusic & (CakePHP3 AdventCalendar 24日目)http://qiita.com/JoJeongMin/items/9fbc4cc1de9268b5de56http://qiita.com/advent-calendar/2016/cakephp3です。

Fusic 新卒の濱野です。
基盤ユニットに配属されてまもなく半年。
周りの席にはその道10年の職人さんが多く座っているので、
いつもつらい気持ちで席についています。

そんな肩身の狭い新卒ですが、
最近少しだけ胸をはれることがありました!

それは、、、

http://bakery.cakephp.org/2016/12/11/cakephp_3310_released.html
f:id:adiboy:20161223210812p:plain

そう。cakephp の core に出したPR が merge されたのです!!!
これはめでたい!!!

ということで、今回は、PR がマージされるまでの模様を時系列に沿ってお伝えしようと思います。
これを機に、PRの数が増えるとうれしいです!!!

何なおしたの?

pagination のバグを修正しました。

$paginate = [
    'limit' => 30,
    'maxLimit' => 20,
];

という設定をした時に、

maxLimit => 20

が無視され、

limit => 30

が採用されていました。
つまり、 maxLimit がちゃんと動いていませんでした。

どうやって見つけたか?

プラグインを作っていたら、挙動がおかしかったのでcore を読みました。
ちなみに、core は極力読むようにしています。
そして、時々ブログなどに結果報告を書いています。

例1
例2

その癖をつけていたおかげで、割とすんなり問題箇所の特定ができました。
そして、何が原因なのかがわかりました。

issue を登録する

こんなissue を登録しました。
https://github.com/cakephp/cakephp/issues/9848

全部英語で書くのが意外と大変でした。

PR を投げる

ついでに、issue に紐付ける形でPR も出しました。

I showed an example to fix this bug in #9849 ,
please review it, and I expect for some comments.
If my PullRequest is not worth to merge, don't hesitate to close it.

って書いて。
超意訳すると、

一応このissue を解決するPR 送りますー  

っていう感じです。

https://github.com/cakephp/cakephp/pull/9849

中の人とやり取りする

PR を出すとすぐ、chinpei215さんが調整してくださいました。
そして、マージされるまで面倒を見てくださいました。
この場を借りてもう一度お礼させて頂きます。
本当に有難うございました。

結局やり取りをしたのは2人でした。
一人は前述のchinpei215さん。
もう一人は、dereuromarkさん。

お二方とやり取りし、コードを修正しました。
そして、気づいたらマージされていました。

PR を出してから Merge されるまで1日もかかりませんでした。

感想

中の人は、優しかったです。(もちろんご指摘も頂きましたが)
そして、社内の人から声をかけられる機会が増えました。
これからも何かあったらどんどんプルリク出していこうと思います。

以上、未経験から入った新人が (cakephp/cakephp)https://github.com/cakephp/cakephp/ にPR を送ってマージされた話でした!

FluentdのログフォーマットでS3に保存されたApacheのアクセスログをAmazon Athenaで集計する

突然の Amazon Web Services Advent Calendar 2016 の 15日の記事です

基盤ユニットの小山 ( @k1LoW )です。

AWS re:Invent 2016すごかったですね。

数多くのサービスが使える形でリリースされてきました。

ただ、個人的にはその後の aws-sdk-ruby が v3に上がる というエントリーを見て、awspecをどうしようか戦々恐々としています。

突然のアクセスログ集計

あるAWS上に構築しているシステムプロジェクトで、突然「月単位でのアクセス集計1年間分」という要望がどこからともなく降ってきました。

そのプロジェクトでは、アクセスログを含む様々なメトリクスをFluentd ( td-agent ) で収集して、S3のバケットに保存しています。

ただ、保存の目的がいざという時のためで、稼働している分析基盤はありませんでした。

そこで、まずはローカルのMacBook ProでDigdag+MySQLによる集計を試みました。

が、

1日立ってもログ取得が終わらず。。。

(そういえば今まではdstatのような定期的に取得するメトリクス情報のログ集計で、アクセスログのようなさらに大量のデータの取得はしていなかった。。。)

さてどうしようかとなった時に、ふと思い出したのが、そう、Amazon Athenaでした。

そうだ、Amazon Athena を使ってみよう

f:id:k1LoW:20161214200312p:plain

aws.amazon.com

Amazon Athena、ざっくり紹介するとマネージドなPrestoです(ざっくりすぎる)。

AWS提供で、S3との相性がとてもよさそうなので、もしかしていけるのでは?と思って試してみたらできました。

前提

アクセスログは s3://[bucket-name]/access_logs/[ec2-hostname]/[year]/[month]/[day]/access_log.xxxxx.xxx.xxx.gz みたいに保存されています。

S3のバケット自体はap-northeast-1 (Tokyoリージョン)にあります(Amazon Athena自体はTokyoリージョンではまだ提供されていませんが、S3バケットの指定はできますよ!)。

実際のアクセスログはFluentdの一般的な(?)ログフォーマットで、

2016-12-19T04:35:27Z ip-10-xx-xxx-xxx    {"host":"xxx.xxx.xxx.xxx","user":"-","method":"GET","path":"/path/to/?q=query","code":"200","size":"1234","referer":"-","agent":"Some User-Agent"}

というような、タイムスタンプとhostnameとJSONの複合形式です。

テーブルの作成

本来ならば「Add Table」 リンクを押してデータベースの作成からするほうがいいのですが、今回は

Query Editorで、おもむろに以下のクエリを実行して集計用テーブルを作成しました。

CREATE EXTERNAL TABLE IF NOT EXISTS default.access_logs (
  date date,
  hour int,
  min int,
  second int,
  z string,
  host string ,
  ip string,
  user string,
  method string,
  path string,
  code int,
  size int,
  referer string,
  agent string
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
WITH SERDEPROPERTIES (
  'serialization.format' = '1',
  'input.regex' = '^(.+)T(\\d+):(\\d+):(\\d+)(.+)\\t([^\\s]+)\\t\\{"host":"([^"]+)","user":"([^"]+)","method":"([^"]+)","path":"([^"]+)","code":"([^"]+)","size":"([^"]+)","referer":"([^"]+)","agent":"([^"]+)"\\}'
) LOCATION 's3://[bucket-name]/access_logs/'

ポイントは 'input.regex' = '^(.+)T(\\d+):(\\d+):(\\d+)(.+)\\t([^\\s]+)\\t\\{"host":"([^"]+)","user":"([^"]+)","method":"([^"]+)","path":"([^"]+)","code":"([^"]+)","size":"([^"]+)","referer":"([^"]+)","agent":"([^"]+)"\\}' でFluentdのログフォーマットに合わせた正規表現を設定しているところです。

集計SQLの実行

ここからは簡単です。

1クエリごとに小さくない金額がかかりますが、突然の依頼なので悠長なことは言っていられません。

そこは札束で殴るように

SELECT MONTH(date) AS month, count(*), SUM(size) AS total_size
FROM rkb_web_public_access_logs
WHERE host IS NOT NULL
        AND date >= CAST('2016-01-01' AS DATE)
GROUP BY  MONTH(date) 
ORDER BY total_size DESC

などと、フルスキャンでがっつり集計などしました。

まとめ

Amazon Athenaは思った以上に気軽に使えました。

ただ、クエリごとに課金されるので、ご利用は計画的に。

突然のアクセスログ集計などには良いと思います。

よい突然ライフを。


おまけ

Dockerで開発環境・テスト環境を作る

こんにちは、2回目の登場になります。
基盤ユニットの櫻川です。

みなさんはDockerを利用してるでしょうか?

Fusicではまだまだ開発環境は Vagrantを複数立てる が主流ですが、 今はDockerの布教活動を行っている真っ最中です。

そもそもDockerを導入した目的

目的は 複数PHPのバージョンを同時に起動したい! です。

というのも、Fusicでは受託開発を行っていることもあり、プロジェクト毎に利用するPHPのバージョンやデータベースの種類・バージョンが異なること多いです。

そのため現在ではプロジェクト毎等でVagrantを新規で立ち上げたり、phpbrewを利用してPHPバージョンを切り替えたりして開発を行っています。

基本的にVagrantとphpbrewで複数PHPを利用することは可能だったのですが以下のような不満もありました。

  • Vagrant
    • 起動に時間がかかる
    • 複数起動すると結構重くなる
  • phpbrew
    • バージョン切り替えにApacheの設定を変える必要がある
    • 同一サーバー内で同時に複数バージョンを起動できない

そこで全てを解決してくれるDockerの出番なわけですよ!

利用している環境

Windowsです。
ただ、Docker自体はVM上のCentOS7で実行しているのでMacでも問題ないと思います。

  • Windows
  • Vagrant
  • Hyper-V
  • CentOS7(ホストOS)
    • Apache(リバースプロキシ用)
  • Docker + Docker Compose
    • Apache + PHP
    • Postgres
    • MySQL
    • samba

Dockerの構成

Dockerのコンテナをポート転送を設定して、最低でも3台のコンテナを起動しています。 ※必要なPHPのバージョン分 + データベース(Postgres or MySQL) + samba

この時点で「複数のPHPバージョンを同時に触りたい」という目的は達成しています。

ただし、このままだとDockerのポート転送を使っているので、PHPにアクセスするときのURLが http://example.com:8080/hoge/fuga というようにポート指定が必要になってきます。

ポート指定 をするのは嫌なのでDockerコンテナの前にリバースプロキシを置くことでポート指定をすることなく複数のPHPにアクセスすることを実現しています。
これで完全に目的達成!

また、ファイルの修正自体はsambaを経由して行っています。

f:id:sakutarou:20161201003230p:plain

どうやって作るの?

1. Dockerインストール

DockerをホストOS(CentOS7)にインストールします。

tee /etc/yum.repos.d/docker.repo <<-'EOF'
[dockerrepo]
name=Docker Repository
baseurl=https://yum.dockerproject.org/repo/main/centos/7/
enabled=1
gpgcheck=1
gpgkey=https://yum.dockerproject.org/gpg
EOF

yum install docker-engine
systemctl enable docker.service
systemctl start docker

2. sambaコンテナを立てる

samba用コンテナをCentOS6で起動します。
※dockerコンテナ内のsambaの設定は行ってください。
 yum install samba など
※ホストOS上の /var/www/html をsambaコンテナでマウントしています

docker run -itd --name samba -p 139:139 -p 445:445 -v /var/www/html:/var/www/html centos:6 /bin/bash

3. Postgresコンテナを立てる

Postgres用イメージを利用してPostgresコンテナを起動します。
MySQLでもかまいません。
{Postgresパスワード} はパスワードを設定してください

docker run --name postgres -e POSTGRES_PASSWORD={Postgresパスワード} -d -p 5432:5432 -e PGDATA=/var/lib/postgresql96/data postgres

4. Apache + PHPコンテナを起動する

Apache + PHPコンテナをCentOS6で起動します。
※dockerコンテナ内のApache + PHPの設定は行ってください。

PHPの必要なバージョン分コンテナを起動します。

docker run -itd --name PHP -p 8080:80 -p 443:443 --link postgres --volumes-from=samba centos:6 /bin/bash

5. ホストOS上でリバースプロキシを設定する。

ホストOSにApacheをインストールし、リバースプロキシを設定します。
※コンテナ上にApacheを立ててリバースプロキシを行ってもいいのですが、dockerを知らない人でも触りやすいようにホストOS上にApacheをインストールしています。

PHPを複数起動したいので、実際はVertualHostと組み合わせています。

ProxyRequests Off
ProxyPass / http://hoge.example.com:8080/
ProxyPassReverse / http://hoge.example.com:8080/

6. イメージをAmazon ECR上に保存する

実行しているDockerコンテナをイメージ化して、ECR上に保存してます。

  • ECR上にリポジトリを構築しておいてください。
  • aws cliをインストールしておいてください。
docker commit samba samba
docker commit php

aws ecr get-login --region ap-northeast-1
出力されたログインコマンドを実行

docker tag samba 発行されたECR用sambaリポジトリURL
docker tag php 発行されたECR用phpリポジトリURL

docker push 発行されたECR用sambaリポジトリURL
docker push 発行されたECR用phpリポジトリURL

最後

上記を実行することで最低限のPHP開発・テスト環境を構築することができます。
ただ、公開環境で起動する場合は公開するポート等セキュリティに注意してください。

また、このままだと起動するのが非常に手間なので、Dockerfile + Docker Composeにまとめています。

Dockerを使ったことない人は是非!