【全図解】コンテナ・Dockerから学ぶAmazon ECR・Amazon ECS入門

記事タイトルとURLをコピーする

垣見です。

コンテナやDockerを知らないけれどAmazon ECRやAmazon ECSを学びたい人向けに、「概念や関係性を理解する」ための図解ブログを書きました。
世間にたくさんあるECSハンズオン前後に読むと理解が深まると思います。

このブログで分かるようになること

以下のテーマを扱っています。長いブログなので、気になるものがあれば上記の目次から飛んでください。

太字はAmazon ECSの理解に必須です。
その他、自分が勉強中に気になったテーマを入れています。

  • コンテナとは何?
  • Dockerとは?
    • Gitとの違いは?
  • Amazon ECRとは?
  • Amazon ECSとは?
    • コンテナオーケストレーションとは?
    • Amazon EKSやKubernetesとの違いは?
    • ECS、EC2、Lambdaの違いは?
    • FargateとEC2の違いは?
  • Amazon ECSのコンポーネントの詳細
    • タスク定義・タスク
    • コンテナイメージとタスク定義の違い
    • サービス
    • クラスター
  • ECSを使う流れ(概要)
  • ECR、ECSを実際に使ってみる(リンクのみ)

結論

以下のような図にまとめて見ました。ブログ内で解説しますのでここでは読まなくても大丈夫です。

コンテナのイメージ

Docker周りまとめ

Amazon ECS周りまとめ

コンテナとは?

アプリとそのアプリを動かすのに必要なもの(ライブラリや設定ファイルなど)をすべてひとまとめにして、どこでも同じように動かせるようにした便利な箱のようなイメージです。

もしコンテナが無かったら

アプリを開発するときには、自分のPCに環境に様々なツールやライブラリをインストールする必要があります。
(例:Pythonの特定のバージョン、データベース(MySQLやPostgreSQL)、Webサーバー(NginxやApache)など)

これらのツールは、それぞれが連携してアプリを動かすための「部品」のようなものです。

そのため、もし必要なツールが足りていない場合は想定した動作にならないという事態になります。
「ある環境Aでは動いたから、環境Bにコードを持ってきて動かそうとしたら、Pythonバージョンが違ったから変な挙動になった!」のような形です。

コンテナを使わない場合はこのように、「アプリを動かすための環境を毎回手動で構築し、その環境の違いによる不具合に対応する」 という大きな手間が発生することになります。

コンテナなしのイメージ図。
もともとの環境がどんな設定かに左右される。足りないものは入れる必要がある。

コンテナの良さ

コンテナは「アプリとその実行に必要な部品一式を、まとめてカプセル化したもの」と考えると分かりやすいです。

大きな倉庫(コンテナを立てるコンピューター)の中に自分用の小屋(コンテナ)を建てて、その倉庫とは関係なくその中で生活するイメージです。その倉庫にどんな資材があろうと関係なく、必要なものがそろった小屋が自動で建つので、簡単に生活を始めることが出来ます。

コンテナありのイメージ図。
もともとの環境とは独立して、その前提ツール(依存関係)ごと配れるイメージ。

コンテナの運用

このように環境ごと複製できるコンテナは、スケーリングもコンテナごとに行います。
このとき、水平スケーリング(サーバースペックではなくコンテナ実行数を上げる)を指すことが多いようです。

先ほどの例で言うと、倉庫の中に住人の増減に応じて小屋を建てたり撤去したりするようなイメージですね。
もちろん、その小屋で行いたいこと(=アプリの中身)別に違う小屋を建てることもできます。

ビジネスにコンテナを使うときのイメージ

コンテナの技術

コンテナは、倉庫の中の他の部屋(他のコンテナ同士)とは独立していますが、倉庫自体の電気や水道(ホストOSのカーネル)はみんなでシェアしています。そのため、ホストOS上でどこにでも同じ部屋(コンテナ)をパッと作って、すぐに作業(アプリ実行)を始められるという訳です。

コンテナは名前空間という技術で独立性を保っています。
ホストOS上で動くため、リソースはcgroupという部分で裏で管理されています。

