AWSコンテナ入門〜コンテナイメージの作成からECSまでのデプロイ〜

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

技術1課の櫻井です。 自分の勉強も兼ねてECSでコンテナをデプロイするハンズオンを行ってみました。 といっても最初からECSに触れるのではなく、自分でコンテナイメージを作成するところから行ってみようと思います。

今回の目標

今回の最終目標は、ECSを用いてコンテナをデプロイ&インターネットからそのコンテナにアクセスするというものになります。 下の画像のような簡単なWebページを作成していきます。 構成としては以下のような形となります。

初めに自分の環境でコンテナイメージを作成、作成したイメージをECRにアップロード、アップロードしたイメージをECSにデプロイといった流れで進めて行きます。

コンテナイメージの作成

コンテナイメージとは簡単にまとめると、「コンテナの内容を記したテンプレート」になります。コンテナそのものと混同するかもしれませんが、コンテナはこのコンテナイメージを基に作成されます。CloudFormationテンプレートがある環境の構成情報をまとめているようなもので、コンテナイメージにはコンテナのOSやミドルウェアの情報が含まれます。まずは自分でこれを作成してみましょう。作成する環境はCloud9を利用します。

Cloud9の準備

①Cloud9のコンソール画面に移動して以下の設定でCloud9を作成 Cloud9の作成完了まで2~3分待ちます。

②Cloud9の作成が完了したら実際に環境に入ってみる Cloud9のコンソールから先ほど作成したものの[開く]を選択してください。

するとIDEが表示されます。次はこのIDEの画面下のターミナルから実際にコンテナイメージを作成してみます。

自分でコンテナイメージを作成してみる

コンテナイメージの作成には後述するDockerfile利用して自動化するのが一般ですが、その利点を理解するためにもまずは手動でコンテナイメージを作成してみましょう。

① docker pullコマンドでUbuntuのコンテナイメージをダウンロード まずはUbuntuのOS情報が含まれる必要最低限のコンテナイメージをダウンロードします。

administrator:~/environment $ docker pull ubuntu
Using default tag: latest
latest: Pulling from library/ubuntu
6b851dcae6ca: Pull complete 
Digest: sha256:6120be6a2b7ce665d0cbddc3ce6eae60fe94637c6a66985312d1f02f63cc0bcd
Status: Downloaded newer image for ubuntu:latest
docker.io/library/ubuntu:latest

② docker images コマンドを実行 先ほどダウンロードしたイメージが確認できます。 必要最低限の情報なのでイメージのサイズは非常に小さいです。

administrator:~/environment $ docker images
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
ubuntu       latest    99284ca6cea0   3 weeks ago   77.8MB

③ docker psコマンドで現在起動しているコンテナを確認 まだコンテナを起動していないので何も表示されません。

administrator:~/environment $ docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

④ docker run コマンドでコンテナを起動 プロンプトが $ から # に変更しています。# 表記のプロンプトで実行するコマンドはコンテナ内で実行されるので、 これでコンテナの中に入ったことがわかります。

administrator:~/environment $ docker run -it --name apache ubuntu
root@ec13f9e3fee4:/# 

⑤ コンテナにApache をインストール Ubuntuのコンテナが起動しましたがこのままでは何も入っていないのでApacheを入れます。

はじめにパッケージリストを更新します。

root@ec13f9e3fee4:/# apt-get update
Get:1 http://security.ubuntu.com/ubuntu jammy-security InRelease [110 kB]
(略)

次にApacheをインストールします。

root@ec13f9e3fee4:/# apt-get install apache2 -y
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
(略)

⑥ Apacheの動作確認

Apacheを起動してみます。

root@ec13f9e3fee4:/# service apache2 start
 * Starting Apache httpd web server apache2 
(略)

root@ec13f9e3fee4:/# service apache2 status
 * apache2 is running

起動できたので、curlコマンドでサンプルページをみてみます。

root@ec13f9e3fee4:/# curl localhost
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <!--
    Modified from the Debian original for Ubuntu
    Last updated: 2022-03-22
    See: https://launchpad.net/bugs/1966004
  -->
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Apache2 Ubuntu Default Page: It works</title>
    <style type="text/css" media="screen">
(略)
  </body>
</html>

サンプルページのHTMLが表示されました。

