[AWS]EC2内でDockerコンテナを起動して、ブラウザからアクセスする

こんにちは、システムエンジニアの Kota です。本記事では、 ハンズオン形式で AWS に EC2 を構築して、Docker を install し、Hello world! と表示させてみたいと思います。

  • 対象の読者
    • 開発環境で Docker を使っているけど、デプロイにも使いたい方
    • Docker、AWS に触れてみたい方
    • インフラに興味がある方

過去に Docker についての記事を執筆しているので、基礎知識については、こちらの記事を参照して下さい。

まずは、完成イメージをご紹介します。

完成イメージ

手順としては以下のようになります。

  1. VPCとサブネットの構築
  2. インターネットゲートウェイ(インターネットへの出入口)を作成し、VPC にアタッチする
  3. EC2(サーバー)を立てる
  4. セキュリティグループ(ファイアウォール)を設定する
  5. ルーティングを設定する
  6. SSHでEC2(サーバー)にアクセスする
  7. EC2 に Docker をインストールする

作業中は、完成イメージを持っているとより理解が深まりやすいと思います。

今回の作業は、AWS のアカウントが必要になりますので、まだお持ちでない方は下記のリンクよりアカウントを作成してください。

では、早速やっていきましょう!

1. VPC と サブネットの構築

まずは、VPC と サブネットの構築です。

VPC とは、Virtual Private Cloud の略で、AWS 上での自分のネットワークの領域のことです。サブネットは、VPC の中をさらに細かく分割する領域のことをいいます。今回は、このサブネットの中にEC2を立てたいので、まずはこれらを構築していきます。

  • イメージ図

AWS にログインしたら、ナビバーからVPCを検索し、VPC ダッシュボードに遷移します。

サイドバーからVPC を選択します。

すると、VPCの一覧画面に遷移します。

右上のVPCを作成ボタンからVPCを作成していきます。

作成画面に遷移すると、下記のようなフォームが表示されます。

まずは、名前タグに作成するVPCの名前を入れていきます。

今回はhello-world-dockerとします。

次に IPv4 CIDR ブロックです。

ここでは、IPv4 CIDR ブロックの詳しい説明は割愛しますが、

簡単に説明すると使用するIPアドレスの範囲を指定しています。

192.168.1.0/24 と指定することで、192.168.1.0 ~ 192.168.1.255 までの IPアドレスを使用することを定義しています。

IPv6CIDR ブロックはなし。テナンシーはデフォルト。

タグは、名前タグを入力すると自動で入力されているかと思います。

入力が完了したら、右下の VPC を作成ボタンをクリックします。

下記のように正常に作成されましたとメッセージが表示されます。

一覧画面に戻ると、作成したVPCが表示されているはずです。

次に作成したVPC内のサブネットを作成するため、サイドバーよりサブネットを選択して下さい。

サブネットの一覧画面に遷移しますので、右上のサブネットを作成ボタンからフォームに移動します。

VPC ID は先ほど作成した VPC (hello-world-docker) を選択します。

サブネット名は分かりやすいように名前をつけます。

今回は hello-world-docker-subnet とします。

アベイラビリティゾーンは、アジアパシフィック(東京) / ap-northaneast-1a を指定します。

アベイラビリティゾーンとは、AWS のデータセンターのことです。

日本には複数のデータセンターが存在します。一般的なサービスにおいては、災害などのトラブルに備え、アベイラビリティゾーンを分け、冗長化を図ります(別々のデータセンターにデプロイしておく)。冗長化をすることで、一つのデータセンターでトラブルが合った場合でも、サービスを継続して提供することが出来ます。今回はそこまでの対応はしません。

IPv4 CIDR ブロックは、192.168.1.0/25、タグオプションは、サブネット名を入力していれば反映されているかと思います。

入力が済んだら、サブネットを作成ボタンを押します。


初めに作成したVPC内にサブネットを作成することが出来ました。

