第9回【いろいろなサービス使ってみよう編その6】 LastUpdated: 2020-12-10¶
(かきかけです)
今回は、dockerとAWSのコンテナ系サービスについて軽く触ってみます。
AWSのコンテナ関連サービスには主に下記のものがあります。
- ECR(Elastic Container Registry)
- ECS(Elastic Container Serivce)
- EKS(Elastic Kubernetes Service)※こういうのがあるという紹介だけで今回は触りません
dockerに関連する単語としてKubernetes(通称:k8s 私は"クバネティス"と発音してます)をよく見ますが、上記のEKSがKubernetesのマネージドサービスとなります。
ECSとk8s(EKS)は両方ともコンテナのオーケストレーションのサービスであり、どちらかを選択して利用することになります。
※ Kubernetesはかなり学習コストが高いものらしいので私は手を出してません。
AWS re:Invent 2020で発表された最新のUpdateではLambdaもDockerイメージでのデプロイをサポートするようになったようです。
AWS Lambda の新機能 – コンテナイメージのサポート
[速報]AWS Lambdaがコンテナイメージをサポート、関数として実行可能に。AWS re:Invent 2020
余談ですが、私の現業務でもSpringBootのJavaアプリケーションをコンテナ化してECS(on Fargate)上で動かしています。
アプリケーションのデプロイ方式にECSのBlueGreenデプロイメント機能を使うことによって、サービスを止めることなく(ダウンタイムなしで)アップデートを行うことが可能な環境を構築しています。
Dockerについて¶
docker自体についてはここでは詳しく扱いませんがCloud9は最初からDockerコマンドを使える状態になっているので基本的なコマンドを試しつつECSで動かしてみます。
(dockerについてはぶっちゃけ私もそれほど詳しくはなく勉強中の身です)
AWSが提供する各種開発用ツール(SAMやDynamoDB-localなど)にもdockerが利用されています。
今回はとりあえず「WebサーバであるNginx(エンジンエックス)を載せたDockerコンテナのイメージを作成してAWSのECSでサービスとして稼働させてみる」ことをやってみようと思います。
(おまけ)dockerの環境をwindows上に構築する場合の選択肢について¶
docker for windowsをインストールしてwindowsのOS上で直接dockerを利用するためには、professionalエディションが必要になります(Hyper-Vが必要なため)。
もしHyper-Vを使えない環境であっても、OracleVirtualBoxなどでLinuxの仮想環境を構築すれば仮想環境上でdockerは利用可能です。
注意点として、windows10のHyper-VとVirtualBoxなどの仮想化ソフトウェアは共存ができません。
つまりHyper-Vを有効化するとvagrantも使えなくなります。
vagrantが使えない開発環境とか私的にはありえないのでローカルに環境作る場合は仮想環境(Linux)上に作成するのがお勧めです。
ECS (ElasticContainerService)について¶
前述した通り、コンテナのオーケストレーションのためのサービスです。
EC2やRDS、ElastiCacheなどと同様にVPC内のサービスとなります。
ECSは実行環境のタイプにEC2とFargate(ファーゲート)を選択することができ、マネージドサービスであるFargateを選ぶことでサーバレスな構成とすることができます。
もしコンテナのオーケストレーションにKubernetesを使いたい場合はECSではなくEKSを使うことになります。
ECSの設定にはクラスタ、タスク定義、サービスなどがありコンテナ化したアプリケーションサーバーをサービスとして稼働させる場合は大まかに下記の手順になります。
- (Cloud9等の任意の環境で)docker buildしてdockerイメージを作成
- ECRにdockerイメージを登録
- ECSのクラスターの作成
- ECRに登録したイメージを使用するECSタスク定義を作成
- ECSサービスの設定を行い、定義したタスクをサービスとして稼働させる
ECSのタスクはサービスとして稼働させるだけでなく、StepFunctionsなどから起動してバッチ処理などにも利用することができます。
この場合は上記手順の「ECSサービスの設定」の部分は必要ありません。
やってみること¶
今回やってみることのサービス構成図
まずはhello world的なこと¶
参考:dockerhub nginx
参考:Docker run リファレンス
# とりあえずhello world docker run hello-world # port8080でnginxをローカル起動(-dはバックグラウンド起動のオプション) # ※ここでDockerHubから"nginx"のイメージがダウンロードされる("docker pull nginx"で事前にpullも可能) docker run --name webserver -d -p 8080:80 nginx # ローカルにあるdockerイメージの確認("nginx"と最初にやった"hello-world"のイメージもあるはず) docker image ls # 起動したプロセスの確認 docker ps # 初期ページの内容取得 curl localhost:8080 # プロセスの停止 docker stop webserver # "-a"オプションをつけないと消えているがつけると出てくる(停止したけどコンテナは残ってる) docker ps docker ps -a # コンテナ削除 docker rm webserver # 出てこなくなる docker ps -a
自前のindex.htmlを追加してコンテナイメージをビルドしてみる¶
参考:Docker でNginx を起動して Web ページを表示する
Dockerを使用したNGINXとNGINX Plusのデプロイ
contentフォルダを作って下記内容のindex.htmlファイルを作成
<html lang="ja">
<head>
<meta charset="utf-8"/>
<meta name="robots" content="noindex">
<title>HELLO</title>
</head>
<body>Hello Container!</body>
</html>
# 差し替えたindex.htmlをまずはローカルで表示してみる docker run --name webserver -v `pwd`/content:/usr/share/nginx/html:ro -d -p 8080:80 nginx curl localhost:8080
"Dockerfile"というファイルを作成して下記内容を定義
FROM nginx COPY content /usr/share/nginx/html
(おまけ)JavaのAPサーバーを起動するようなコンテナイメージの場合のDockerfile例
ビルドしてdockerイメージをローカルに作成
# ビルド docker build -t myimage1 . # ポート8081で起動 docker run --name myimage1_server -p 8081:80 -d myimage1 curl localhost:8081
作成したイメージのECRへの登録¶
ECR イメージのプッシュ
AWS CLIを使ってECRにDockerイメージを登録する
# jqのインストール(未インストールの場合) sudo yum install jq -y # shell変数の設定 AWS_REGION="ap-northeast-1" ACCOUNT_ID=`aws sts get-caller-identity | jq -r .Account` REPOSITORY_NAME=repo-study-nginx TAG_NAME=${ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${REPOSITORY_NAME}:latest # ECRのリポジトリ作成 aws ecr create-repository --repository-name ${REPOSITORY_NAME} --region ${AWS_REGION} # dockerイメージをビルド docker build -t $TAG_NAME . # ECRのget-login実行(pushの向き先をECRに向けるため) $(aws ecr get-login --region ${AWS_REGION} --no-include-email) # ECRにpush docker push $TAG_NAME # 確認 aws ecr list-images --repository-name ${REPOSITORY_NAME} --region ${AWS_REGION}
ECSの設定¶
(ここに詳細な手順を書くのは私の作業コストが高すぎるので画面共有しながら一緒にやっていきます)
- ECSクラスタの作成
- ECRの確認
- ECSタスク定義の作成(タスク定義名:study-webserver-taskdef、メモリ0.5GB、0.25vCPU、コンテナ名:study-webserver-container、ポートマッピング:80)
- SG(SecurityGroupの作成、ELB用"study-load-balancer"とECSサービス用"study-ecs-service"、ELB用は"0.0.0.0/0, ::/0"をポート80に許可、ECSサービス用は"study-load-balancer"からの80を許可)
- ELB(ALB)の作成(ALBを選択,名前:study-load-balancer,インターネット向け, AとCのAZを選択、"study-load-balancer"のSGを選択、ターゲットグループ: tg-study ipで作成)
- ECSサービスの作成(サービス名: study-service、タスクの数:2、パブリック IP の自動割り当て:ENABLED、Application Load Balancerを選択、プロダクションリスナーポート:80 tg-studyのTGを選択、Service Auto Scaling:サービスの必要数を直接調整しない)
- 動作確認(ブラウザより)
リソース削除¶
ECSやELBもEC2と同様にインスタンスが稼働した時間に応じて課金が発生します(しかも、ECSについては1年間限定の無料枠もたぶんありません)。
今回作成したリソースも放置するとそこそこ課金されてしまうのでしっかり削除しましょう。
リソース削除対象(と順番)
- ECSサービス
- ELB(リスナー、ターゲットグループ、本体)
- SecurityGroup(任意)
- ECRのリポジトリ
- Cloud9(任意)
補足(注意点)¶
docker-hubは最近のアップデートでdocker-hubからのイメージのダウンロード制限を設けました。
ダウンロード回数はipアドレス単位でカウントされているようですが、CodeBuild内pullする場合はCodeBuildのIPアドレスが使われてしまいます。
CodePipelineでコンテナイメージのビルドプロセスを自動化している場合、「CodeBuildというサービスを使っている他の人(リージョン単位)」の影響とdocker-hubの制限を受けてimageのpullが失敗する場合があります。
参考:Docker Hub の Rate Limitに引っかかったのでdocker loginで対策した
直近(2020年12月)のアップデートでECRがpublicリポジトリとして利用可能となり、AWS公式のpublicリポジトリ「Amazon ECR Public Gallery」も公開されました。
AWS公式のpublicリポジトリにあるものはDockerHubではなくこちらからpullするようにすることで前述のダウンロード制限の問題を回避できそうです。
amazonlinuxやnginxなどのイメージはすでにありますが、amazoncorrettoなどはまだ登録されていません(これから増えるものと予想されます)。
ECRをパブリックレジストリとして利用可能になりました! #reinvent
ECR Public Gallery
参考など¶
Amazon Elastic Container Service の特徴(公式)
EKSは本当にECSより難しいのか?
なぜKubernetesではなくAmazon ECSを使うべきなのか