⑦ コンテナイメージとして保存する。 Apacheが入っている状態のコンテナをイメージとして保存してみます。

まずコンテナから抜けます。

root@ec13f9e3fee4:/# exit
exit
administrator:~/environment $ 

次にdocker commit コマンドで先ほど操作していたコンテナ apcaheをコンテナイメージapache_imageとして保存します。

administrator:~/environment $ docker commit apache apache_image
sha256:299f7daead4567cde187653c38f17ef1056eed031108850b8ac25f4d9b14fc01

docker imagesコマンドを使用するとapache_imageというコンテナイメージが作成されていることがわかります。

administrator:~/environment $ docker images
REPOSITORY     TAG       IMAGE ID       CREATED          SIZE
apache_image   latest    299f7daead45   9 seconds ago    227MB
ubuntu         latest    99284ca6cea0   3 weeks ago      77.8MB

これでapacheが含まれるコンテナイメージが作成できました。 今回はApacheのインストールのみだったため簡単でしたが、 実際にコンテナの中に入ってカスタマイズするのは手間が多いです。 そこで次はDockerfileを使用して簡単にコンテナイメージを作成してみます。

Dockerfileからコンテナイメージを作成

Dockerfileとは、コンテナイメージの設計図のようなものです。 新規にコンテナイメージを作成する際の手順を記したテキストファイルになります。 このDockerfileを使用することで、Dockerfileに記述された指示を基にコンテナイメージが作成され、先ほど手動で行っていたApacheのインストールなどを自動化することが可能となります。

①Dockerfileの作成 Cloud9上にてそのままDockerfileという名称でファイルを作成します。 (ファイル一覧を右クリックしてNew fileを選択するとファイルが作成されます。)

②Dockerfileの編集

以下の内容を先程作成したDockerfileへ貼り付けて保存します。

FROM ubuntu:18.04
​
# Install dependencies
RUN apt-get update && \
 apt-get -y install apache2
​
# Install apache and write hello world message
RUN echo 'Hello World!' > /var/www/html/index.html
​
# Configure apache
RUN echo '. /etc/apache2/envvars' > /root/run_apache.sh && \
 echo 'mkdir -p /var/run/apache2' >> /root/run_apache.sh && \
 echo 'mkdir -p /var/lock/apache2' >> /root/run_apache.sh && \ 
 echo '/usr/sbin/apache2 -D FOREGROUND' >> /root/run_apache.sh && \ 
 chmod 755 /root/run_apache.sh
​
EXPOSE 80
​
CMD /root/run_apache.sh

参考 AWS Document : https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/docker-basics.html

Dockerfileの内容は以下のとおりです。

  • 作成するコンテナイメージの基となるベースイメージは DockerHub で公開されている Ubuntu 18.04
  • Web サーバーとして Apache HTTP Server をインストール
  • 実際の Web ページに表示するために index.html を作成
  • EXPOSE で、このコンテナは 80 ポート(HTTP) を利用することを宣言

HTML ファイルから Dockerfile の文字列を張り付ける際は、ノーブレークスペースが入ることがあるとのことなので、以下のコマンドでノーブレークスペースを削除します。

administrator:~/environment $ sed -i "s/$(echo -ne '\u200b')//g" Dockerfile

③Dockerfileからコンテナイメージを作成 docker buildコマンドで実際にDockerfileで定義した情報を元にコンテナイメージを作成します。 -t オプションでイメージ名を指定します。

administrator:~/environment $ docker build -t apache_image2 .
Sending build context to Docker daemon  14.79MB
Step 1/6 : FROM ubuntu:18.04
18.04: Pulling from library/ubuntu
7c457f213c76: Pull complete 
Digest: sha256:152dc042452c496007f07ca9127571cb9c29697f42acbfad72324b2bb2e43c98
Status: Downloaded newer image for ubuntu:18.04
 ---> f9a80a55f492
(略)

docker imagesコマンドを実行すると作成したコンテナイメージを確認できます。

administrator:~/environment $ docker images
REPOSITORY      TAG       IMAGE ID       CREATED          SIZE
apache_image2   latest    b250d012635e   31 seconds ago   205MB
apache_image    latest    299f7daead45   39 minutes ago   227MB
ubuntu          18.04     f9a80a55f492   4 weeks ago      63.2MB