2. インターネットゲートウェイ(インターネットへの出入口)を作成し、VPC にアタッチする

次に、インターネットゲートウェイ(以降、IGW)を作成し、先ほど構築した VPC にアタッチしていきます。

IGWは、文字通り、インターネットへの出入口になります。VPC は、デフォルトの状態だと、インターネットへの出入口がありません。インターネットから隔離された、ただの領域です。今回はブラウザからEC2 にアクセスしたいので、隔離されたVPC に出入口を設けて、インターネットへ繋がるように設定していきます。

  • イメージ図

VPCダッシュボードのサイドバーから、IGWを選択します。

選択すると、一覧画面に遷移しますので、右上の作成ボタンを押します。

フォーム画面に遷移しますので、IGWの名前を入力します。

今回は hello-world-docker-internet-gateway とします。

入力したら、作成ボタンを押します。


無事作成できました。

一覧画面に行くと先ほどのIGWが表示されていると思います。次に今作成したものを 1. で作成したVPCにアタッチしていきたいと思います。

一覧画面から先ほど作成したIGWのチェックボックスにチェックを入れ、右上のアクションを押すとVPCにアタッチという項目が表示されるので、クリックします。

フォーム画面に遷移するので、使用可能なVPCから 1. で作成したVPCを選択し、作成ボタンをクリックします。

これで、1. の VPC にIGWをアタッチすることができました。

3. EC2(サーバー)を立てる

  • イメージ図

IGWのアタッチが済んだら、次に VPC のサブネット内に EC2 を立てていきます。

EC2 とは、Elastic Compute Cloud の 略で、AWS 上で構築できる仮想サーバーのことです。

まずは、ナビバーでEC2と検索し、ダッシュボードへ遷移します。

サイドバーのインスタンスをクリックします。

ちなみにインスタンスとは EC2 の単位のことです。

インスタンスの一覧画面右上のインスタンスを起動をクリックします。

最初にAMIを選択します。

AMIとは、Amazon Machine Images の 略で、ページの説明にも記載がある通り、作成するインスタンスに必要なソフトウェアを予めテンプレートとして、用意してくれているものです。

今回は一番上の無料枠になっている Amazon Linux 2 AMI (HVM) を選択します。

次にインスタンスタイプの選択です。

こちらはインスタンスのCPU、メモリ、ストレージ、などのスペックを選択するステップです。こちらは無料枠になっている t2.micro を選択します。

チェックを入れたら右下の次のステップをクリックします。

次にインスタンスの詳細設定です。

細かく設定できますが、今回設定するのは、赤枠の部分のみ設定していきます。

ネットワークは 1. で作成した VPC を選択します。

サブネットは、VPC内に一つしか作成していないので、VPCを選択した時点で、自動で選択されているかと思います。

自動割り当てパブリックIP は有効にして下さい。こちらの設定を有効にすることで、AWS の領域から外のインターネットへアクセスすることができます。

設定が完了したら、右下の次のステップをクリックします。

ストレージの追加に関しては、今回特に設定する必要がないので、そのまま右下の次のステップをクリックします。

タグの追加では、EC2 に名前をつけられるので、分かりやすいように設定していきます。

左下のタグの追加をクリックします。

キーに Name、値に hello-world-docker-ec2 と入力しておきます。

入力したら、次のステップをクリックします。

そのまま次のセキュリティグループの設定をしていきます。

4. セキュリティグループ(ファイアウォール)を設定する

  • イメージ図

ここではセキュリティグループの設定を行っていきます。

セキュリティグループとは、いわゆるファイアウォールのことで、AWSでの名称です。こちらでインターネット(AWSの外側)からの通信を許可するようポートの設定(SSH の 22 番と、HTTP の 80 番)をしていきます。

まず、セキュリティグループの割り当ては、新しいセキュリティグループを作成するにチェックを入れます。そして、セキュリティグループ名には分かりやすい名前を付けます。

今回は、hello-world-docker-ec2-security-group としておきます。

