概要
アプリケーションを動かす方法として、EC2 インスタンスに OS ごと環境を用意するやり方のほかに、アプリケーションとその実行に必要なものをまとめた「コンテナ」で動かすやり方が広く使われています。コンテナは、開発者の PC でもテスト環境でも本番環境でも同じように動くため、デプロイのたびに環境の違いで悩む場面を減らせます。
AWS でコンテナを動かす中心となるサービスが Amazon ECS(Elastic Container Service)です。ECS はフルマネージドのコンテナオーケストレーションサービスで、コンテナをどこで・いくつ・どのように動かすかを管理します。コンテナの実行基盤には、サーバーを管理せずに使える AWS Fargate か、自分で管理する EC2 インスタンスなどを選べます。コンテナの元になるイメージは、Amazon ECR(Elastic Container Registry)に保存して ECS から取り出します。ECR・ECS・Fargate の組み合わせは CLF・SAA のどちらでも問われる基本です。
本記事では、コンテナと仮想マシンの違い、イメージとレジストリ、ECS の構成要素(クラスター・タスク定義・タスク・サービス)、起動タイプ(Fargate と EC2)、EKS との使い分けを解説したうえで、ECR のプライベートリポジトリに nginx のイメージを push し、Fargate のサービスとして起動してブラウザから表示を確認するまでを体験します。
クラウドおさるコンテナとは、バナナを木箱に詰めて、どの猿山に運んでも同じように食べられるようにするようなものでござろうか。弊猿、箱詰めから届け先で開けるところまで、一通り確かめてみるでござる!


この記事のメリット
- コンテナと仮想マシン(EC2 インスタンス)の違いを説明できる
- コンテナイメージ・レジストリ・リポジトリの関係と、Amazon ECR の役割を理解できる
- ECS のクラスター・タスク定義・タスク・サービスがそれぞれ何を表すかを把握できる
- 起動タイプ Fargate と EC2 の違い、ECS と EKS の使い分けを判断できる
- ECR へのイメージの push から Fargate でのサービス起動、ブラウザでの表示確認までを一通り体験できる
執筆者とキャラクター紹介
執筆者:土肥(とひ)
株式会社ジェニュインの代表であり元エンジニア。これまでオンプレミスと AWS 環境のインフラ業務を担当。AWS 認定資格の学習で得た知識を、ハンズオンとともに解説するのが得意。直近では新人の教育も行っており、これから技術を学ぶ方が納得できる解説を心がけています。基礎編・Cloud Practitioner の記事では、解説役としても登場します。


クラウドおさる



はじめましてでござる。弊猿はクラウドおさる。IT インフラが異常に発達した猿山から、雲に乗って地上の AWS を学びに降りてきたのでござる。



基礎編や Cloud Practitioner の記事では、とひさんに素朴な疑問をぶつける役でござるな。Security - Specialty などの記事では、要所でワンポイントや注意点をひとこと添えるでござる。



猿山にもデータセンターや監視当番があって、地上で起きることはだいたい猿山にも同じ仕組みがあるのでござる。例え話がつい猿山に寄るのは、弊猿の癖でござる。
技術解説
コンテナとは(仮想マシンとの違い)



とひさん、最近どこへ行っても「コンテナ」と聞くでござる。そもそもコンテナとは何でござるか?
コンテナは、アプリケーションを動かすのに必要なものを全部ひとまとめにした、標準化されたソフトウェアの単位だよ。中にはアプリのコードだけじゃなくて、ランタイムやシステムツール、システムライブラリまで入っているんだ。



必要なものが全部入っている……それなら EC2 インスタンスと何が違うのでござる? EC2 にもアプリを入れて動かせるでござるよな。
いいところに気づいたね! EC2 インスタンスみたいな仮想マシン(VM)は、OS を丸ごと 1 台分用意して、その上にアプリを入れるよね。コンテナは OS 丸ごとじゃなくて、アプリとその依存関係だけを箱にするイメージなんだ。だから軽くて、従来の仮想マシンより少ないリソースで動くし、起動したり数を増やしたりするのも簡単なんだよ。
| 観点 | 仮想マシン(EC2 インスタンスなど) | コンテナ |
|---|---|---|
| 中に入っているもの | OS を含むサーバー 1 台分 | アプリと、その実行に必要なランタイム・ライブラリ |
| 重さ | OS ごと起動するため重め | 軽量で、すばやく起動・複製できる |
| 環境の違い | サーバーごとに設定がずれやすい | どの環境でも同じイメージから同じように動く |
| 主な用途 | OS レベルで細かく管理したいサーバー | Web アプリ・API・バッチなどを素早く配布・スケール |