仮想化技術などを絡めたもう少し技術的な説明については以下ブログをご覧ください。

blog.serverworks.co.jp

Dockerとは?

Dockerとはこの「コンテナ」を扱うための技術で、Docker社が出しているソフトウェアプラットフォームです。

www.docker.com

アプリのコードや依存関係、OS情報などをコンテナにしたり、他の人が作ったコンテナ用の情報を自分の環境にダウンロード・展開したりするのにはDocker(または代替技術)が必要です。

先ほどの例で言うと、Dockerは小屋を建てる大工さん、また後程出てくる「リポジトリ(レジストリ)」は小屋の注文カタログのようなイメージです。

分かりにくかったので、アプリ開発後からDockerを使って別の端末のコンテナで動かすまでの流れを4コマで図示してみました。

①【開発者側】アプリのコンテナ化

コンテナ化にはDockerのインストールが必要です。この4コマではすでにローカルにインストールが済んでいる前提で話します。
アプリをコンテナにするために必要な情報を書き込んだ「Dockerfile」というファイルを用意し、それを使ってdocker buildコマンドで「コンテナイメージ」を作ります。

イメージその1。コンテナイメージ作成まで。
これが「コンテナ化」

Dockerファイルはコンテナ設計のための指示書のようなイメージです。
どんな言語のどのバージョンで書かれたアプリか、どんな依存ライブラリが必要か、Webアプリの場合はポート番号、、ベースとなるコンテナイメージ(例:UbuntuやAlpine)、環境変数、などの指示を書き込みます。

コンテナイメージとは、アプリ情報をDocker fileの指示通りにまとめたパッケージです。
普段使うようなファイルの形式ではなく、全ての依存関係などをカプセル化という技術で読み取り専用のレイヤー状の集合体にしているそうです。これはDockerの内部ストレージに保管されます。
これにより、そのアプリを実行する環境情報ごと他の場所に持っていって展開できるようになります。

docker buildとは、Dockerfileをもとに、アプリをコンテナイメージ化するためのコマンドです。

②【開発者側】コンテナイメージのプッシュ

今はまだ、コンテナイメージはローカルにとどまっています。
これを他の人にも共有するために、docker tagコマンドでのタグ付けと、docker pushコマンドでのリポジトリへのアップロードを行います。

イメージその2。コンテナイメージをリポジトリにプッシュする。

docker tagというのは、すでにビルドしたコンテナイメージに新しい「名前(リポジトリ名)とバージョン(タグ)」を付けるための操作です。 プッシュにはタグ付けが必須です。 タグ付けすることでそのコンテナイメージはリポジトリ内での一意のものとなり、バージョンなどが混ざらないよう管理できます。(設定にもよりますが、同じタグ名を利用するとリポジトリ内の既存コンテナイメージが更新されます)

docker pushというのは、ローカル環境(開発者のPCなど)にあるDockerイメージを、リモートのコンテナレジストリ(Docker HubやAmazon ECRなどいくつかの種類があります)にアップロードする操作です。
自身が使うリポジトリにログイン・アクセスし、そこにコンテナイメージをアップロードして管理していきます。
リポジトリにはプライベートとパブリックがあり、アクセス範囲を制御したり、全世界に公開したりできます。

これで、リポジトリへの権限を持つ利用者ユーザー(図の右のユーザー)はコンテナイメージにアクセスできるようになりました。

※ブログ内で「リポジトリ」と「レジストリ」の用語が混在していますが、コンテナレジストリというのがDocker HubやAmazon ECRなどの「リポジトリをまとめるサービス自体の呼び方」で、レジストリの中に複数のリポジトリを切り分けています。
Github上に多数のRepositoryがあるイメージが似ていると思います。

本ブログ内ではほぼ同じ意味で読み替えていただければと思います。

③【利用者側】コンテナイメージのプル

今度は利用者側の視点です。

利用者も、dockerが無いとコンテナイメージをダウンロード(pull)したりそれを立ち上げたりすることが出来ません。
リポジトリに対して「このコンテナイメージが欲しい」という指示をします。

イメージその3。利用者側がリポジトリからコンテナイメージをpullする。

