DockerfileをGitで管理してElastic Beanstalkでデプロイする

Elastic Beanstalk

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

森永です。

ElasticBeasntalkとDockerを組み合わせると色々と夢が広がります。
Dockerでアプリケーションの実行環境を構築し、EBでAWS環境を構築して実行環境とアプリケーションをまるっとデプロイします。 これが出来るとまったく同じ環境をいくつでも作成できるようになります!

Dockerのコンテナを作成する方法はいくつかあるのですが、今回はコンテナの設計書となるDockerfileを使い作成します。 Dockerfile自体はただのテキストファイルなのでgitで管理すると捗りますし、EB CLIは公式にgitとの連携をサポートしていますので、非常に簡単に使用することが可能です。

前準備

Macで作業していきます。(OS X Yosemite Ver.10.10.3)

必要な物をインストールしておきましょう。

Macであればデフォルトでgitがインストールされているので特に問題はないかと思います。
必要に応じてアップデートして下さい。
AWS CLIとEB CLIに関してはこちらの記事を参考に、クレデンシャルの設定まで完了させておいて下さい。
プロファイルを分けておくと複数のアカウントを使いまわせるので非常に便利です。

使用できることを確認しておきます。

$ git --version
git version 2.4.3
$ aws --version
aws-cli/1.7.34 Python/2.7.6 Darwin/14.3.0
$ eb --version
EB CLI 3.4.5 (Python 2.7.6)

バージョン情報が出ればOKです。

Gitローカルリポジトリ作成

まずは、gitのローカルリポジトリを作成します。
ここが、EBでデプロイするプロジェクトともなります。
お好きなところにディレクトリを作成して、その中でgitリポジトリの初期化を行います。

$ mkdir eb-docker
$ cd eb-docker
$ git init
Initialized empty Git repository in /Users/morinagataishi/git/eb-docker/.git/
$ ls -al
total 0
drwxr-xr-x  3 morinagataishi  staff  102  6 15 16:42 .
drwxr-xr-x  8 morinagataishi  staff  272  6 15 16:40 ..
drwxr-xr-x  9 morinagataishi  staff  306  6 15 16:42 .git

.gitというディレクトリができていたらローカルリポジトリ作成成功です。

EBプロジェクトの作成

次にこのディレクトリをEBのプロジェクト(EBでデプロイするディレクトリ)として設定します。 といっても、eb initコマンドを実行して、対話的に進めていくだけです。

$ eb init

Enter Application Name
(default is "eb-docker"): # アプリケーション名を入力します。既存のアプリがある場合は選択肢が出ます。
Application eb-docker has been created.

Select a platform.
1) PHP
2) Node.js
3) IIS
4) Tomcat
5) Python
6) Ruby
7) Docker
8) Multi-container Docker
9) GlassFish
10) Go
(default is 1): 7 # 今回はDockerなので7を選択しますが、別のプラットフォームでもgit管理できます。
Do you want to set up SSH for your instances?
(y/n): y # SSHログインする場合は"y"を選択します。

Select a keypair.
1) cm-morinaga
2) [ Create new KeyPair ]
(default is 2): 1 # SSHログインする際のキーペアを選択します。

$ ll
total 8
drwxr-xr-x  5 morinagataishi  staff  170  6 15 17:03 .
drwxr-xr-x  8 morinagataishi  staff  272  6 15 16:40 ..
drwxr-xr-x  3 morinagataishi  staff  102  6 15 17:00 .elasticbeanstalk
drwxr-xr-x  9 morinagataishi  staff  306  6 15 16:42 .git
-rw-r--r--  1 morinagataishi  staff  108  6 15 17:03 .gitignore

.elasticbeanstalk.gitignoreが作成されています。
.gitignoreを覗いてみると

