一からAPIサーバの開発フローを作った話〜コンテナ編


去年、「[一からマイクロサービスの開発フローを作った話](https://qiita.com/tomoyamachi/items/0f049c87bfdef4aa6ad9)」という記事を投稿した。
今回、また新しく割と大きめのプロジェクトに関われたので、コンテナ管理で開発〜運用フローを3ヶ月でつくった。 忘れる前に、記録を残そうと考えている。

今回は、「サービスの構成」について。なお、前回はAWSだったが、今回はGCPを利用した。AWSに比べサービスが少ないが、CUIがわかりやすく料金も割安なことが多いので、特に不便はない。

※ 2019/5/21 追記
いまであれば、脆弱性検知ツールの trivy もCIに組み込むと思う。
[フロントエンドでもtrivyを使って脆弱性対策したい！](https://qiita.com/tomoyamachi/items/e0394e9bcfeb90543e97) に導入方法を記載した。

# だいたいの構成
- nginx
- php 7.1.9
	- OPcache, APCu, Phalcon, オレオレフレームワーク
	- NewRelic APM : パフォーマンス測定で利用
	- BlackFire : プロファイリングで利用
- redis, MySQL, ElasticSearch
- Firebase RDB : [Firestore](https://firebase.google.com/docs/firestore/)に乗り換えたい 
- fluentd : ログを集約。本番(GAE)では勝手に作成される
- ruby + cucumber : 自作のAPIテストライブラリを利用

現在、ローカルでの開発やクローズドテストの際はdocker-composeで構築し、それ以外はGoogleAppEngine(GAE)で運用している。
いずれそれぞれの比較記事とサンプルを動かすまでの記事書きたい。

# 開発環境の構成 (ローカル開発, テスト)

![docker-local-environment.jpg](https://qiita-image-store.s3.amazonaws.com/0/14275/ff36c474-673f-2927-9b3c-a9e3b5baad21.jpeg "docker-local-environment.jpg")

ローカルでの開発時は、docker-composeを利用している。
初期にdocker-composeを利用していたので、そのまま。

## docker-composeについて

- 良い点
	- 手軽に始められる
		- 最近はDockerをインストールするだけで、docker-composeがついてくることが多い
	- ボリュームマウントが楽にできる
- 悪い点
	- スケーラブルではないので、そのまま本番では利用できない

最近GAEに環境を移したので、[GAEのローカル環境で構築](https://cloud.google.com/appengine/docs/standard/python/tools/using-local-server)を準備中。
追記 : ローカル環境ではGAEのstandard環境しか再現できないため、php5.5のみが利用可能


## 補足事項
### 開発環境
- ネット環境がなくても開発ができる
- すべてのログをfluentdコンテナに集約
- MySQL, Redis, ElasticSearchはボリュームマウントして、データを永続化

### コンテナ容量削減
- PHPプロジェクトを2つに分けた
	- 利用に最低限必要なプロジェクト(FPM経由で動作するもの)
	- CIをしていく上で利用するものに関するプロジェクト
		- コードチェック、ユニットテスト etc。[以前の開発フロー](https://qiita.com/tomoyamachi/items/0f049c87bfdef4aa6ad9#開発フロー)とほぼ同じ
		- ローカルでのテスト以外では利用しない


### テスト
- ユニットテスト時はCI用プロジェクトを含めて実行
- 結合テスト時(nginx経由)は、API用プロジェクトのみで実行
- [前回](https://qiita.com/tomoyamachi/items/0f049c87bfdef4aa6ad9)同様、APIの結合テスト(ブラックボックステスト)をまったく別のネットワークで利用
	- docker-composeのnginxのポートを指定して、そこに対して接続する形


## その他の工夫
- コンテナに慣れていない人は、docker-composeでの操作でも迷うので、最初に質問が多かった
	- スクリーンキャプチャでチュートリアル動画をつくり、みんなに配布


# 本番環境 (dev, stg, prod)

![prod-environment.jpg](https://qiita-image-store.s3.amazonaws.com/0/14275/5aacf237-9fe4-f9c7-c7e4-98c77e8d4883.jpeg "prod-environment.jpg")

先日PHP7.1が安定版になったので、現在はGAE(Google App Engine)を利用して運用している。

## GAEについて
- 良い点
	- 自動でバージョン管理 / スケーリングをしてくれる
	- セキュリティなどもとにかく任せておけばいいという安心感
	- SSLが無料で、メンテナンス不要
	- Stackdriver(ログ管理サービス)との連携が楽
- 悪い点
 	- GCEに比べると割高になりやすい
	 	- コンピュート単位で課金されるので場合による
	- デバッグしづらい
		- コンテナにログインすること自体が非推奨
	- 利用できる言語に限りがある
	- ドキュメントが古いことがあるし、ドキュメントにないこともある


## 補足事項
- App Engine Flexibleを利用
- PHPを利用しているが、php7.1用のphalconや、newrelicを入れる都合で、customランタイムを利用してDockerfileから構築している
- 環境ごとに定数、php.ini、Googleのプロジェクトなどが分かれるため、各設定ファイルを環境ごとに分けた
	- 以下のようなMakefileを作成し、 `make deploy ENV={env} VERSION={version}` だけでdeployするように設定

```
prod: Dockerfile.prod
	cp -f $(PROJECT_DIR)/Dockerfile.prod $(PROJECT_DIR)/Dockerfile
stg: Dockerfile.stg
	cp -f  $(PROJECT_DIR)/Dockerfile.stg $(PROJECT_DIR)/Dockerfile
dev: Dockerfile.dev
	cp -f $(PROJECT_DIR)/Dockerfile.dev $(PROJECT_DIR)/Dockerfile

# 環境に応じたapp.yaml, Dockerfileを利用
deploy: ${ENV}
	gcloud app deploy app-${ENV}.yaml --version v${VERSION} --project project-${ENV}

```
もっとよい方法があるはずなので、知見を得たい…

# よもやま話
探りながらの開発だったので、かなり紆余曲折あった。
徐々にコンテナとGCPに慣れたおかげもあり、どんどん環境構築にかける時間が短くなっているのが振り返ると分かる。

7月半ば : 最初は手軽にできるdocker-composeで環境を整える(7日)
↓
9月上旬 : そろそろ本番環境つくらなくては...
↓
Kubernetesを利用して本番環境を作成(5日)
↓
10月上旬 : Google App EngineでPHP7.1が正式リリース
↓
Google App Engineでdeployまでのフローを作成(2日)

# まとめ
開発フローとタイトルにありながら、開発フローの話にはいれていない。
次回は開発フローの話に書きたい。