docker pull コマンドをタグ名を指定して使うことで、リポジトリに対して「このタグ名のコンテナイメージが欲しい」という指定を行えます。

これにより、利用者側のdockerが管理するローカルストレージにコンテナイメージが管理される状態になりました。
ただ、まだイメージがあるだけでアプリは動いていません。

④【利用者側】コンテナの起動

いよいよ、コンテナイメージを起動し、利用者のローカル環境内にコンテナを立ち上げます。
コンテナではアプリが動かす環境が整うので、利用者は既存の環境に関わらずアプリを使えるようになります。

イメージその4。pullしたコンテナイメージをもとにコンテナを起動し、アプリを動かす環境が整う

docker run コマンドを使用することで、コンテナイメージから実際のコンテナを立ち上げます。

コンテナは仮想化という技術を使っていて、ローカル環境の中に論理的に隔離された環境を作り、その中で指定ファイルを使ってアプリを立ち上げたり、その他の環境を準備したりします。 「仮想マシン」がOS丸ごと仮想化する一方で、コンテナはもっと軽量で、アプリ実行に特化した部分を仮想化しているそうです。

これで、利用者が「コンテナでアプリを動かしている状態」になったわけです。

ここまでのまとめ

Docker周りまとめ

Dockerを使うと、Dockerの技術をDockerコマンド経由で使えるようになります。

以下がキーワードになってきます。

  • Dockerfile
  • docker build
  • docker tag
  • docker push
  • docker pull
  • docker run

Gitリポジトリとの違い

超初心者の自分は最初は「gitでのリポジトリ管理とは何が違うの?」と思っていましたが、こうして図で整理してみるとだいぶ違いますね。

Gitリポジトリは、アプリの設計図(ソースコード)と、その設計図の変更履歴を管理する場所です。

Gitリポジトリが「これこれこういう材料を使って、こういう手順で作ってくださいね」という情報(コード)の集合体だとしたら、コンテナは「はい、もう作ったから電源入れたらすぐ使えますよ」いう、すぐに使える状態のパッケージです。

アプリのコードだけではなく依存関係やOSや言語の情報、ポート番号や環境変数などの情報をひとまとめにして、dockerの技術で環境を立ち上げてもらうところまでできるのがいいのですね。

Amazon ECRとは?

ということで、ようやくAWSに戻ってきました。

上記のDockerの図の中で、 Amazon ECRは「リポジトリ(レジストリ)」の部分に該当します。
コンテナイメージをリポジトリ別・タグ別に管理していく部分ですね。これは分かりやすいです。

次のAmazon ECS部分は、新要素が出てきます。

Amazon ECSとは?

Amazon ECS(Elastic Container Service)は、よく「コンテナの面倒をまとめて見てくれる、【フルマネージドのコンテナオーケストレーションサービス】」と表現されている気がします。よく分からないですよね。
分かるように解説していきます。

「コンテナオーケストレーション」とは?

まず前提として、本番環境でのコンテナの利用を想像してみてください。

こんな環境。複数のコンテナでユーザーのリクエストを処理、バックエンドにデータベースがある。

EC2やRDSと同じように、あるアプリケーションコンテナに対し、例えば以下のような「運用」が必要になってきます。

  • コンテナをどこで動かすか
    • どのサーバーでどのコンテナを何台動かすか
    • このサーバーでこのコンテナを動かすのにメモリが足りるか
  • コンテナのスケーリング
    • アクセスが増えたらコンテナを増やして、アクセスが減ったら減らしたり消したり
  • アプリに障害が発生
    • どのサーバーのどのコンテナが落ちたのか原因切り分け
    • 新規で入れ替え
  • コンテナのバージョンアップ
    • 新規バージョンにバグがあったら障害になる
    • 新しいバージョンのアプリを既存のコンテナと入れ替えるのはどうしたらいいか

これを、全部別々に手動で設定・運用していくなんて考えたくないですね。

そこで、それらを1つの場所から一元管理・自動化設定ができるようにした技術があります。それが、「コンテナオーケストレーションツール」です。

Kubernetes(クーバネティス、K8s)、Docker Swarm(ドッカースウォーム)、そして Amazon ECS(Elastic Container Service)・ Amazon EKS(Elastic Kubernetes Service) などがそれにあたります。