説明にはセキュリティグループの説明を入力できます。(英字のみ)

デフォルトで設定されている SSH は、この後、ホストから EC2 へ SSH 接続をし、EC2 に Docker を install する為にそのまま残しておきます。

次に http 接続する為の設定をする為、ルールの追加をクリックします。

タイプは、カスタムTCP、プロトコルはそのままTCP、ポート範囲は 80 、ソースはカスタムの 0.0.0.0/0 を指定します。

0.0.0.0/0 と指定することで、全ての IP アドレスからのインスタンスにアクセスすることが許可されます。

注意

今回はあくまでも実験用として http で port を設定していますが、実運用として使う場合は、https 化して下さい。

設定が完了したら、右下の確認と作成ボタンをクリックします。

クリックすると、セキュリティグループ hello-world-docker-ec2-security-group は世界に向けて開かれています。というメッセージと先ほどまで設定してきた内容が表示されているかと思います。

内容を確認したら、右下の起動ボタンをクリックします。

クリックすると、キーペア選択、作成のモーダルが表示されます。

今回は新しいキーペアを作成していきましょう。

新しいキーペアの作成を選択し、RSAタイプにチェックを入れます。

キーペア名は分かりやすいように名前をつけます。

今回は hello-world-docker としました。

入力が済んだら、キーペアのダウンロードをクリックします。

こちらは、EC2 に SSH 接続に必要な秘密鍵になりますので、必ずダウンロードをしてください。また、この秘密鍵は、一度しかダウンロードできない為、大切に保管して下さい。mac の場合、デフォルトだと、~/Downloads にダウンロードされるかと思います。ダウンロードが完了したら、.ssh フォルダを作成し、そちらに移動させておきましょう。

ターミナルを開いて、下記のコマンドを実行します。

~ $ mkdir .ssh
~ $ mv ~/Downloads/hello-world-docker.pem ~/.ssh

そして、秘密鍵のパーミッションを下記のコマンドで変更します。

$ chmod 600 ~/.ssh/hello-world-docker.pem

上記が完了したら、ブラウザに戻ってインスタンスの作成をクリックします。

上記の画面が表示され、インスタンスの作成が進行します。

一覧画面に戻り、ステータスチェックの欄を見ると、初期化していますと表示されていると思います。しばらく経ってから、上部の更新ボタンを押し、チェックに合格しましたと表示が変われば、作成完了です。

↓ しばらくして、更新ボタンを押すと、

これで EC2 の作成と、セキュリティグループの設定が完了です。

5. ルーティングを設定する

さて、作業も終盤に入ってきました。次にルーティングの設定をしていきます。

  • イメージ図

先ほど、立てた EC2 に対して、通信先の定義をしていきます。繰り返しになりますが、今回はブラウザからEC2にアクセスして Hello world! と表示させること(レスポンスを返すこと)が目標なので、(EC2側から)インターネットへ通信が向かうように設定をしていきます。

まずは、VPCのダッシュボードに戻りましょう。

ナビバーのサービスをクリックすると、今まで作業を行ったダッシュボードの履歴が表示されますので、VPC をクリックしてダッシュボードへ戻ります。

サイドバーのルートテーブルをクリックします。

一覧画面へ遷移しますので、右上の作成ボタンをクリックします。

フォームに遷移しますので、

テーブルの名前を入力します。

今回も分かりやすいように hello-world-docker-route とします。

VPC には、作成するルートテーブルを適用したい VPC を選択します。

今回は、hello-world-docker です。

入力が完了したら、作成ボタンをクリックします。

作成が完了したら、一覧画面へ戻ります。

作成したルートテーブルにチェックを入れると、詳細が表示されます。

ルートタブを押すとルートを編集というボタンが表示されますので、そちらをクリックします。

フォーム画面に遷移しますので、ルートを追加をクリックします。

送信先は、全ての ip アドレスに対して、通信を返したいので、0.0.0.0/0 と設定します。

