AWS
EC2
Docker
ECS

AWS上にDocker環境構築を、EC2に直で入れる方法とECS(マネジメントコンソール上で操作)の導入の2つの方法で入れてみた。

More than 1 year has passed since last update.

Dockercon 16で今、Dockerの話題で盛り上がっています。

http://2016.dockercon.com/

AWS上にDocker環境をEC2上とECSの2つの方法で導入してみたのでメモ。

ECSはマネジメントコンソールからの操作で、2016年6月での地点での操作方法となります。

ECSを使用した場合はクラスタ管理から、負荷分散、スケーリングなどの面倒も見てくれます。


EC2インスタンス上に直で入れる方法

DockerイメージはDocker Hubからpullしてきたものを使用する場合

$ sudo yum install -y docker

$ sudo service docker start

$ sudo docker pull '<Docker Hubユーザー名>/<イメージ名>:<Tag名>'
'<Tag名>': Pulling from '<Docker Hubユーザー名>/<イメージ名>'
efd26ecc9548: Pull complete
a3ed95caeb02: Pull complete
d1784d73276e: Pull complete
72e581645fc3: Pull complete


Digest: sha256:c8beee1a15bbc67edee9e4532a105d500ebc5935879557b020ba7dd1cfa0bdb1
Status: Downloaded newer image for '<Docker Hubユーザー名>/<イメージ名>:<Tag名>'

$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
'<Docker Hubユーザー名>/<イメージ名>' '<Tag名>' 83602403dcba 10 weeks ago 856.4 MB

#コンテナを作成する
$ sudo docker run -d --name '<適当なコンテナ名>' -p '<Dockerで受け付けるポート番号>':'<アプリケーション側で受け付けるポート番号>' (-p '<Dockerで受け付けるポート番号>':'<アプリケーション側で受け付けるポート番号>') '<Docker Hubユーザー名>/<イメージ名>:<Tag名>'
65e1dd030dc25c46aa046c4daa5bac194931657e7188305df9723f77c2a9434f
# 又は docker run -ti タグ名(docker build -t タグ名 などで指定したもの)

$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
65e1dd030dc2 '<Docker Hubユーザー名>/<名>:<Tag名>' "~~~" 5 minutes ago Up 5 minutes 0.0.0.0:'<Dockerで受け付けるポート番号>'->'<アプリケーション側で受け付けるポート番号>'/tcp, 0.0.0.0:'<Dockerで受け付けるポート番号>'->'<アプリケーション側で受け付けるポート番号>'/tcp, 8181/tcp '<コンテナ名>'

#コンテナを起動する
$ sudo docker start <コンテナ(CONTAINER ID or NAMES)>
65e

#ホストからコンテナにログイン
$ sudo docker exec -it '<コンテナ名>' bash

http://'<IP address>':'<Dockerで受け付けるポート番号>'/'<PATH>' にアクセス。


ECSを導入する方法

DockerイメージをDockerfileからビルドする場合

ECSで出てくるタスクとサービスの語句についてですが、

タスクはバッチ処理のような一回限りの処理、サービスは永続的な処理のものです。

ECSを導入する場合について、初めてのウォークスルーの場合と自分で構築する場合の2つのパターンを取り上げる。


初めての場合

以下のURLから行うことでいつでも初めのウォークスルーの状態で設定を行うことができる。

https://console.aws.amazon.com/ecs/home#/firstRun


Get Startedを選択する。

Deploy a sample application onto an Amazon ECS Cluster

Store container images securely with Amazon ECR

の2つにチェックを入れた状態でContinueを選択する。


Step 1: Configure repository

Repository name: ecs-test

として、Next stepを選択する。


Step 2: Build, tag, and push Docker image

ローカルで以下の作業を行う。OSはUbuntu14.04を使用した場合のものとなる。

$ mkdir docker-test

$ cd docker-test/
$ aws ecr get-login --region us-west-2
docker login -u AWS -p '<Password>' -e none https://~~~.ecr.us-west-2.amazonaws.com