※ Kubernetes、Docker SwarmはAWS(クラウド)外でも使える技術であり、Amazon ECS・ Amazon EKSはAWS上でコンテナオーケストレーションができるようにしたAWS提供サービスです。

これらは、「CPU使用率が〇〇%になったらコンテナを△個増やす」、「コンテナが止まってしまったら、自動的に新しいコンテナを起動し直す」のような設定をして、自動的にコンテナの数を増減させたり、監視したりしてくれます。

コンテナオーケストレーションツール(ECS)のイメージ

ECSに限らず、コンテナオーケストレーションツールの動作イメージは以下図のようになります。
コンテナ運用管理を行う領域は「コントロールプレーン」と呼ばれ、コンテナを動かす実行環境は「データプレーン」と呼ばれます。

ピンクの枠範囲がコンテナオーケストレーションツールのイメージ。
管理を行う領域は「コントロールプレーン」と呼ばれ、実際に管理対象になるサーバやコンテナ自体は「データプレーン」と呼ばれる。

Amazon ECSとは?

ということで、Amazon ECSとは、「AWS上でコンテナオーケストレーションツールが使えるように提供されるAWSのサービス」です。

特長としては、「AWSネイティブ」があります。

最初からAWS仕様で作られたコンテナオーケストレーションツールなので、AWS上の他のサービス(ロードバランサー、CloudWatchなど)や認証との連携がスムーズだったり、AWS側でマネージドにやってくれる部分がより多くて追加学習が不要だったり(これは嘘ですね)、ユーザーの負担が少なくなっています。

「AWS上でコンテナを使う」となったら、まず選択肢に上がるのがECSです。

また、「AWS上でコンテナを使う」ことをサポートするための技術なので、コンピューティング(先ほどのイラストでラップトップやサーバーだった部分)は「AWS上のコンピューティングサービス」になります。

主に、EC2とFargateという二つの選択肢があります。(違いは後述)

FargateやEC2といったコンピューティングサービス上でコンテナが動く

Amazon ECSとAmazon EKSとの違いは?

先ほど、以下のように書きました。

Kubernetes、Docker SwarmはAWS(クラウド)外でも使える技術であり、Amazon ECS・ Amazon EKSはAWS上でそれを使えるようにしたAWSのサービスです。

Amazon EKSは、「AWS上でKubernetesが使えるように提供されるAWSのサービス」です。

このKubernetesが何かというと、Googleが主導したオープンソースのコンテナオーケストレーションツールです。
Kubernetesは10年以上の歴史を持ち、世界中にパートナー企業を持つ人気の技術です。

ECSはKubernetesではなく独自のコンテナ管理技術で動いているので、「これまでKubernetesを使っていたサービスをAWS移行したい・オンプレミスとハイブリッドで一律の技術を使いたい」といったときには選択肢になってきます。
使用にはAWSに加えてKubernetesの知識も必要になるので、ECSよりも手軽さは落ちる(その分カスタマイズ性は高い)ので、用途に合わせて選ぶことが大事です。

kubernetes.io