コンテナイメージをECRへアップロード

これでコンテナイメージを作成することができましたが、このままではCloud9上でしかコンテナが動作しません。 ECSにデプロイできるようにまずはECRへコンテナイメージをアップロードしましょう。

ECRとは

ECRとはElastic Container Registry の略で名前の通り、コンテナイメージを保存・管理するためのレジストリとなります。

リポジトリの作成とアップロード

①ECRのコンソール画面に移動して画面左のナビゲーションペインから「Repositories」→「リポジトリを作成」を選択

②以下の設定でリポジトリを作成

③リポジトリが作成されたらURIを控えておく

④Cloud9 に戻り、再度 docker build を実行

先程作成したDockerfileを元にECRアップロード用のイメージを作成します。

書式

docker build -t <ECR の URL>:<イメージのバージョン Tag> .

実行例

administrator:~/environment $ docker build -t 566122949358.dkr.ecr.ap-northeast-1.amazonaws.com/container-handson:0.0.1 .                                          
Sending build context to Docker daemon  14.79MB
Step 1/6 : FROM ubuntu:18.04
 ---> f9a80a55f492
Step 2/6 : RUN apt-get update &&  apt-get -y install apache2
 ---> Using cache
 ---> bec10f9cc722
Step 3/6 : RUN echo 'Hello World!' > /var/www/html/index.html
 ---> Using cache
 ---> 2520ef532bff
Step 4/6 : RUN echo '. /etc/apache2/envvars' > /root/run_apache.sh &&  echo 'mkdir -p /var/run/apache2' >> /root/run_apache.sh &&  echo 'mkdir -p /var/lock/apache2' >> /root/run_apache.sh &&  echo '/usr/sbin/apache2 -D FOREGROUND' >> /root/run_apache.sh &&  chmod 755 /root/run_apache.sh
 ---> Using cache
 ---> 0a9365b176bc
Step 5/6 : EXPOSE 80
 ---> Using cache
 ---> 3fa15cd3ff6e
Step 6/6 : CMD /root/run_apache.sh
 ---> Using cache
 ---> b250d012635e
Successfully built b250d012635e
Successfully tagged 566122949358.dkr.ecr.ap-northeast-1.amazonaws.com/container-handson:0.0.1

docker imagesを実行するとイメージが作成されているのがわかります。

administrator:~/environment $ docker images
REPOSITORY                                                            TAG       IMAGE ID       CREATED       SIZE
566122949358.dkr.ecr.ap-northeast-1.amazonaws.com/container-handson   0.0.1     b250d012635e   2 hours ago   205MB
apache_image2                                                         latest    b250d012635e   2 hours ago   205MB
apache_image                                                          latest    299f7daead45   2 hours ago   227MB
ubuntu                                                                latest    99284ca6cea0   3 weeks ago   77.8MB

⑤docker loginの実施

リポジトリに作成したイメージをアップロードするためdocker loginを行います。 --password-stdin には、コピーしてきた URI のうち、スラッシュ(/)より前の部分を指定してください。 Login Succeeded と表示されれば成功です。

administrator:~/environment $ aws ecr get-login-password | docker login --username AWS --password-stdin 566122949358.dkr.ecr.ap-northeast-1.amazonaws.com
WARNING! Your password will be stored unencrypted in /home/ec2-user/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

⑥docker push で ECR に作成したコンテナイメージをアップロード

リポジトリのURIと先程指定したバージョンタグ0.0.1を指定してアップロードします。

administrator:~/environment $ docker push 566122949358.dkr.ecr.ap-northeast-1.amazonaws.com/container-handson:0.0.1
The push refers to repository [566122949358.dkr.ecr.ap-northeast-1.amazonaws.com/container-handson]
21403b370f4f: Pushed 
3a2cae816da1: Pushed 
f0be3ae910c7: Pushed 
548a79621a42: Pushed 
0.0.1: digest: sha256:22942e66d3f431ae395fdf7e5d1227c90a6835850dfa555bf957f34af5d21950 size: 1155

リポジトリの詳細画面を確認するとイメージがアップロードされています。

ECRのコンテナイメージからECSでデプロイ

自分のコンテナイメージをECRに保存したので準備は完了しました。次にいよいよECSを用いてコンテナをデプロイします。

ECSとは

