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から行うことでいつでも初めのウォークスルーの状態で設定を行うことができる。
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
<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を以下のように作成。
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
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