項目 Kubernetes (K8s) Docker Swarm Amazon ECS Amazon EKS
利用環境 オンプレミス、任意のクラウド (ベンダーニュートラル) 主にDocker環境が動作する場所 AWS環境に特化 AWS環境に特化
提供者 CNCF (Cloud Native Computing Foundation) - Googleが開発を主導 Docker社 Amazon Web Services (AWS) Amazon Web Services (AWS)
位置付け コンテナオーケストレーションの事実上の標準 Docker標準の簡易オーケストレーション AWSネイティブのフルマネージドコンテナサービス AWSマネージドのKubernetesサービス
学習コスト 高い (機能が豊富で概念が多い) 低い (Dockerに標準で入っているので、その延長で使える) 中程度 (AWSの概念知識が必要) 中程度〜高い (K8s知識 + AWS概念知識が必要)
セットアップ 複雑 (自前で構築する場合は手間がかかる) 簡単 (Dockerコマンドで数分) AWSコンソール/CLIで設定 (マネージド) AWSコンソール/CLIで設定 (マネージド)
運用負担 高い (自前で基盤を管理する場合) 低い (簡易的) 低い (AWSがコントロールプレーンを管理) 低い (AWSがコントロールプレーンを管理)
特徴1 強力な自己修復、スケーリング、サービスディスカバリ機能 Docker Composeファイルからの移行が容易 Fargateでサーバー管理不要な運用が可能 標準K8sと高い互換性
特徴2 豊富なエコシステムとコミュニティ 小規模なクラスターや簡易的な利用向け AWSの各種サービスとシームレスな連携 AWSのセキュリティ・監視機能と統合
複雑度 大規模、複雑なシステム構築に向く 小〜中規模のシンプルな運用向け AWSのベストプラクティスに従いやすい 既存のK8s資産をAWSに移行しやすい
ユースケース 大規模マイクロサービス、ハイブリッドクラウド運用など 小規模アプリ、PoC (概念実証)、学習 AWS上でコンテナアプリを動かす最も簡単な方法 AWS上でKubernetesを運用したい場合、オンプレ・マルチクラウドなどのハイブリッド環境での運用をしたい場合

Amazon EC2とAWS Fargateの違いは?

どちらも、Amazon ECSの「起動タイプ」と呼ばれます。

Amazon EC2というのは、「普通にEC2(AWSの一般的な仮想サーバーサービス)上にコンテナを立てましょうね」ということです。
詳細はEC2について調べていただければと思いますが、OSやCPU、メモリなどのスペックは自分で選ぶ必要があります。

AWS Fargateは「コンテナがどこで動いているか?」を意識せず、多くの部分をAWS側で用意してくれます。
その代わり、AWS側で管理する部分の自由度は落ちます。

例えるならこう。遊ぶ子供たちはコンテナ、遊ぶ場所はデータプレーン(コンテナ実行環境)のイメージ。

違いは以下の表のとおりです。

項目 EC2(仮想サーバー) Fargate(サーバーレスコンテナ実行環境)
管理範囲 サーバー、OS、ミドルウェアなど、ユーザーがすべて管理する AWSがすべて管理する
サーバー 自分でインスタンスタイプを選択・起動・管理する
(インスタンスを用意またはAutoScaling設定しておく必要がある)
意識しない
AWSが裏で最適なリソースを自動で割り当てる
コスト インスタンスの起動時間とタイプに応じて課金(予約も可) コンテナの実行時間と使ったリソース(CPU/メモリ)に応じて課金
自由度 高い。 基本何でもできる(EC2の機能が使える) 低い。 コンテナを動かすことに特化している
SSH接続 できる。EC2インスタンスにSSHでログインして、直接サーバーやコンテナのログを確認したり、デバッグしたりできる できない。 (※ただしdocker execという機能を使えば接続可能)
スケーリング EC2インスタンスのAuto Scaling Groupを自分で設定して、クラスターのEC2インスタンス数を自動調整する必要がある(やや複雑) タスク(コンテナ)単位で自動スケーリングが可能。
指定したCPUやメモリの量に合わせ、AWSが自動で最適なサーバーリソースを割り当ててくれる(簡単)
セキュリティ EC2インスタンスのOSレベルからのセキュリティ設定や、ネットワークセキュリティグループの管理など、ユーザー責任範囲が広い 基盤となるインフラのセキュリティはAWSが担当してくれるから、ユーザー管理負担は狭い。
タスクレベルでの隔離がされるため、よりセキュアな環境を作りやすい
ユースケース ・コストを徹底的に最適化したい(特に長期間・高稼働率で使う場合)
・特定のEC2インスタンスタイプ(GPUインスタンスなど)を使いたい
・OSや基盤ミドルウェアを細かくカスタマイズしたい
・サーバーにSSH接続してデバッグしたい
・サーバー管理の手間をゼロにしたい
・開発に集中したい
・急なアクセス変動に柔軟に対応したい(サーバー管理なしで自動スケーリング)
・コストをシンプルに把握したい(使った分だけ課金)
・高いセキュリティと隔離性が欲しい

Amazon ECS、Amazon EC2、AWS Lambdaの違いは?

