- 本番環境にDockerを導入し、Dockerのメリットである不変性を利用してWebアプリのローカル開発環境を整えたときのノウハウメモ。
- Beanstalkを使っていますがBeanstalkのことはここには書いてません。
- 実際に作ったWebアプリは↓こんな感じ
項目 | 内容 |
---|---|
概要 | Webアプリケーション。シングルページアプリ。 |
環境 | AWS, ElasticBeanstalk |
サーバーサイド言語 | Java, gradle |
フロントエンド言語 | ReactJs, Gulp |
キャッシュ | Redis |
DB | mariadb10系 |
作るコンテナ
- サンプルとして2つのコンテナを作成することにします。作成するコンテナは以下の2つ。
- frontendコンテナがアクセスを受け付けて、apiへのアクセスだけをbackendコンテナへプロキシします。
コンテナ名 | 用途 | OS | ポート |
---|---|---|---|
backend | サーバーサイド側(Java)を実行するためのコンテナ | alpineLinux | 8080 |
frontend | フロントエンド側(React,HTML)を実行するためのコンテナ | alpineLinux | 443 |
フォルダ構成
- backendコンテナを例にあげます。基本的に
base
とput
に別れます。 - それぞれのフォルダにDockerfileが存在します。
-/
|- backend
|- base
| |- Dockerfile
| |- ***.conf
|- put
|- Dockerfile
baseで行っていること
- プロジェクトに必要なミドルウェア類のインストールや、設定ファイル(conf等)のCOPYを行います。
- baseフォルダには独自に以下のルールを設けています。
-
RUN
は1回のみ。&&
で繋げる。 - 変更があるものを入れない。(confで都度変更しなければならない場合はbaseには入れない)
-
こんな感じ
FROM alpine:3.3
RUN apk --update add openjdk8-jre \
&& rm -rf /var/cache/apk/* \
&& mkdir -p /var/log/project /project \
&& cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
putで行っていること
-
base
でビルドしたものに対してプロジェクトの注入を行います。 - putフォルダには独自に以下のルールを設けています。
- RUNは極力書かない。(自分のチームでは
put
フォルダにRUNは書かれていません) - 極力、
FROM
,COPY
,EXPOSE
,CMD
の4行だけにする。 - このフォルダにあるものは絶対に人の手ではビルドしない。
- 自分のチームではputのビルドをJenkinsでビルドしています。
- RUNは極力書かない。(自分のチームでは
FROM ↑で作ったコンテナ
COPY project.jar /opt/project.jar
EXPOSE 8080
CMD ["java","-jar","/opt/project.jar"]
全体的にはこんな感じ
- リポジトリに格納されているフォルダ構造としてはこんな感じになります。
-/docker-codes
|- backend
| |- base
| | |- Dockerfile
| |- put
| | |- Dockerfile
|- frontend
|- base
| |- Dockerfile
| |- ssl.key
| |- ssl.pem
| |- nginx.conf
| |- service.conf
|- put
|- Dockerfile
ローカル開発環境として動かすには
- ローカルでは
docker-toolbox
を使用して動かします。 - 上記の
put
の役割を docker-compose で代用して動かします。
putフォルダを適用しない状態でどうやってローカルで動かすのか
- こんな感じで
docker-compose
で代用できます。
項目 | 内容 |
---|---|
プロジェクトファイルの COPY
|
docker-composeでディレクトリをマウントさせます |
EXPOSE 設定 |
docker-compose のportsでローカルの docker-machine にポートを紐付けます |
CDM 設定 |
docker-compose のcommand かentrypoint で対応 |
- たとえば以下の
dockerfile
の場合
FROM registry.example.com/backend-base-image:1.0
COPY project.jar /opt/project.jar
EXPOSE 8080
CMD["java","-jar","/opt/project.jar"]
- こんな感じの
docker-compose
になります。
docker-compose.yml
backend:
hostname: backend
image: registry.example.com/backend-image:1.0
volumes:
- /opt/project-backend:/opt
ports:
- "8080:8080"
links:
- mariadb:mariadb #データベースが必要な場合。
- redis:redis #redisキャッシュサーバーが必要な場合
entrypoint:
java -jar /opt/project.jar
#---------------
#実際には複数のコンテナで動かすと思うのでfrontendコンテナがある場合は以下のように記述されると思います。
#---------------
frontend:
hostname: frontend
image: registry.example.com/frontend-image:1.0
volumes:
- /opt/project-frontend/public:/opt
ports:
- "443:443"
links:
- backend:backend
entrypoint:
/usr/sbin/nginx -g 'daemon off;'
mariadb:
.........
redis:
.........
- このように
docker-compose.yml
を組み立てて、baseでビルドしたコンテナをローカル開発環境として使用します。
まとめ
- ビルドを
base
とput
に分けてそれぞれでビルドする。 -
base
でビルドしたものをローカルの開発環境として使う。 - ローカルでは
put
でビルドする代わりにdocker-composeで工夫する。
最後に
- この構成のほうがイケてるなどありましたら教えて下さいm(__)m