ターゲットでは、2. で作成した IGW を選択します。

入力が完了したら、変更を保存します。

変更が保存されたら、下記の画面が表示されますので、そのままサブネットの関連付けをしていきます。サブネットの関連付けタブをクリックし、サブネットの関連付けを編集をクリックします。

ここでは、作成したルートテーブルと関連付けたVPC内のどのサブネットと関連付けるかを設定します。

今回はVPC内に一つしかサブネットを作成していませんので、表示されているhello-world-docker-subnet にチェックを入れ、関連付けを保存します。

これで一通りのルーティングの設定が完了しました。

6. SSH で EC2 に アクセスする

先ほどまでのステップで、AWS のコンソールで行う作業は全て完了しました。

それでは、お手元のPCから構築した EC2 に SSH 接続したいと思います。

と、その前に先ほど構築した EC2 の IP アドレスを確認したいので、もう一度、EC2 のダッシュボードにアクセスします。

一覧画面で hello-world-docker-ec2 にチェックを入れると、詳細が表示されます。

赤枠のパブリック IPv4 アドレスを控えておきます。

次にターミナルを開きます。

先ほどダウンロードした秘密鍵を使って、EC2 に SSH 接続します。

$ ssh -i ~/.ssh/hello-world-docker.pem ec2-user@13.113.91.85

-i [秘密鍵のpath] でその秘密鍵を使って SSH 接続をします。

今回、EC2を作成するにあたってAmazon Linux 2 AMI (HVM)を使いました。Amazon Linux の場合、SSH で接続するデフォルトのユーザーは ec2-user なので、そちらを指定しています。そして、@に続いて、先ほど控えておいた IP アドレスを指定します。

初めて接続する際、そのまま接続を続けるか聞かれますので、その際はyes を入力して下さい。

コマンドを実行して下記のように表示されれば、接続成功です。

7. EC2 に Docker を install する

  • イメージ図

前のステップで、EC2 に SSH 接続されたままの状態になっているかと思いますので、そのまま EC2 に Docker を install していきたいと思います。

まずは、yum の update を行います。

yum とは、Linuxのパッケージ管理ツールのことです。

EC2インスタンスに install されているパッケージを update する為、下記のコマンドを実行します。

[ec2-user@ip-192-168-1-4 ~]$ sudo yum -y update

次に、Docker を install します。

下記のコマンドを実行します。

[ec2-user@ip-192-168-1-4 ~]$ sudo yum -y install docker

install が完了したら、Docker を起動します。

下記のコマンドを実行します。

[ec2-user@ip-192-168-1-4 ~]$ sudo service docker start

sudo docker info と実行し、下記のような内容が表示されれば、起動に成功しています。

[ec2-user@ip-192-168-1-4 ~]$ sudo docker info
Client:
 Context:    default
 Debug Mode: false

Server:
 Containers: 0
  Running: 0
  Paused: 0
  Stopped: 0
 Images: 0
 Server Version: 20.10.7
 Storage Driver: overlay2
  Backing Filesystem: xfs
  Supports d_type: true
  Native Overlay Diff: true
  userxattr: false
 Logging Driver: json-file
 Cgroup Driver: cgroupfs
 Cgroup Version: 1
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
 Swarm: inactive
 Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: d71fcd7d8303cbf684402823e425e9dd2e99285d
 runc version: 84113eef6fc27af1b01b3181f31bbaf708715301
 init version: de40ad0
 Security Options:
  seccomp
   Profile: default
 Kernel Version: 5.10.96-90.460.amzn2.x86_64
 Operating System: Amazon Linux 2
 OSType: linux
 Architecture: x86_64
 CPUs: 1
 Total Memory: 965.5MiB
 Name: ip-192-168-1-4.ap-northeast-1.compute.internal
 ID: T3TS:4QOT:KB35:2USQ:JDUZ:WFIZ:DRXS:43VU:3XPG:I2DZ:K4UU:6GB4
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Registry: https://index.docker.io/v1/
 Labels:
 Experimental: false
 Insecure Registries:
  127.0.0.0/8
 Live Restore Enabled: false