上記章タイトルは、EC2とLambdaばかり触っていた私がECS勉強前に思っていた疑問です。

今は、だいぶ違うことがわかります。

  • ECS:コンテナオーケストレーションサービス。FargateとEC2という二つの起動タイプから選んで、その上にコンテナを立てたり、管理したりできる。コンテナとは、アプリケーションの実行に必要な環境情報を丸っと包んで配付・実行できる技術。
  • EC2:仮想サーバーサービス。ECSの起動タイプとして選択することで、コンテナを動かす基盤として使うことが出来る。コンテナ基盤以外にも普通にサーバーとして使うこともできる。
  • Lambda:そもそもサーバーを気にせずに「関数」を実行するサービス。その実行時だけコンピューティングが行われればいいという、イベント駆動型の考え方。「~という条件(スケジュール、S3PUTEventなど)の時にこの関数を実行したい」というような要望に応えられる。

Lambda・ECS・EC2、それぞれの考え方と位置づけ

Lambdaはあくまでその時だけの実行なので、タイムアウトまでの最大実行時間が15分に限られています。
例えばバッチ処理などは、その処理の複雑さや処理時間と合わせてどちらを採用するかを決める形になります。

おまけ:AWS Lambdaでもコンテナイメージを使えます

blog.serverworks.co.jp

コンテナイメージを作るときは、Lambda用のエントリポイントとコマンドを指定するようです。

Amazon ECS使用時の各コンポーネントの位置づけは?

技術的詳細は以下のブログが詳しいです。

blog.serverworks.co.jp

本ブログではこのブログから以下の図を引用し、「クラスター」「タスク定義」「タスク」「サービス」というAWS ECS周りの用語についての位置づけがイメージしやすくなるように、例を用いて解説します。

全体の図を引用

定義と例え

簡単にまとめると以下のようになります。

  • コンテナイメージ: 例えるならコンテナ自体の設計書。アプリを動かすために必要な環境セット。AWSの場合、Amazon ECRイメージとも。
  • タスク定義: 例えるなら作業マニュアル、レシピ。ECRにあるイメージをどこで、どれくらいのメモリとCPUで動かすかだったり、どのポートを使うかコンテナの動かし方の指示書。
  • タスク:タスク定義に基づいて実際に動いているコンテナの実行単位。動いているものを指す。1つのタスク定義から複数のタスク(実行中のコンテナ)を起動できる。
  • サービス: 例えるなら現場監督。マニュアル通りに色々やってくれる監督ロボット。
  • クラスター: 例えるなら遊び場・作業場。サービスによってコンテナを動かす場所、環境。起動タイプ(実行基盤環境)でFargate, EC2で選べる。

サッカーというタスクをする場合で考える

タスク定義・タスク

タスク定義:「コンテナイメージを、AWS ECS上でどうやって起動して動かすか」という、ECS固有の実行設定ファイルのこと。JSON形式で記述され、以下のような情報を含みます。

  • どのコンテナイメージを使うか: ECRのURLなどを指定可能。{アカウントID}.dkr.ecr.{リージョン}.amazonaws.com/{リポジトリ名}:{タグ}のような形式
  • CPUとメモリの割り当て: 「このコンテナにはCPUを1コア、メモリを2GB使わせてね!」など、リソースをどれくらい使うか決められる
  • ポートマッピング: 「コンテナのポート80番を、外からアクセスするときはホストのポート8080番にマッピングしてね!」のように、ネットワークの設定が可能
  • 環境変数: コンテナの起動時に渡したい秘密の情報や設定値。データベースの接続情報などが該当
  • ログの設定: コンテナが出すログをどこに送るか(CloudWatch Logsなど)
  • コンテナの起動コマンド: コンテナが起動したときに、最初に何を実行するか
  • IAMロール: コンテナがAWSの他のサービス(S3、DynamoDBなど)にアクセスするときに使う権限

タスク は、タスク定義によって定義された設計に基づき、実際に起動されるECSのスケジューリング単位のこと。

ECSはコンテナの数で考えるのではなく、タスクという「1つ以上のコンテナの集合」という実行単位で管理しています。

