Dockerであそぶ(10)docker-machineを使ってAWS(EC2)にDockerホストを構築する


ここ1,2年で注目を集めている仮想化技術の1つ「Docker」について、今更感がありますが試していきたいと思います。
他の仮想化技術との違いや特徴、開発環境として使っていくにはどうすればいいかなどを紹介していきたいと考えています。

これまでの連載

はじめに

前回はEC2インスタンスを作成し、そこにdockerツール群をインストールしてこれまでに作成してきたコンテナを動かしてみました。
しかしdockerにはこれらのdockerホストを自動で作成することができる仕組みが備わっています。前回も登場したdocker-machineというコマンドがそれに当たるのですが、このツールを使用することで複数のdockerホストを一元管理することが可能になり、管理コストの削減につなげていくことが可能です。

今回はこのdocker-machineコマンドを使用して、ローカルマシンからEC2上にdockerホストを構築、さらにコンテナを動作させるところまで行っていきたいと思います。

IAM (Identity and Access Management) Administratorユーザーの作成

ローカルマシンのdocker-machineコマンドでEC2上にアクセスするためには、Administorator権限を持たせたIAMユーザーのAWS Access Key IDおよびAWS Secret Access Keyが必要になります。
AWSの操作は本連載の趣旨ではないと考えますので詳細は割愛しますが、以下のサイトが非常に参考になりました。

AWSアカウント作ったらこれだけはやっとけ!IAMユーザーとAuthyを使ったMFAで2段階認証

IAMユーザーを作成する際に、アクセスキーおよびシークレットアクセスキーをCSVファイルでダウンロードできたと思います。
アクセスキーはAWS上から確認することが可能ですが、シークレットアクセスキーに関しては再ダウンロードできないようですので紛失してしまった方は以下の画面から新しいアクセスキーを作成しておいてください。

screencapture-console-aws-amazon-com-iam-home-1457008921867

docker-machineを使ってEC2インスタンスを作成する

以下のオプションを指定してdocker-machineコマンドを実行します。

オプション オプション値 概要
–driver amazonec2 使用するサービスを指定します。Supported Drivers
–amazonec2-access-key アクセスキーを指定 上記で取得したIAMアクセスキーを指定します
–amazonec2-secret-key シークレットキーを指定 上記で取得したIAMシークレットキーを指定します
–amazonec2-region ap-northeast-1 インスタンスを作成するアベイラビリティーゾーンを指定します。値は東京リージョン
–amazonec2-subnet-id サブネットID 作成するインスタンスのネットワークを設定します。どちらか一方のオプションのみ指定すればOKです。
–amazonec2-vpc-id VPC-ID
–amazonec2-security-group docker-machine セキュリティグループを指定します。TCP2376ポートは必ず開放しておく必要があります。
$ docker-machine create --driver amazonec2 \
--amazonec2-access-key AKIXXXXXXXX \
--amazonec2-secret-key T3ZbtjDrVKFVXXXXXXXXXXXXXXXXXXXXXXXXX \
--amazonec2-region ap-northeast-1 \
--amazonec2-subnet-id subnet-acaa81d8 \
--amazonec2-security-group docker-machine \
aws-sandbox

Running pre-create checks...
Creating machine...
Waiting for machine to be running, this may take a few minutes...
Machine is running, waiting for SSH to be available...
Detecting operating system of created instance...
Provisioning created instance...
Copying certs to the local machine directory...
Copying certs to the remote machine...
Setting Docker configuration on the remote daemon...
To see how to connect Docker to this machine, run: C:\Program Files\Docker Toolbox\docker-machine.exe env aws-sandbox

これで作成できました。
AWSコントロールパネルを確認するとaws-sandboxというインスタンスが作成されているのがわかります。
screencapture-ap-northeast-1-console-aws-amazon-com-ec2-v2-home-1457054462189

サブコマンドのlsを使用すると登録されているdockerホストを確認することができます。
ACTIVE欄に「*」がついているホストが現在操作ターゲットになるdockerホストになります。
この状態でdocker-composeなどを実行するとdefault、つまりローカルマシンにインストールされたvirtualboxに対してコマンドが実行されることになります。

$ docker-machine ls
NAME          ACTIVE   DRIVER       STATE     URL                         SWARM
aws-sandbox   -        amazonec2    Running   tcp://52.193.xxx.xxx:2376
default       *        virtualbox   Running   tcp://192.168.99.100:2376

ACTIVEを切り替えるにはサブコマンドenvで出力される環境変数をそのままローカルマシンに設定すればOKです。

$ docker-machine env aws-sandbox
export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://52.193.xxx.xxx:2376"
export DOCKER_CERT_PATH="C:\Users\sudoy\.docker\machine\machines\aws-sandbox"
export DOCKER_MACHINE_NAME="aws-sandbox"
# Run this command to configure your shell:
# eval "$(C:\Program Files\Docker Toolbox\docker-machine.exe env aws-sandbox)"