ECSとはAWS独自のコンテナオーケストレーションサービスです。 先ほどApacheを入れるためにコンテナを起動した際は、当然ですが一つだけコンテナが動いている形となっておりました。 ですが、アプリケーションの冗長化などでコンテナは複数起動されるのが一般的です。 複数台のコンテナを一括で管理するためのものがコンテナオーケストレーション、今回でいうところのECSとなります。

ECS用VPCの作成

ECSでコンテナを作成する前にECS用のVPCを用意します。

①以下の設定でVPCを作成

VPCのコンソール画面へ移動して以下の設定でVPCを作成します。

VPCが作成されたらVPC IDをコピーしてください。

②セキュリティーグループの編集

実際にコンテナに入ってWebページを見れるようにするため、セキュリティグループの変更を行いコンテナに HTTP アクセスを許可します。 セキュリティーグループ一覧に移動したら先ほどのIDを検索窓に入力してVPCのデフォルトセキュリティーグループを選択します。 セキュリティーグループを選択したら[アクション]→[インバウンドのルールを編集]の順に選択します。

以下の画像の通りにHTTPフルアクセスのルールを追加します。

以上で準備は完了です。次から実際にECSを使用していきます。

ECSでデプロイ

クラスターの作成

初めにクラスターを作成します。クラスターとはコンテナが動作する実行環境を定義するものです。 クラスターを別に作成することでコンテナ同士を干渉することなく実行できます。 ここで先ほど作成したVPCとサブネットを指定しましょう。

①ECSのコンソールから[クラスター]→[クラスターの作成]を選択

②クラスター名を指定し、先ほど作成したVPCとサブネットを選択して[作成]を選択(他設定値はデフォルト)

③クラスターが作成される

タスク定義の作成

タスク定義とは、コンテナに使用するコンテナイメージやコンテナが使用するCPU・メモリ・ストレージ容量などを指定します。 タスクとはこのタスク定義に基づいて作成される一つ以上のコンテナの集まりを指します。タスク≒コンテナ(ほぼ同義)と考えてください。 今回のタスク定義では一種類のコンテナしか定義していませんが、複数のイメージを選択して複数のコンテナを定義してタスクとしてまとめることも可能です。

①[タスク定義]→[新しいタスク定義の作成]を選択

②タスク定義ファミリー名を指定後、デプロイするコンテナの名前、とイメージURI、ポートを指定 この際のイメージURIは先ほどECRにアップロードしたものを選択(他設定値はデフォルト)

③今回はCPU・メモリ・ストレージ容量などの他設定値は全てデフォルト

④最後に設定値の確認画面が表示されるのでそのまま画面下の「作成」を選択

⑤タスク定義が作成される

サービスの作成

サービスとはALBやAutoScaling Groupに紐付けられたタスク群であり、実行中のタスクを管理するものとなっています。 タスクをそれ単体でデプロイすることも可能ですが、今回はサービスを作成してコンテナをALBに紐づけてみましょう。

①ECSのコンソールから[クラスター]→先ほど作成したクラスターを選択

②サービスの作成を選択

③「デプロイ設定」を以下の通りに設定

④「ロードバランシング」を以下の通りに設定

⑤他設定値はデフォルトで[作成]を選択 数分待つとコンテナのデプロイが完了する

作成したWebページにアクセス

これで完全にコンテナのデプロイが完了したので実際にWebページにアクセスしてみましょう。

①先ほど作成したサービスを選択

②[ネットワーキング]タブ→DNS名の[オープンアドレス]を選択

③Hello World! と表示されれば成功

実際にECSで稼働するコンテナにインターネット経由でアクセスすることができました。

後片付け

今回の記事の通りにハンズオンを行った方は終了後に、以下のリソースを上から順番に削除してください。

  • ALB
  • TargetGroup
  • ECS Service の Task 数を 0 に変更
  • ECS Service の削除
  • クラスターの削除
  • VPC の削除
  • ECR の削除
  • Cloud9 の削除

まとめ

今回は本当に基礎的な部分しか行いませんでしたが、そもそもコンテナがどのようなものか、そしてECSで動くコンテナがどんなものかイメージが少しでもつければ幸いです。ECSのサービスやタスクといった概念に関しては今回は省略気味に解説してしまいましたが、後ほど詳しく解説する記事も作成してみようと思います。