その他、以下のような特徴があります。

  • タスク定義をもとに起動される
  • 寿命がある。起動後、処理を終える・エラーで停止する・ユーザーに停止される、まで動き続ける。Webサイトのようにずっと動く場合もあればバッチ処理のようにすぐ停止するタスクもある
  • 各タスクはネットワークインターフェース(ENI)を持ち、独立している
  • 「1つのタスク定義に1つのコンテナ」というパターンの他、「1つのタスク定義に複数のコンテナ」で一塊として扱うパターンもあります。これはマルチコンテナタスクと呼ばれ、「複数のコンテナが密接に関連していて、同じライフサイクルを共有すべき」場合に使われます。(「メインのWebサーバーコンテナ」と「そのWebサーバーのログをリアルタイムでS3に送るサイドカーコンテナ」を一緒に動かしたい場合など。)タスク定義の中に二つのコンテナイメージを含めることで設定が可能です。

マルチコンテナタスクのイメージ

コンテナイメージとタスク定義の違い

コンテナイメージは「アプリとそれを動かすために必要な部品が入った設計図兼パッケージ」。ECRなどのリポジトリ内にプッシュし、プルなどして使う。コンテナ技術の一般的な用語。

タスク定義は、「コンテナイメージを、AWS ECS上でどうやって起動して動かすか」という、ECS固有の実行設定ファイルのこと。AWS ECS専用の概念。

サービス

サービスは、タスクを自動で監視・維持し、可用性を高めるAmazon ECSのコンポーネントです。
事前にサービスの中身の設定をすることで、「動いてるコンテナのグループ」であるタスクを、設定どおりに、自動かつ安定的に管理してくれます。

具体的には以下のような設定ができます。

  • Desired Count: 設定したタスク数を自動で保ってくれる、タスクの常時維持機能。タスクが1つ落ちたら自動で設定した数に戻してくれる。
  • ロードバランサー連携: 複数のタスクにアクセスを分散。サービスをApplication Load Balancer (ALB) ・ Network Load Balancer (NLB) に紐付けることで、起動したタスクを自動でロードバランサーのターゲットグループに登録できる。
  • デプロイメント戦略: アプリの更新をスムーズに安全に実行する。新しいバージョンのアプリケーション(新しいタスク定義)をデプロイするときに、ローリングアップデート・ブルーグリーンデプロイなど、切り替え方法を設定できる。
  • Auto Scaling: アクセス量に応じてタスク数を自動調整できる。CPU使用率やアクセス量などで管理可能。

もしサービスを使わずにタスクを直接起動した場合、タスクは起動はされるものの、何かの拍子で停止してしまったらそれっきりアプリが使えなくなってしまいます。Webサーバーのように動かし続けたり、一定の可用性を保ちたい場合に特に役立ちます。

クラスター

クラスターとは、ECSでコンテナを動かすための「リソースの論理的なグループ」です。
タスクやサービスは、必ずどれかのクラスターに属する必要があります。

そのクラスター設定として、実際にコンテナが動く「実行基盤(インフラ)」としてFargateとEC2を紐づけることで、クラスター内での起動をすることが出来るようになります。

ECSを使う流れ(概要)

ECRのイメージからECS上でコンテナを動かす流れの例は以下のようになります。

  1. コンテナイメージ(コンテナの設計図)をECRに用意する。
  2. タスク定義(コンテナの動かし方の指示書)を作り、コンテナイメージやCPU・メモリ、ポート、環境変数・ログなどを指定する
  3. クラスター(Fargate, EC2)を用意する。
  4. サービスを作り、「指定したタスク定義のコンテナを、指定した数だけクラスター内で動かし続ける」という指示をする。スケーリングの設定なども可能。
  5. それにより、サービスがクラスター内で、指定したタスク定義のコンテナを指示通りに動かしてくれる

ECSパラメータまとめ

それぞれの関係性が分からなくなったらご確認いただければ幸いです。

再掲

実践編(リンクのみ)