$ eval "$(docker-machine env aws-sandbox)"
$ docker-machine ls
NAME          ACTIVE   DRIVER       STATE     URL                         SWARM
aws-sandbox   *        amazonec2    Running   tcp://52.193.xxx.xxx:2376
default       -        virtualbox   Running   tcp://192.168.99.100:2376

コンテナを作成/起動する

いよいよコンテナを作成/起動してみます。コマンドは前回登場したdocker-compose up -dでよいのですが、docker-compose.ymlは若干修正する必要があります。

my-mariadb:
  image: mariadb:latest
  environment:
    - MYSQL_ROOT_PASSWORD=root
    - MYSQL_DATABASE=docker
    - MYSQL_USER=docker
    - MYSQL_PASSWORD=docker
  ports:
    - "3306:3306"

my-php:
  # image: my-php
  build: ./php
  ports:
    - "80:80"
  volumes:
    # - /c/Users/sudoy/Documents/docker/techpjin-lamp/php/public-html:/var/www/html 
    # - /home/ec2-user/techpjin-lamp/php/public-html:/var/www/html # 修正前
    - /home/ubuntu/public-html:/var/www/html # 修正後
  links:
    - my-mariadb

my-phpmyadmin:
  image: phpmyadmin/phpmyadmin
  ports:
    - "8080:80"
  links:
    - "my-mariadb:db"

では、コンテナを作成/起動してみましょう。カレントディレクトリをdocker-compose.ymlファイルのあるフォルダに切り替えてから、docker-composeコマンドを実行します。

$ cd ~/Documents/docker/techpjin-lamp
$ docker-compose up -d

以下のURLが正常に表示できることを確認しましょう。

  • http://ec2-xxxxx.compute.amazonaws.com/
  • http://ec2-xxxxx.compute.amazonaws.com/db.php
  • http://ec2-xxxxx.compute.amazonaws.com:8080/

index.phpやdb.phpへのアクセスがうまくいかないかと思います(phpMyAdminへのアクセスはうまくいくと思います。)。これはdockerホスト側にソースファイルを持っているため、今作成したEC2ホストにはまだそれらのファイルが存在していないことが原因です。
docker-compose.ymlに記述した/home/ubuntu/public-htmlにローカルホスト上のファイルを転送しましょう。
docker-machineのサブコマンドscpを使うと転送することができます。

$ docker-machine scp -r php/public-html/ aws-sandbox:/home/ubuntu/public-html/
db.php                                                            100%  601     0.6KB/s   00:00
index.php                                                         100%   17     0.0KB/s   00:00

改めてindex.phpとdb.phpにアクセスしてみましょう。
今度は正しく表示することができたかと思います。

ソースファイル自体も本来はコンテナ(イメージ)の中に入れてしまうのがベターな気がしますが、仮にEC2を本番環境と見立てた場合にどのようにコンテナの中にそのソースを入れるのがよいのでしょうか。。。
開発環境と本番環境はできるだけコンテナ(イメージ)は共通のものにしておきたいですので、単にDockerfileを修正するというわけにはいかないのでないかと考えています。環境に依存するファイルとしてはdocker-compose.ymlがありますので、この中でコンテナ(イメージ)中にソースプログラムをダウンロードもしくはコピーする設定を記述できればいいのですが。(何かいい方法が思いついたらまた本連載の中で紹介していきたいと思います。)

補足:docker-compose up -dでエラーが発生する

「docker-compose up -d」時に以下のようなエラーが発生し、コンテナの作成に失敗してしまうことがあるかもしれません。

$ docker-compose up -d
・・・ 中略 ・・・
Failed:
  httpd.x86_64 0:2.4.6-40.el7.centos

Complete!
ERROR: Service 'my-php' failed to build: The command '/bin/sh -c yum -y update &&     yum -y install httpd php' returned a non-zero code: 1

これはEC2(dockerホスト)で使用されているストレージドライバーのaufsに不具合があるからのようです。ストレージドライバーを変更するか、my-phpコンテナで使用しているイメージをcentos:latestからcentos:6に変更することで解決することができます。

ストレージドライバーを変更するには、docker-machine createするときに以下のオプションを追加します。

オプション オプション値 概要
–engine-storage-driver devicemapper 使用するストレージドライバーを指定します。

centos:6に変更するにはローカルマシンにあるtechpjin-lamp/php/Dockerfileを変更します。

# FROM centos:latest # 修正前
FROM centos:6 # 修正後
RUN yum -y update && \
    yum -y install httpd php
RUN yum -y install php-mysql
EXPOSE 80
CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]

変更が終わったらイメージの再作成を行いましょう。

$ docker-compose build
$ docker-compose up -d

devicemapperはパフォーマンスに難があるという情報がありますので、centos6にした方が無難かもしれません。

↓参考にさせていただいたサイト

今回はここまでにしておきます。

  • このエントリーをはてなブックマークに追加

PAGE TOP