# Elastic Beanstalk Files
.elasticbeanstalk/*
!.elasticbeanstalk/*.cfg.yml
!.elasticbeanstalk/*.global.yml

となっており、.elasticbeanstalkディレクトリはgit管理から除外されています。
ただし、.cfg.yml.global.ymlの拡張子のファイルだけはgitで管理されます。
EBの設定でバージョン管理したいものについてはこの拡張子を設定するようにしましょう。

Dockerfileの作成

今回はテストで、Apacheをインストールしてページを閲覧できるようにしてみます。

$ vi Dockerfile
FROM ubuntu:12.04

MAINTAINER morinaga

# Apacheインストール
RUN apt-get update
RUN apt-get install -y apache2

# 環境変数設定
ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_LOG_DIR /var/log/apache2
ENV APACHE_LOCK_DIR /var/lock/apache2
ENV APACHE_PID_FILE /var/run/apache2.pid

# アプリ(今回はHTMLファイル)配置

ADD . /var/www

# コンテナポート開放
EXPOSE 80

# apacheの起動
CMD ["/usr/sbin/apache2", "-D", "FOREGROUND"]

これでちゃんとコンテナを作成できるのかをローカルでビルドしておくことをオススメします。
こちらを参考に、boot2dockerをインストールしてローカルでビルドが通ることを確かめましょう。

$ boot2docker up
Waiting for VM and Docker daemon to start...
............oooo
Started.
(省略)
$ docker build -t eb-docker .
Sending build context to Docker daemon 34.82 kB
Sending build context to Docker daemon
Step 0 : FROM ubuntu:12.04
12.04: Pulling from ubuntu
(省略)
Successfully built e9c3b321a829

Successfully built ******が出ればDockerfileとして正しくビルド出来ます。

boot2docker上のDockerがバージョン1.6以上であれば、eb local runも使用できます。

$ eb local run
12.04: Pulling from ubuntu
(省略)
Successfully built c1a929ac5512

boot2docker上で動くのは変わりません。

環境作成

Dockerfileの準備が出来ましたので、早速EBで環境を作っていきましょう。

ただ、このまま環境構築してもDockerfileしかデプロイされないので一緒にデプロイするアプリを作成します。
といってもただのHTMLです。テストなのでご容赦下さい。

$ echo 'test' > index.html

では、気を取り直してEBで環境を作っていきます。
EBをGitと連携すると、GitでcommitされたファイルだけがEBでデプロイされます。 なので、先にGitでCommitをしてからEBの操作を行います。

まずはデプロイ対象のファイルをコミットします。

$ git add Dockerfile index.html
$ git commit

続いて、EBで新規環境を構築します。dev-envという名前で作成します。

$ eb create dev-env
Creating application version archive "ad0f".
Uploading eb-docker/ad0f.zip to S3. This may take a while.
Upload Complete.
(省略)
INFO: Successfully launched environment: dev-env

INFO: Successfully launched environment: 環境名で環境構築成功です!

以下のコマンドで、作成した環境にアクセスが出来ます。

$ eb open

デプロイ

次に、アプリケーションの更新を行ってからのデプロイを行ってみます。
先ほどとの違いはeb createではなくeb deployを使用することだけです。

$ echo 'test-dev' > index.html
$ git add index.html
$ git commit
$ eb deploy
Creating application version archive "35de".
Uploading eb-docker/35de.zip to S3. This may take a while.
Upload Complete.
(省略)
INFO: Environment update completed successfully.

完了したらeb openしてみましょう。デプロイされたことがわかると思います。

dev

環境の切り替え

このGit+EBの連携の利点はアプリケーションやDockerfileのバージョン管理出来る他に、ブランチを作成して環境を切り替えられる事にあります。
先ほどまで、dev-envMasterブランチに作成していました。
ここでprdブランチを作成し、prd-envを作成してみましょう。

prdブランチを作成し、チェックアウトします。

$ git branch prd
$ git checkout prd
Switched to branch 'prd'
$ git branch
  master
* prd

アプリケーションを本番仕様にして、Gitでコミットします。

$ echo 'test-prd' > index.html
$ git add index.html
$ git commit

この状態でprd-env環境を構築します。

$ eb create prd-env
Creating application version archive "99c7".
Uploading eb-docker/99c7.zip to S3. This may take a while.
Upload Complete.
(省略)
INFO: Successfully launched environment: prd-env

eb openしてみるとprd用のアプリになっていることが分かります!

prd

GitとEBの連携は環境作成時以外にもeb useを使用することで可能です。 以下のコマンドで、masterブランチにprd-env環境を結びつけることが出来ます。 既存のEB環境をGitで管理したい場合にはこちらを使用しましょう。

$ git checkout master
$ eb use prd-env

さいごに

GitとEBの連携をするとバージョン管理、環境の切り替えが非常に用意になります。
今回はアプリケーションだけデプロイという形でしたが、Deckerfileを変更することで開発、本番で違った環境を作成可能です。

ただし、Dockerfileでの環境構築には問題があります。
一つは構築が遅いことです。 構築の遅さは、コマンドを一個一個実行して、ダウンロードして、というのをビルド時に行っているのが原因です。

もう一つは、冪等性を担保できないことです。 パッケージインストールのタイミングによってyumaptはバージョンが変わります。
それ以外にも、Dockerfileの記述が増えれば冪等性を保つのはどんどん難しくなってきます。

これを回避する方法として、Dockerのイメージをビルドした状態で保管しておき、イメージをデプロイするということが考えられます。
既にビルドされているので、Dockerfileより早く、冪等性も担保できます。
ただ、イメージを保管するためのレジストリを用意する必要がありますので、状況に応じて使い分けましょう。 (公開のRegistryとしてDocker HubDocker Hubがあります。ただし無償版ではPublicのイメージになります。GitHubと同じ感じですね。)

参考文献

EB CLI 3.x - Elastic Beanstalk

AWS Cloud Roadshow 2017 福岡