なるほど! VM は猿山ごと引っ越すようなもので、コンテナはバナナを詰めた木箱だけを運ぶようなものでござるな。
そうそう、そのイメージで合ってるよ。箱の中身が同じなら、開発者の PC でも本番でも同じように動く。これがコンテナの「移植性」や「整合性」っていうメリットなんだ。
イメージとレジストリ、Amazon ECR



その木箱は、どうやって作るのでござるか?
コンテナは「イメージ」っていう読み取り専用のテンプレートから作られるんだ。イメージはアプリとその依存関係を固めた静的な成果物で、普通は Dockerfile っていう手順書から作る(ビルドする)よ。



型があって、そこから何個でも同じ木箱を作れるのでござるな。では、その型はどこにしまっておくのでござる?
イメージを置いておく場所を「レジストリ」って呼ぶよ。ビルドしたイメージをレジストリにアップロードすることを push、レジストリから取ってくることを pull っていうんだ。AWS のレジストリサービスが Amazon ECR だね。
| 用語 | 意味 |
|---|---|
| イメージ | コンテナの元になる読み取り専用のテンプレート |
| レジストリ | イメージを保管する場所。ECR では AWS アカウントごとにデフォルトのプライベートレジストリ(<アカウントID>.dkr.ecr.<リージョン>.amazonaws.com)が用意される |
| リポジトリ | レジストリの中で、イメージを種類ごとにまとめる単位(例: ecs-handson-nginx) |
| タグ | 同じリポジトリ内のイメージを区別するラベル(例: v1、latest) |
| push / pull | イメージをレジストリへ送る / レジストリから取得する操作 |



ECR に置いたイメージは、誰でも取り出せてしまうのでござるか?
ECR のプライベートリポジトリは IAM で権限を管理するから、許可したユーザーやサービスだけが push・pull できるよ。ほかにも、使わなくなったイメージを自動で消すライフサイクルポリシーや、push 時に脆弱性をチェックするイメージスキャン、別のリージョンやアカウントへのレプリケーションといった機能があるんだ。
それとは別に、誰でも匿名で pull できる公開イメージを集めた Amazon ECR Public Gallery(public.ecr.aws)もあるよ。今回の実践では、そこで公開されている nginx のイメージを取ってきて、自分のプライベートリポジトリに push し直すんだ。



公開の倉庫から箱を借りてきて、自分の猿山の鍵付き倉庫にしまい直すのでござるな!
ECS の構成要素(クラスター・タスク定義・タスク・サービス)



イメージができたら、ECS ではどうやってコンテナを動かすのでござるか?
ECS には覚えておきたい部品が 4 つあるよ。まとめるとこんな感じだね。
| 構成要素 | 役割 | たとえ |
|---|---|---|
| タスク定義 | アプリの設計図。使うイメージ、CPU とメモリの量、開くポート、ネットワークモード、IAM ロール、ログの設定などを JSON で書いたもの | レシピ |
| クラスター | タスクやサービスをまとめる論理的なグループ。登録されたキャパシティ(実行基盤)の上でタスクが動く | 厨房 |
| タスク | タスク定義から実際に起動したもの。1 つのタスクに 1 つ以上のコンテナが入る | 作った料理 |
| サービス | 指定した数のタスクを動かし続ける仕組み。タスクが失敗・停止すると新しいタスクを起動して置き換える | 「常に 1 皿出しておく」係 |