Dockerをインストールしていない場合はインストールする。

$ wget -qO- https://get.docker.com/ | sh

$ sudo usermod -aG docker $USER
$ su - $USER

#先ほどaws ecrコマンドで生成されたdockerログインコマンドをコピペする。

$ docker login -u AWS -p '<Password>' -e none https://~~~.ecr.us-west-2.amazonaws.com
Warning: '-e' is deprecated, it will be removed soon. See usage.
Login Succeeded

Login Succeededと出ればログイン成功である。

次にDockerfileを作成する。

$ vim Dockerfile

例えば、以下のように作成する。

FROM ubuntu:14.04

RUN apt-get update -y
RUN apt-get install -y git curl apache2 php5 libapache2-mod-php5 php5-mcrypt php5-mysql

RUN rm -rf /var/www/*
ADD src /var/www

RUN a2enmod rewrite
RUN chown -R www-data:www-data /var/www
ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_LOG_DIR /var/log/apache2

EXPOSE 80

CMD ["/usr/sbin/apache2", "-D", "FOREGROUND"]

コマンドはroot権限で実行される。

Dockerfileと同じ階層にsrcディレクトリを作成し、デプロイ対象となるファイルを用意する。

mkdir src && cd src

vim index.php


index.php

<html>

<body>Hello, world!</body>
</html>

作成したDockerfileを元にイメージファイルをビルドする。

$ docker build -t ecs-test .

Sending build context to Docker daemon 2.048 kB
Step 1 : FROM php:5.6-apache
---> 306370e37ec1
Step 2 : RUN a2enmod rewrite
---> Using cache
---> e1523614a754
Step 3 : RUN docker-php-ext-install pdo_mysql mbstring
---> Using cache
---> 320d68c3ce69
Step 4 : RUN echo 'date.timezone = Asia/Tokyo' >> /usr/local/etc/php/conf.d/99_myconf.ini
---> Using cache
---> c404ecfa957f


Successfully built 4b0569678402

タグ付けをする。

$ docker tag ecs-test:latest ~.ecr.us-west-2.amazonaws.com/ecs-test:latest

ECSにPUSHする。

$ docker push ~.ecr.us-west-2.amazonaws.com/ecs-test:latest

The push refers to a repository [~.ecr.us-west-2.amazonaws.com/ecs-test]
4a7543f178f3: Pushed
40da234f8043: Pushed
749b6ec33d91: Pushed
293489163a1e: Pushed
61cd28b6b81d: Pushed
7e9e746ecede: Pushed
63e87343ae05: Pushed
98fe2d81486b: Pushed
0dcf6f5af493: Pushed
8f86eea0e277: Pushed
358d48af1ad0: Pushed
72a004f2419f: Pushed
f1c36d11715d: Pushed
2f141c453bd9: Pushed
ee63decf49d1: Pushed
42755cf4ee95: Pushed
latest: digest: sha256:5fa6532df8ee23369ee533afbc1cfdd53897839775c6c6d7207abc2e4486d7a6 size: 18332

Next Stepを押す


Step 3: Create a task definition

Task definition name: console-sample-app-static-ecs-test

Container name: sample-app-ecs-test
Image: ~~.ecr.us-west-2.amazonaws.com/ecs-test:latest(デフォルト値)
Maximum memory (MB)*: 300(デフォルト値)
Port mapping: Host port 80, Container port 80, Protocol tcp

Next stepを選択する。


Step 4: Configure service

Configure serviceの項目を以下のように入力する。

Service name: sample-webapp-ecs-test

Desired number of tasks*: 2

Elastic load balancingの項目を以下のように入力する。

Configure service: sample-app-ecs-test:80

ELB listener protocol*: HTTP
ELB listener protocol*: 80
ELB health check: http:80/

Service IAM roleの項目が以下のようになっていることを確認する。

Select IAM role for service: ecsServiceRole

Next stepを選択する。


Step 5: Configure cluster

Configure clusterの項目を以下のように入力する。

Cluster name: default

EC2 instance type: t2.micro
Number of instances: 2
Key pair : '<EC2のネットワーク&セキュリティの項目中のキーペアで作成するなどして所持しているキーペア>'

Security groupの項目は以下のようになっていることを確認する。

Allowed ingress source(s)*: Anywhere, 0.0.0.0/0

Container instance IAM roleの項目が以下のようになっていることを確認する。

Container instance IAM role: Create new role

Review & launchを選択する。


Step 6: Review

Launch instance & run serviceを選択する。


Launch status

ECS statusが4項目の内すべてが"pending"から"created"の状態になり、

EC2 instance statusが15項目の内すべてが"pending"から"created"の状態になったら、ECS clusterの準備が完了である。

View serviceを選択する。


動作確認

EC2のロードバランサの項目から先ほど作成したロードバランサを選択する。

説明というタブのDNS名を確認して、ブラウザからアクセスする。

Dockerで作成した通りのものがでれば動作確認ができたことになる。


自分で構築する場合


リポジトリの作成

画面左のリポジトリを選択し、[リポジトリの作成]を選択。


ステップ 1: リポジトリの設定

例えば、以下のようにリポジトリ名を入力して、[次のステップ]を選択。

リポジトリ名: sample-ecr


ステップ 2: Docker イメージの構築、タグ付け、プッシュ

以下のコマンドを入力して[次のステップ]

docker-machine start default

eval $(docker-machine env default)

$ aws ecr get-login --region us-east-1 --profile private

$ docker login -u AWS -p XXXXXXXXXX -e none https://<AWSアカウント番号>.dkr.ecr.us-east-1.amazonaws.com\n
$ docker build -t sample-ecr .
$ docker tag sample-ecr:latest <AWSアカウント番号>.dkr.ecr.us-east-1.amazonaws.com/sample-ecr:latest
$ docker push <AWSアカウント番号>.dkr.ecr.us-east-1.amazonaws.com/sample-ecr:latest

--profileに注意


タスク定義の作成

画面左のタスク定義を選択し、[新しいタスク定義の作成]を選択。

タスク定義名: sample-task

コンテナの定義から[コンテナの追加]を選択。

以下のように情報を入力して、[追加]を選択。

コンテナ名: sample-container

イメージ: arn:aws:ecr:us-east-1::repository/sample-repository:latest

メモリ制限(MB): ハード制限 128

ポートマッピング: ホストポート 80, コンテナポート 80, プロトコル tcp

[作成]を選択。

以降、イメージに変更がある時は[新しいリビジョンの作成]からリビジョンを作成してサービスの方も関連づけるリビジョンを更新する。


クラスターの作成

クラスターを作成する前に、ECSに最適化されたAMIでEC2インスタンスを作成する。もしくはエージェントをインストールする方法 (http://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/ecs-agent-install.html )もある。


EC2インスタンスの作成

マネジメントコンソールからEC2を選択。

[インスタンスの作成]を選択。


1. AMI の選択

コミュニティAMIを選択し、検索ウィンドウからecs-optimizedと入力し出てくる以下のAMIを選択。

amzn-ami-2016.09.a-amazon-ecs-optimized - ami-1924770e


2. インスタンスタイプの選択

t2.microを選択し、[次の手順: インスタンスの詳細の設定]を選択。


3. インスタンスの設定

IAMロール: ecsInstanceRole

(※ Amazon EC2 Container Service Role中のAmazonEC2ContainerServiceRoleのロールを割り当てる。)

自動割り当てパブリックIP: [サブネット設定を使用(有効)]もしくは[有効化]で有効にしておく。

[次の手順: ストレージの追加]を選択。


4. ストレージの追加

[次の手順: インスタンスのタグ付け]を選択。


5. インスタンスのタグ付け

[次の手順: セキュリティグループの設定]を選択。


6. セキュリティグループの設定

[ルールの追加]を選択し、HTTP TCP 80 0.0.0.0を追加しておく。

[次の手順: 確認]を選択。


7. 確認

内容を確認したら、インスタンスの作成をする。鍵は適切なものを選択しておく。

画面左のクラスターを選択し、[クラスターの作成]を選択。

クラスター名を以下のように入力し、[作成]を選択。

EC2の起動が完了すると、ECSのクラスターに登録済みコンテナインスタンス: 1の状態でdefaultという名前で追加される。


クラスターの作成

クラスターから先ほどのdefaultを選択。

[サービス]タブから[作成]を選択し、以下のように入力。

タスク定義: sample-task

クラスター: default

サービス名: sample-service

タスクの数: 1

最小ヘルス率: 50

最大率: 200

[サービスの作成]を選択。

ELBやAuto Scalingの設定も可能だが、ここでは省略。

[タスク]タブから[新しいタスクの実行]を選択。

以下のように入力して、[タスクの実行]を選択。

タスク定義: sample-task

クラスター: default

タスクの数: 1

以上で完了。


Amazon ECS CLI 一覧

create-cluster

create-service
delete-cluster
delete-service
deregister-container-instance
deregister-task-definition
describe-clusters
describe-container-instances
describe-services
describe-task-definition
describe-tasks
discover-poll-endpoint
list-clusters
list-container-instances
list-services
list-task-definition-families
list-task-definitions
list-tasks
register-container-instance
register-task-definition
run-task
start-task
stop-task
submit-container-state-change
submit-task-state-change
update-container-agent
update-service
wait


Dockerfile命令 一覧

FROM

MAINTAINER
RUN
CMD
LABEL
EXPOSE
ENV
ADD
COPY
ENTRYPOINT
VOLUME
USER
WORKDIR
ARG
ONBUILD
STOPSIGNAL


Dockerコマンド 一覧

#管理系

daemon
info
inspect
version

#イメージ系
build
commit
export
history
images
import
load
rmi
save
tag

#コンテナ系
attach
cp
create
diff
events
exec
kill
logs
pause
port
ps
rename
restart
rm
run
start
stats
stop
top
unpause
wait

#Hub ・レジストリ系
login
logout
pull
push
search

#ネットワーク・接続系
network_connect
network_create
network_disconnect
network_inspect
network_ls
network_rm

#共有データ・ボリューム系
volume_create
volume_inspect
volume_ls
volume_rm

例えば、以下のように操作する。

$ sudo docker start 65e

65e
$ sudo docker stop 65e
65e
$ sudo docker restart 65e
65e

$ sudo docker rm 65e
Error response from daemon: You cannot remove a running container 65e1dd030dc25c46aa046c4daa5bac194931657e7188305df9723f77c2a9434f. Stop the container before attempting removal or use -f

$ sudo docker stop 65e
65e
$ sudo docker rm 65e
65e


コマンドチートシート

http://qiita.com/voluntas/items/68c1fd04dd3d507d4083

http://qiita.com/suzukihi724/items/961112f6578a60dd6266


ユースケース


PHPの場合のDockerサンプル

src/以下にアプリケーション本体を置く。

FROM ubuntu:14.04

RUN apt-get update -y
RUN apt-get install -y git curl apache2 php5 libapache2-mod-php5 php5-mcrypt php5-mysql

RUN rm -rf /var/www/*
ADD src /var/www

RUN a2enmod rewrite
RUN chown -R www-data:www-data /var/www
ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_LOG_DIR /var/log/apache2

EXPOSE 80

CMD ["/usr/sbin/apache2", "-D", "FOREGROUND"]


PHPの場合のDocker Composeによるサンプル

Dockerfileを作成。

FROM php:5.6-apache

# Configuration of Redis
ENV PHP_REDIS_VERSION 2.2.7

RUN docker-php-source extract \
&& curl -L -o /tmp/redis.tar.gz https://github.com/phpredis/phpredis/archive/$PHP_REDIS_VERSION.tar.gz \
&& tar xfz /tmp/redis.tar.gz \
&& rm -r /tmp/redis.tar.gz \
&& mv phpredis-$PHP_REDIS_VERSION /usr/src/php/ext/redis \
&& docker-php-ext-install redis

RUN usermod -u 1000 www-data \
&& groupmod -g 1000 www-data

RUN echo 'date.timezone = Asia/Tokyo' >> /usr/local/etc/php/conf.d/99_myconf.ini
RUN echo 'error_reporting = E_ALL' >> /usr/local/etc/php/conf.d/99_myconf.ini

RUN apt-get update
RUN apt-get install -y libmysqlclient-dev mysql-client libpng12-dev libjpeg-dev libmagickwand-dev

# Install PHP GD
RUN docker-php-ext-configure gd --with-jpeg-dir=/usr/include/ \
&& docker-php-ext-install -j $(nproc) gd

# Install PHP Imagick
RUN pecl install imagick
RUN docker-php-ext-install pdo_mysql mbstring
RUN docker-php-ext-enable imagick

RUN a2enmod rewrite

WORKDIR /var/www
USER root

EXPOSE 80

# Update the default apache site with the config we created.
ADD docker-etc/apache-config.conf /etc/apache2/sites-enabled/000-default.conf

docker-compose.ymlを以下のように作成。


docker-compose.yml

web:

build: .
ports:
- "80:80"
volumes:
- .:/var/www
links:
- db
- redis
db:
image: mysql
environment:
MYSQL_ROOT_PASSWORD: root
redis:
image: redis

docker-etc/apache-config.conf

<VirtualHost *:80>

DocumentRoot /var/www

<Directory /var/www>
Options FollowSymLinks
AllowOverride All
Require all granted
</Directory>

ErrorLog /var/log/apache2/error.log
CustomLog /var/log/apache2/access.log combined
</VirtualHost>


Railsを動かす場合のDocker composeによるサンプル

FROM ruby:2.3.1

ENV APP_ROOT /app

RUN apt-get update -qq && \
apt-get install -y build-essential \
libmysqld-dev \
libmysqlclient-dev \
mysql-client \
--no-install-recommends && \
rm -Rf /var/lib/opt/lists/*

RUN mkdir $APP_ROOT
WORKDIR $APP_ROOT

ADD . /app
RUN bundle install


docker-compose.yml

version: '2' 

services:
app:
build: .
command: bundle exec rails s -b 0.0.0.0
volumes:
- .:/app
ports:
- "3000:3000"
links:
- db
db:
image: mysql:5.6.30
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: root


Node.jsを動かす場合のDockerfileサンプル

FROM ubuntu:14.04

RUN apt-get update -y
RUN curl -sL https://deb.nodesource.com/setup_6.x | bash -
RUN apt-get install -y nodejs npm build-essential

RUN update-alternatives --install /usr/bin/node node /usr/bin/nodejs 10

RUN rm -rf /var/www/*
ADD src /var/www

WORKDIR /var/www
RUN npm install

RUN chown -R www-data:www-data /var/www

EXPOSE 3000
CMD ["node", "index.js"]

サービスを作成してタスクを実行すると、Node.jsが実行される。


注意点



  • RUN update-alternatives --install /usr/bin/node node /usr/bin/nodejs 10を追加することが重要。

  • タスクの定義でコンテナ定義時にポートマッピング設定でDockerfile中のポート番号と合わせることを忘れないようにする。


    • EXPOSEで設定したポート番号とコンテナ側のポート番号を一致させ、ホスト側のポート番号で実際に公開に使用するポート番号を設定する。WebSocketなどを使用するときはホスト側のポート番号で指定する。




参考

http://qiita.com/toshihirock/items/dfd42314158aff073e9d

http://qiita.com/con_mame/items/1df441d86c703a0e6fa6

ECSのデプロイサンプル

https://github.com/awslabs/ecs-demo-php-simple-app

Dockerコマンド 一覧

https://docs.docker.com/v1.11/engine/reference/run/

Docker 公式

https://www.docker.com/

Docker Hub

https://hub.docker.com/

Amazon ECS CLI

http://docs.aws.amazon.com/cli/latest/reference/ecs/

Node.js Dockerfile

https://gist.github.com/thom-nic/724a2af410e90a654e35