今のままだと、docker コマンドを打つ際に、sudo を付けなければなりません。
これは、ec2-user にdocker コマンドの操作権限がない為です。
ec2-user に操作権限を与える為、以下のコマンドを実行します。

sudo usermod -a -G docker ec2-user

上記のコマンドは、操作権限をもつ docker グループに ec2-user を加えるコマンドです。詳しく知りたい方は、公式ドキュメント や、こちらの記事を参照して下さい。

グループの追加は、シェルを起動し直さないと反映されないので、一度 exit でサーバーからログアウトし、ログインし直して下さい。

sudo なしで、docker info と実行し、先ほどと同じ内容の出力がされれば、グループへの追加が成功しています。

グループへの追加ができたら、作業用のディレクトリを作成し、ディレクトリ内に移動します。

[ec2-user@ip-192-168-1-53]$ mkdir hello-world-docker
[ec2-user@ip-192-168-1-53]$ cd hello-world-docker/

そして、Hello world! と表示させる為の html ファイルを用意します。

[ec2-user@ip-192-168-1-53 hello-world-docker]$ vi hello-world.html

vi が開きますので、i で insert mode にし、

Hello world! と記述して、esc キー、 :wq で保存します。

ls コマンドでディレクトリに今作成した html ファイルが作成されていると思います。

[ec2-user@ip-192-168-1-53 hello-world-docker]$ ls
hello-world.html

次にDockerimage を作成する為に、Dockerfile を作成、編集していきます。

今回は、webサーバーに nginx を使用します。先ほど作成した、html ファイルを nginx 上で表示させます。

[ec2-user@ip-192-168-1-53 hello-world-docker]$ vi Dockerfile

Dockerfile

FROM nginx
COPY ./hello-world.html /usr/share/nginx/html/

nginx では、デフォルトの状態だと/usr/share/nginx/html/ 配下がブラウザからアクセスした際の初期表示になっているので、./hello-world.html をコピーします。

編集出来たら、先ほどと同じように保存して下さい。

そして、作成したDockerfile を元に image を build します。

下記のコマンドを実行します。

[ec2-user@ip-192-168-1-53 hello-world-docker]$ docker build -t hello-world-docker-ec2 .

build が完了したら、container を起動します。

下記のコマンドを実行して下さい。

[ec2-user@ip-192-168-1-53 hello-world-docker]$ docker run --rm -d -p 80:80 hello-world-docker-ec2
  • 今回はあくまで実験として作業をしているので、--rm オプションをつけてコンテナ終了時に削除していますが、本番を想定する場合は、オプションを付与しなくても良いかも知れません。

docker ps コマンドでコンテナの STATUS が UP になっていれば、起動に成功しています。

[ec2-user@ip-192-168-1-53 hello-world-docker]$ docker ps
CONTAINER ID   IMAGE                    COMMAND                  CREATED          STATUS          PORTS                               NAMES
0742571c5bf3   hello-world-docker-ec2   "/docker-entrypoint.…"   14 seconds ago   Up 12 seconds   0.0.0.0:80->80/tcp, :::80->80/tcp   romantic_greider

ここまでで、全ての作業が完了です。

それではブラウザからアクセスしてみましょう。

控えておいた IP アドレス / hello-world.html でアクセスします。


無事に Hello world! と表示させることができました!

さて、如何だったでしょうか?
今回は、AWS に EC2 を立て、その中で Docker コンテナを起動させ、ブラウザからアクセスすることをハンズオン形式でやってみました。私自身もインフラに関して、まだまだ勉強中で今回の内容は、かなり初歩的な内容だったかと思います。次の機会には、もう少し発展した内容を書いてみたいと思います。
最後まで読んで頂き、ありがとうございました!