タスクとサービスの違いが、まだぼんやりしているでござる……。
タスクは「1 回起動したもの」だから、処理が終わったり落ちたりしたらそれっきりなんだ。バッチ処理みたいに、作業をして止まるものはタスクを単体で実行すればいいよ。一方で Web サーバーみたいにずっと動いていてほしいアプリは、サービスにして「タスクを 1 つ動かしておいて」って頼むんだ。そうすると、タスクが止まってもサービススケジューラが新しいタスクを起動して、必要な数を保ってくれるんだよ。



猿山の見張り番が倒れたら、長老会がすぐ次の見張りを立てるようなものでござるな! ずっと動かしたいものはサービスにするのでござる。
その通り! ちなみにタスク定義の中には、ECS が代わりにイメージを pull したりログを送ったりするための「タスク実行ロール」も指定するよ。プライベートな ECR からイメージを取ってくるときにはこのロールが必要なんだ。コンテナの中のアプリが AWS の API を呼ぶための「タスクロール」とは別物だから、取り違えないようにね。
起動タイプ: Fargate と EC2



タスクは、実際にはどこのサーバーで動いているのでござる?
そこを決めるのが起動タイプ(キャパシティ)だよ。代表的なのは Fargate と EC2 の 2 つだね。
| 観点 | Fargate | EC2 |
|---|---|---|
| サーバーの管理 | 不要(サーバーレス)。インスタンスの選択やクラスターのスケーリングを考えなくてよい | 自分で EC2 インスタンスを選び、設定・管理する |
| 料金 | タスクに割り当てた vCPU とメモリのリソースに対して課金 | 起動している EC2 インスタンスに対して課金 |
| ネットワークモード | awsvpc が必須。タスクごとに ENI(ネットワークインターフェース)が付く | awsvpc のほか bridge なども選べる |
| 向いているケース | インフラを管理せずアプリに集中したい、ワークロードの変動が読めない、まず手軽に始めたい | GPU などの特殊なハードウェア、特定のインスタンスタイプ、カスタム AMI が必要 |
Fargate では、タスク定義で CPU とメモリの量を決めるんだけど、選べる組み合わせが決まっているよ。一番小さいのは 0.25 vCPU(CPU 値 256)で、メモリは 512 MiB・1 GB・2 GB から選ぶんだ。今回の実践はこの最小構成で動かすよ。



Fargate だと、ほかのお客さんのコンテナと同じサーバーに同居させられたりはしないのでござるか?
Fargate のタスクは 1 つずつ独立した分離境界を持っていて、カーネルや CPU、メモリ、ENI をほかのタスクと共有しないんだ。だからそこは安心していいよ。ほかにも、AWS が EC2 インスタンスの管理まで引き受けてくれる「ECS マネージドインスタンス」や、オンプレミスのサーバーを登録する「ECS Anywhere」という選択肢もあるけど、まずは Fargate と EC2 の違いを押さえておこう。



「サーバーの面倒を見たくないなら Fargate、インスタンスを細かく選びたいなら EC2」でござるな!
ECS と EKS の使い分け



コンテナのサービスには、EKS というものもあると聞いたでござる。ECS とは何が違うのでござるか?
Amazon EKS(Elastic Kubernetes Service)は、Kubernetes というオープンソースのコンテナオーケストレーションツールを AWS 上で動かすマネージドサービスだよ。ECS は AWS 独自の仕組みで、EKS は Kubernetes の仕組み、っていうところが一番の違いだね。
| 観点 | Amazon ECS | Amazon EKS |
|---|---|---|
| オーケストレーションの仕組み | AWS 独自 | Kubernetes |
| 必要なスキル | AWS の操作に慣れていれば始めやすい | Kubernetes の知識が必要 |
| 選ぶ目安 | シンプルにコンテナを動かしたい、AWS のサービスと組み合わせて使いたい | すでに Kubernetes を使っている、Kubernetes の仕組みやツールを生かしたい |
ちなみに Fargate は ECS 専用じゃなくて、EKS と組み合わせても使えるよ。ECR もどちらからでもイメージを取ってこられるんだ。



