はじめてのAWSのEC2上でのDockerのインストールと設定
AWSのEC2にDockerをインストールして動かしてみたいと思ったことはありませんか?
本文書では、以下の手順で環境構築と動作確認を行います:
- Amazon Linux 2023がインストールされたEC2インスタンスにDockerをインストール
- Dockerを使用してWebサーバー(Apache)のコンテナを作成し、パブリックネットワークからのアクセスを確認
- Docker Composeをインストールし、PythonのWebフレームワークであるFastAPIの環境をDocker上に構築
この手順に従うことで、DockerとDocker Composeを使用した基本的なWeb環境の構築方法を学ぶことができます。
目次
EC2インスタンスの作成
DockerをインストールするEC2インスタンスの作成を行います。 EC2のインスタンスの作成については下記の文書で公開済みなのでEC2インスタンスを作成した経験がない人は参考にしてください。
作成したEC2インスタンスにはEC2 instance Connectを利用して接続します。
Dockerの設定
Dockerのインストール
Dockerのインストールを行うためdnfコマンドを利用します。dnf -y updateコマンドでパッケージのアップデートを行っておきます。管理者権限が必要なのでコマンドの前にsudoをつけて実行しています。
$ sudo dnf -y update
Last metadata expiration check: 0:06:31 ago on Tue Feb 20 12:59:17 2024.
Dependencies resolved.
Nothing to do.
Complete!
dnf installコマンドを利用してdockerのインストールを行います。
$ sudo dnf install docker
インストールが完了するとdockerコマンドを利用することができるのでDockerのバージョンを確認しておきます。
[ec2-user@ip-172-31-3-114 ~]$ docker -v
Docker version 24.0.5, build ced0996
[ec2-user@ip-172-31-3-114 ~]$ which docker
/usr/bin/docker
Dockerの起動設定
コンテナの一覧を表示するためのdocker psコマンドを実行してもサービスが起動していないのでエラーとなります。
[ec2-user@ip-172-31-3-114 ~]$ docker ps
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
dockerのサービスが起動しているかどうかはsystemctl statusコマンドで確認することができます。
[ec2-user@ip-172-31-3-114 ~]$ sudo systemctl status docker.service
○ docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled; preset: disabled)
Active: inactive (dead)
TriggeredBy: ○ docker.socket
Docs: https://docs.docker.com
inactiveなのでsystemctl startコマンドでサービスを起動します。
[ec2-user@ip-172-31-3-114 ~]$ sudo systemctl start docker.service
再度ステータスを確認するとactiveになっていることが確認できます。
[ec2-user@ip-172-31-3-114 ~]$ sudo systemctl status docker.service
● docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled; preset: disabled)
Active: active (running) since Tue 2024-02-20 13:21:52 UTC; 2s ago
TriggeredBy: ● docker.socket
Docs: https://docs.docker.com
Process: 27392 ExecStartPre=/bin/mkdir -p /run/docker (code=exited, status=0/SUCCESS)
Process: 27393 ExecStartPre=/usr/libexec/docker/docker-setup-runtimes.sh (code=exited, status=0/SUCCESS)
Main PID: 27395 (dockerd)
Tasks: 8
Memory: 35.3M
CPU: 309ms
CGroup: /system.slice/docker.service
└─27395 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --default-ulimit nofile=32768:65536
Feb 20 13:21:52 ip-172-31-3-114.ap-northeast-1.compute.internal systemd[1]: Starting docker.service - Docker Application Container Engine...
//略
Feb 20 13:21:52 ip-172-31-3-114.ap-northeast-1.compute.internal systemd[1]: Started docker.service - Docker Application Container Engine.
EC2を停止、起動(再起動)してもDockerサービスが起動するように自動起動設定を行います。設定する前はsystemctl is-enabledコマンドで確認することができます。
[ec2-user@ip-172-31-3-114 ~]$ sudo systemctl is-enabled docker.service
disabled
systemctl enableコマンドで自動起動を有効にしてis-enabledコマンドを実行するとdisabledからenabledに変わっていることが確認できます。
[ec2-user@ip-172-31-3-114 ~]$ sudo systemctl enable docker.service
Created symlink /etc/systemd/system/multi-user.target.wants/docker.service → /usr/lib/systemd/system/docker.service.
[ec2-user@ip-172-31-3-114 ~]$ sudo systemctl is-enabled docker.service
enabled
dockerサービスが起動したのでdocker psコマンドを実行すると先ほどのエラーとは異なりPermission deniedでコマンドが実行できないことがわかります。
[ec2-user@ip-172-31-3-114 ~]$ docker ps
permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/json": dial unix /var/run/docker.sock: connect: permission denied
dockerグループにec2-userを追加する必要があります。/etc/groupを確認するとdockerが追加されていることが確認できます。
[ec2-user@ip-172-31-3-114 ~]$ more /etc/docker
//略
ec2-user:x:1000:
docker:x:992:ec2-user
dockerグループへの追加はusermodコマンドで行います。
[ec2-user@ip-172-31-3-114 ~]$ sudo usermod -aG docker ec2-user
再度docker psコマンドを実行しても同じPermission Deniedのエラーが表示されます。一度インスタンスからログインして再ログインすると設定が反映されエラーは解消されます。docker psコマンドの実行結果は、コンテナは存在しないので下記の表示となります。
[ec2-user@ip-172-31-3-114 ~]$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Apacheを利用した動作確認
設定したDockerが動作するのか確認するためにApacheのDockerイメージであるhttpdを利用してコンテナの起動を行います。ポートはEC2インスタンスを作成する際にセキュリティグループでhttpのポート80の接続を許可しているので80を指定しています。Dockerコンテナの名前はapache-testとしています。
$ docker run --name apache-test -d -p 80:80 httpd
Unable to find image 'httpd:latest' locally
latest: Pulling from library/httpd
e1caac4eb9d2: Pull complete
87b0fe460fd9: Pull complete
4f4fb700ef54: Pull complete
9cebd3e3b523: Pull complete
e9304da947c5: Pull complete
b60d4b66b268: Pull complete
Digest: sha256:104f07de17ee186c8f37b9f561e04fbfe4cf080d78c6e5f3802fd08fd118c3da
Status: Downloaded newer image for httpd:latest
f3101ca8efdea05c893cecfcf497778a5f2a27f823c93a174002b2bf0d6f7bcd
docker psコマンドを実行するとapache-testという名前のコンテナが起動していることが確認できます。
[ec2-user@ip-172-31-3-114 ~]$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
680d1e7206ee httpd "httpd-foreground" 5 seconds ago Up 4 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp apache-test
ネット上から接続するためにはパブリック IPv4 DNSを利用します。パブリック IPv4 DNSはManagement Consoleのインスタンス概要画面で確認することができます。
ブラウザから”http://パブリック IPv4 DNS”をURLに設定して接続を行います。
ブラウザ上に”It works”が表示されれば設定した内容通りDocker上に起動しているApacheサーバからレスポンスが行われており、Dockerが正常に動作していることがわかります。
Docker Composeとは
Docker Composeは、複数のDockerコンテナを定義し実行するためのツールです。先ほどApacheで確認した通りdockerコマンドでは1つのコンテナを起動することができました。Docker Compserを利用するとdockerコマンドとは異なり、複数のコンテナを効率的に構成・管理できるため、特に複雑なアプリケーション環境では非常に便利です。
Docker Composeのインストール
Docker ComposeはDockerとは別にインストールを行う必要があります。インストールではGithub上にあるファイルをcurlコマンドを利用してローカルにコピーを行います。インストール方法についてはドキュメントを参考に行います。
バージョンをv2.24.6を指定していますがこれは現時点の最新版を指定しているので実行する際はGitHubのreleasesページで最新版を確認してください。
[ec2-user@ip-172-31-3-114 ~]$ sudo curl -SL https://github.com/docker/compose/releases/download/v2.24.6/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
100 58.5M 100 58.5M 0 0 46.7M 0 0:00:01 0:00:01 --:--:-- 118M
上記のコマンドではhttps://github.com/docker/compose/releases/download/v2.24.6/docker-compose-linux-x86_64にあるファイルを/usr/local/bin/docker-composeにコピーしているためsudoで実行しない場合に”Warning: Failed to open the file /usr/local/bin/docker-compose: Permission”のエラーとなります。
ファイルをコピーしただけでは権限が不足しているので実行権限を追加します。
[ec2-user@ip-172-31-3-114 ~]$ ls -l /usr/local/bin/docker-compose
-rw-r--r--. 1 root root 61431093 Feb 21 00:34 /usr/local/bin/docker-compose
[ec2-user@ip-172-31-3-114 ~]$ sudo chmod +x /usr/local/bin/docker-compose
[ec2-user@ip-172-31-3-114 ~]$ ls -l /usr/local/bin/docker-compose
-rwxr-xr-x. 1 root root 61431093 Feb 21 00:34 /usr/local/bin/docker-compose
実行権限を付与後はバージョンを確認するためにdocker-compose -vコマンドを実行します。実行時に指定したバージョンであることが確認できます。
[ec2-user@ip-172-31-3-114 ~]$ docker-compose -v
Docker Compose version v2.24.6
FastAPIの環境構築
Docker-composeのインストールが完了したのでPythonベースのWebフレームワークであるFastAPIの環境の構築をDocker-composeを利用して行います。
ec2-userのホームディレクトリにDockerfile, docker-compose.ymlファイルを作成します。それぞれには下記のコードを記述します。
FROM python
WORKDIR /usr/src/app
COPY /app/requirements.txt ./
RUN pip install --upgrade pip
RUN pip install -r requirements.txt
version: "3"
services:
app:
container_name: fastapi-dev
build: .
ports:
- "80:8000"
volumes:
- ./app:/usr/src/app
command: uvicorn main:app --reload --host 0.0.0.0
2つのファイルが作成できたらappディレクトリを作成してrequiments.txtを作成してインストールするPythonパッケージを記述します。
fastapi
uvicorn[standard]
FastAPIを動かすためのコードmain.pyファイルをappディレクトリの中に作成します。
[ec2-user@ip-172-31-3-114 app]$ more main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
main.pyファイルの中のコードを以下のような意味を持っています。
- “from fastapi import FastAPI”でFASTAPIライブラリからFastAPIをimportしてAPIアプリケーション(FastAPIのインスタンス)を作成しています。
- @app.get(“/”)でルートのエンドポイントを設定しています。GETリクエストがルートURLにアクセスした時の処理をしてしています。
- def read_root()はルートURLにリクエストが来た場合に実行する関数です。
- JSONコードで{“Hello”: “World”}を戻しています。
作成したファイルをec2-userのホームディレクトリで実行します。コマンドは”docker-compose up -d”で”docker-compose up -d”を実行すると実行したディレクトリに存在するdocker-compose.ymlファイルが読み込まれ、その内容に基づいて処理が行われます。docker-compose.ymlファイルのbuildキーワードが指定されているので同じディレクトリにあるDockerfileを見つけてイメージをビルドします。
[ec2-user@ip-172-31-3-114 ~]$ docker-compose up -d
[+] Building 39.1s (10/10) FINISHED docker:default
=> [app internal] load build definition from Dockerfile
//略
[+] Running 1/2
⠙ Network ec2-user_default Created 1.0s
✔ Container fastapi-dev Started
docker psコマンドを実行してfastapi-devという名前のコンテナが起動していることを確認します。
[ec2-user@ip-172-31-3-114 app]$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ec45f2197266 ec2-user-app "uvicorn main:app --…" 3 minutes ago Up 3 minutes 0.0.0.0:80->8000/tcp, :::80->8000/tcp fastapi-dev
apacheのコンテナを起動した時と同様にネット上から接続するためにはパブリック IPv4 DNSを利用します。パブリック IPv4 DNSはManagement Consoleのインスタンス概要画面で確認することができます。
ブラウザから”http://パブリック IPv4 DNS”をURLに設定して接続を行います。main.pyファイルで設定したJSONの{“Hello”:”World”}がブラウザ上に表示されれば Docker上で設定したFastAPIアプリは正常に動作しています。
EC2の再起動後にコンテナも起動させたい場合やdocker-compose.ymlファイルにrestart:alwaysを追加します。
version: "3"
services:
app:
container_name: fastapi-dev
build: .
restart: always
ports:
- "80:8000"
volumes:
- ./app:/usr/src/app
command: uvicorn main:app --reload --host 0.0.0.0
自動起動が設定されているかどうかはdocker inspectコマンドのRestartPolicyのNameの値が”always”になっているかどうかで確認できます。設定されていない場合はNameの値は何も設定されていません。
EC2へのDocker, Docker Composeのインストールの方法とインストールしたDockerを利用してApache, FastAPIが動作することを確認することができました。