これまでのまとめとして、実際にDockerからコンテナイメージを作り、コンテナを動かす流れは以下のようになります。

  1. アプリケーションファイルを用意し、Dockerfileを作成する
  2. (必要であれば)Dockerを開発環境にインストールする
  3. Docker buildで開発環境上にコンテナイメージを作成する
  4. ECRにリポジトリを作成し、開発環境からコンテナイメージをプッシュする
  5. タスク定義(コンテナの動かし方の指示書)を作り、コンテナイメージやCPU・メモリ、ポート、環境変数・ログなどを指定する
  6. クラスター(Fargate, EC2)を用意する。
  7. サービスを作り、「指定したタスク定義のコンテナを、指定した数だけクラスター内で動かし続ける」というような指示をする。それにより、サービスがクラスター内で、指定したタスク定義のコンテナを指示通りに動かしてくれる

以下のブログが参考になるかと思います。 上記のDockerまわり・Amazon ECS周りの用語の図と見比べながら実施してみてください。

blog.serverworks.co.jp

blog.serverworks.co.jp ※現在はCloud9を新規で使うことはできないので、自分はローカル環境を利用してコンテナイメージを作るところから実施しました↑

また、Amazon ECSを使わず、ECS上でDockerを使ってみるようなブログもありますので是非こちらもご覧ください。

blog.serverworks.co.jp

今回は、自分が躓いたDockerインストール周りのみ記載しておきます。

(初めての場合)Dockerのインストール

必要に応じて実施してください。 以下のようにDockerのバージョンを確認すると、インストール出来ているかが分かるかと思います。

$ docker -v
Docker version 28.3.1, build 38b7060

私はWSLを使ったUbuntu環境だったので、こちらを参考にインストールしました。

※なお、GUIで操作しやすいDocker Desktopというものもあるようです。一定規模の企業の業務利用の場合ライセンスが必要などありますが、もしよければ調べてみてください。

www.docker.com

# Dockerの公式GPGキーを追加する。 これがないとダウンロードするパッケージが正しいものか確認できないため、まずはこのコマンドで信頼できるキーを手に入れる。
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

# Dockerのリポジトリをaptのソースリストに追加する。これでUbuntuがDockerのパッケージを見つけられるようになる。
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update

Dockerのリポジトリをシステムに追加したので、いよいよDocker本体をインストールします。

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Dockerのインストールが完了したら、正しく動作するか確認するための最初のステップが、このhello-worldコンテナの実行です。

$ sudo docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
e6590344b1a5: Pull complete 
Digest: sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

hello-worldは実行したいコンテナイメージの名前です。docker runコマンドが実行されると、まず開発環境(ローカルPC)にこのhello-worldイメージがあるかを探します。

もしローカルにイメージがない場合、Dockerは自動的にDocker Hub(Docker公式のパブリックコンテナレジストリ)からこのイメージをダウンロード(プル)してきます。

これにより、「DockerクライアントがDockerデーモンと通信し、リモートのレジストリからイメージをプルし、そのイメージからコンテナを起動して、アプリケーションを実行する」という、Dockerの基本的なサイクルをテストできます。

確認として、Dockerのバージョンを確認すると、無事にインストールが完了していることがわかります。

$ docker -v
Docker version 28.3.1, build 38b7060

エラーについて

コード実行中、ERROR: permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Head "http://xxxxxxdocker.sock/_ping": dial unix /var/run/docker.sock: connect: permission denied のような権限エラーが出ました。

sudo usermod -aG docker $USER を実行してPCを再起動した結果うまくいきました。

まとめ

という訳で、全体像を図解してまいりました。

コンテナのイメージ

Docker周りまとめ

Amazon ECS周りまとめ

ただ「Amazon ECS」を知りたいだけなのに、理解が必須の派生概念が多すぎて大変ですね。

このブログが皆様の助けになれば幸いです。

●本ブログは2025 AWS Jr.Champions内の企画「コンテナ/サーバーレス領域アウトプットもくもく会(# 2025-output-lab-containers)」の7月企画の中で検証・発表した内容になります。ありがとうございました。

垣見(かきみ)(執筆記事の一覧)

2023年新卒入社 エンタープライズクラウド部所属 2025 Japan AWS Jr.Champions

図解するのが好き。「サバワク」のアイキャッチ作成も担当しています