「Kubernetes」と出てきたら EKS、と覚えておくでござる。全体像がつかめたでござる!
実践
ECR にプライベートリポジトリを作成し、CloudShell から nginx のイメージを push します。続いて ECS のクラスターとタスク定義を作成し、パブリック IP を付けた Fargate のサービスとしてタスクを 1 つ起動して、ブラウザから nginx の画面が表示されることを確認します。
前提条件
- リージョン:
ap-northeast-1(東京) - AWS マネジメントコンソールにログイン済みであること
- ECR・ECS の操作と、IAM ロール(タスク実行ロール)の作成ができる権限があること
- 以下のリソースが作成済みであること
| リソース種別 | リソース名 | 内容 |
|---|---|---|
| VPC | ecs-vpc | 10.0.0.0/16 |
| サブネット | ecs-public-subnet-1a | 10.0.1.0/24(ap-northeast-1a、インターネットゲートウェイ経由で外部と通信できる) |
| サブネット | ecs-public-subnet-1c | 10.0.2.0/24(ap-northeast-1c、インターネットゲートウェイ経由で外部と通信できる) |
| セキュリティグループ | ecs-web-sg | インバウンド: HTTP(TCP 80)を 0.0.0.0/0 から許可 / アウトバウンド: すべて許可 |
VPC とサブネットの基本は「Amazon VPC で仮想ネットワークを構築しサブネットを設定する」、セキュリティグループの考え方は「セキュリティグループとネットワーク ACL でアクセスを制御する」で解説しています。
作成するリソース一覧
| リソース種別 | リソース名 | 用途 |
|---|---|---|
| ECR プライベートリポジトリ | ecs-handson-nginx | nginx イメージ(タグ v1)の保存先 |
| ECS クラスター | ecs-handson-cluster | タスクとサービスをまとめるクラスター |
| ECS タスク定義 | ecs-handson-task | nginx コンテナを Fargate(0.25 vCPU / 0.5 GB)で動かす設計図 |
| IAM ロール | ecsTaskExecutionRole | ECR からのイメージ pull とログ送信に使うタスク実行ロール(タスク定義の作成時にコンソールで作成。既にある場合はそれを使う) |
| ECS サービス | ecs-handson-service | タスクを 1 つ動かし続けるサービス |
ステップ1: ECR のプライベートリポジトリを作成する
- AWS マネジメントコンソールにログインし、リージョンが
ap-northeast-1(東京)であることを確認します - 上部の検索バーに
ECRと入力し、表示された「Elastic Container Registry」を選択します - 左側ナビゲーションの「プライベートレジストリ」→「リポジトリ」を選択し、「リポジトリを作成」をクリックします
- 以下を設定します
- リポジトリ名:
ecs-handson-nginx - イメージタグのミュータビリティ:
Mutable(デフォルト) - 暗号化設定:
AES-256(デフォルト) - その他の項目はデフォルトのままにし、「作成」をクリックします


- リポジトリ一覧に
ecs-handson-nginxが表示されたら、その「URI」(<アカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/ecs-handson-nginx)を控えておきます
ステップ2: CloudShell で nginx のイメージを pull して ECR に push する
AWS CloudShell には Docker がプリインストールされており、CloudShell の中から ECR にイメージを push できます。CloudShell の Docker で使える領域は限られているため、ここではサイズの小さい Alpine Linux ベースの nginx イメージを使います。
- コンソール上部のツールバーにある CloudShell のアイコンをクリックし、CloudShell を起動します(リージョンが
ap-northeast-1のままであることを確認します) - Docker が使えることを確認します
docker --version- アカウント ID とレジストリの URL を変数に入れます
AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
ECR_URL=${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com
echo ${ECR_URL}- ECR Public Gallery で公開されている nginx のイメージを pull します(ECR Public は匿名で pull できるため、ログインは不要です)。後で Fargate の
Linux/X86_64で動かすので、プラットフォームを指定します
docker pull --platform linux/amd64 public.ecr.aws/nginx/nginx:stable-alpine- Docker を自分のプライベートレジストリに認証させます。
Login Succeededと表示されれば成功です(この認証は 12 時間有効です)
aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin ${ECR_URL}- pull したイメージに、自分のリポジトリ名とタグ
v1を付けます
docker tag public.ecr.aws/nginx/nginx:stable-alpine ${ECR_URL}/ecs-handson-nginx:v1- イメージを ECR に push します
docker push ${ECR_URL}/ecs-handson-nginx:v1最後に v1: digest: sha256:... の行が表示されれば push は完了です。


- ECR コンソールに戻り、リポジトリ一覧で
ecs-handson-nginxをクリックします - 「イメージ」の一覧に、イメージタグ
v1のイメージが表示されていることを確認します





「pull して、タグを付け直して、push する」の 3 手でござる。タグに自分のレジストリの URL を入れるから、送り先の倉庫が決まるのでござるな。
ステップ3: ECS クラスターを作成する
- 上部の検索バーに
ECSと入力し、表示された「Elastic Container Service」を選択します - 左側ナビゲーションの「クラスター」を選択し、「クラスターの作成」をクリックします
- 「クラスター設定」の「クラスター名」に
ecs-handson-clusterと入力します - 「インフラストラクチャ」は、既定で「Fargate のみ」(サーバーレス)が選ばれているのでそのままにします
- 「モニタリング」「タグ」などその他の項目はデフォルトのままにし、「作成」をクリックします
- クラスター一覧に
ecs-handson-clusterが表示されることを確認します
そのアカウントで ECS を初めて使う場合、サービスリンクロールの作成直後に「Unable to assume the service linked role」というエラーが出ることがあります。数十秒待ってからもう一度「作成」をクリックします。
ステップ4: タスク定義を作成する
- 左側ナビゲーションの「タスク定義」を選択し、「新しいタスク定義の作成」→「新しいタスク定義の作成」をクリックします
- 「タスク定義の設定」で、タスク定義ファミリーに
ecs-handson-taskと入力します(初期値の自動生成された名前を書き換えます) - 「インフラストラクチャの要件」で以下を設定します
- 起動タイプ:
AWS Fargateにチェック(デフォルト) - オペレーティングシステム/アーキテクチャ:
Linux/X86_64 - ネットワークモード:
awsvpc(Fargate では固定) - タスクサイズ: CPU を
1 vCPUから.25 vCPUに変更します。メモリは互換性のある最小値の.5 GBに自動で調整されます - タスクロール:
-(なし)のまま(今回のコンテナは AWS の API を呼ばないため) - タスク実行ロール:
デフォルトロールを作成(デフォルト。作成時にecsTaskExecutionRoleが作られます。既にある場合はそれが使われます)


- 「コンテナ – 1」で以下を設定します
- 名前:
web(初期値を書き換えます) - イメージ URI: ステップ1で控えた URI の末尾に
:v1を付けたもの(<アカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/ecs-handson-nginx:v1) - 必須コンテナ:
はい - ポートマッピング: コンテナポート
80、プロトコルTCP(ポート名・アプリケーションプロトコルは空欄・デフォルトのまま) - 「ログ収集」は Amazon CloudWatch に送る設定(デフォルト)のままにします
- その他の項目はデフォルトのままにし、「作成」をクリックします


- タスク定義
ecs-handson-taskのリビジョン1が作成されたことを確認します
ステップ5: Fargate のサービスを作成する
- 左側ナビゲーションの「クラスター」を選択し、
ecs-handson-clusterをクリックします - 「サービス」タブで「作成」をクリックします
- 「サービスの詳細」で以下を設定します
- タスク定義ファミリー:
ecs-handson-task(リビジョンは最新の1) - サービス名:
ecs-handson-service - 「環境」の「コンピューティング設定」で、コンピューティングオプションを既定の「キャパシティープロバイダー戦略」から「起動タイプ」に切り替え、起動タイプ
Fargate、プラットフォームバージョンLATESTを指定します(どちらも既定値です) - 「デプロイ設定」で、サービスタイプ
レプリカ、必要なタスク1を指定します


- 「ネットワーキング」を開き、以下を設定します
- VPC:
ecs-vpc(vpc-xxxx ecs-vpcの形で表示されます) - サブネット:
ecs-public-subnet-1aとecs-public-subnet-1cの 2 つが選ばれていることを確認します(VPC を選ぶと VPC 内のサブネットがすべて選択されます) - セキュリティグループ: 「既存のセキュリティグループを使用」のまま、初期選択の
defaultを外してecs-web-sgを選択 - パブリック IP: オン(デフォルト)
- 「ロードバランシング」などその他の項目はデフォルト(ロードバランサーなし)のままにし、「作成」をクリックします


パブリックサブネットで Fargate のタスクが ECR からイメージを pull するには、タスクにパブリック IP が付いているか、インターネットへの経路が必要です。パブリック IP をオンにし忘れると、イメージを取得できずにタスクが起動しない点に注意が必要です。
ステップ6: タスクの起動を確認し、ブラウザでアクセスする
- サービスの作成が終わったら、クラスター
ecs-handson-clusterの「サービス」タブでecs-handson-serviceをクリックします - 「タスク」タブを選択し、タスクの「前回のステータス」が「実行中」になるまで待ちます(1 分前後かかります)
- タスク ID をクリックしてタスクの詳細を開き、「設定」の「ネットワーキング」にある「パブリック IP」を確認します


- 「パブリック IP」の横の「オープンアドレス」をクリックするか、ブラウザで
http://<パブリック IP>を開きます(https://ではなくhttp://でアクセスします) - 「Welcome to nginx!」のページが表示されることを確認します


ECR に push したイメージから、Fargate 上でコンテナが起動し、インターネットからアクセスできることが確認できました。



Fargate はタスクが動いている間、割り当てた vCPU とメモリの分だけ料金がかかり続けるのでござる。しかもサービスが残っていると、タスクだけ止めても次のタスクが起動されてしまうのでござる。試し終わったら、タスクではなくサービスごと削除するでござるぞ。
まとめ
- コンテナは、アプリとその実行に必要なランタイム・ライブラリをまとめた単位で、仮想マシンより少ないリソースで動き、どの環境でも同じように動かせる
- コンテナは読み取り専用のイメージから作られ、イメージはレジストリに保存する。Amazon ECR は AWS のマネージドなコンテナレジストリで、プライベートリポジトリへのアクセスは IAM で制御する。公開イメージは ECR Public Gallery から匿名で pull できる
- ECS の構成要素は、設計図のタスク定義、論理的なグループのクラスター、起動した実体のタスク、指定数のタスクを動かし続けるサービスの 4 つ
- サービスは、タスクが失敗・停止すると新しいタスクを起動して必要な数を維持する。プライベートな ECR からの pull やログ送信にはタスク実行ロールが必要
- 起動タイプは、サーバー管理が不要で vCPU とメモリの分だけ課金される Fargate と、自分でインスタンスを管理する EC2 が代表的。Fargate では
awsvpcネットワークモードが必須 - Kubernetes を使うなら EKS、AWS 独自の仕組みでシンプルにコンテナを動かすなら ECS。Fargate と ECR はどちらとも組み合わせられる
関連記事:
参照先
- Amazon Elastic Container Service とは
- Amazon ECS のソリューションの構築
- Amazon ECSの タスク定義
- Amazon ECS サービス
- Amazon ECS の AWS Fargate 用のアーキテクト
- Fargate における Amazon ECS タスク定義の違い
- Amazon ECS タスク実行IAM ロール
- Fargate 用の Amazon ECS Linux タスクを作成する方法について説明します。
- Fargate ワークロード用の Amazon ECS クラスターを作成する
- コンソールを使用した Amazon ECS タスク定義の作成
- Amazon ECS のローリング更新デプロイの作成
- Amazon Elastic Container Registry とは
- Amazon ECR プライベートレジストリ
- イメージを保存するための Amazon ECR プライベートリポジトリの作成
- Amazon ECR プライベートリポジトリへの Docker イメージのプッシュ
- What Is Amazon Elastic Container Registry Public?
- CloudShell 内で Docker コンテナを構築して Amazon ECR リポジトリにプッシュする
- AWS CloudShell コンピューティング環境: 仕様とソフトウェア
- AWS コンテナサービスの選択
- Amazon EKS とは













