はじめに
昨年CloudShellでDockerコマンドが利用できるようになりました(2023年12月27日 アップデート)。
だから何ができるのか分からなかったので、とりあえず自分の中で思いつた『こういった構成できるんじゃないか?』を試してみました。
構築イメージ
やってみた目次
No | 内容 |
---|---|
1 | コンテナ構築 / 起動 |
2 | ECRへイメージをプッシュ |
3 | ECSでコンテナ起動 |
1.コンテナ構築 / 起動
1.1.CloudShellでFlaskアプリ作成
CloudShell
にて静的ページを返すアプリを構築
# 最終的なフォルダ構成
.
├── Dockerfile
├── app.py
├── requirements.txt
└── templates
└── index.html
1.2.Flaskインストール
requirements.txt
にFlask
を記載
vi requirements.txt
cat requirements.txt
Flask
# Flaskインストール
pip install -r requirements.txt
1.3.『app.py』作成
vi app.py
cat app.py
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=8080)
1.4.『templates/index.html』作成
vi index.html
cat index.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Flask</title>
</head>
<body>
<p>Hello World!!</p>
</body>
</html>
1.5.『DockerFile』作成
vi Dockerfile
cat Dockerfile
# Python 3.11の公式イメージをベースとする
FROM python:3.11
# 作業ディレクトリを/appに設定
WORKDIR /app
# 現在のディレクトリの内容をコンテナの/appに追加
ADD . /app
# pipをアップグレードし、requirements.txtにリストされた依存関係をインストール
RUN pip install --upgrade pip && \
pip install -r requirements.txt
# コンテナの8080ポートを公開
EXPOSE 8080
# コンテナ起動時にapp.pyを実行
CMD ["python", "app.py"]
1.6.コンテナ起動
# Dockerイメージのビルド
docker build -t flask-app .
# Dockerコンテナの実行
docker run -d -p 8080:8080 --name flask-app flask-app:latest
1.7.コンテナ起動確認
# Curlコマンドによる確認
curl http://localhost:8080
<!DOCTYPE html>
<html lang="en">
<head>
<title>Flask</title>
</head>
<body>
<p>Hello World!!</p>
</body>
</html>
# Docker コンテナ状況確認
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
203c24eebd5c flask-app:latest "python app.py" 6 minutes ago Up 5 minutes 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp flask-app
# Docker images確認
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
flask-app latest 533d5b063fc0 7 minutes ago 1.03GB
コンテナを停止する際のコマンド
コンテナを停止する際は下記コマンドを利用
# コンテナ停止する場合
docker stop ${CONTAINER ID ※上記の場合、203c24eebd5c}
# コンテナの削除
docker rm ${CONTAINER ID ※上記の場合、203c24eebd5c}
#イメージの削除
docker rmi ${IMAGE ID ※上記の場合、533d5b063fc0}
2.ECRへイメージをプッシュ
リージョンは東京リージョン(ap-northeast-1)を使用
各自のAWSアカウントIDを利用
2.1.ECRリポジトリ作成
# 環境変数
export AWS_ACCOUNTID=123456789012
export AWS_REGION=ap-northeast-1
export AWS_REPOSITORY_NAME=my-flask-app
# リポジトリ作成
aws ecr create-repository --repository-name ${AWS_REPOSITORY_NAME} --region ${AWS_REGION}
2.2.ECRへイメージをプッシュ
# ECRにDockerクライアントをログイン
aws ecr get-login-password --region ${AWS_REGION} | docker login --username AWS --password-stdin ${AWS_ACCOUNTID}.dkr.ecr.ap-northeast-1.amazonaws.com
# Docker イメージ名確認
# REPOSITORY == イメージ名
# TAG == タグ
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
flask-app latest 533d5b063fc0 7 minutes ago 1.03GB
# リポジトリにイメージをプッシュできるようタグを付与
docker tag ${イメージ名}:${タグ} ${ACCOUNTID}.dkr.ecr.ap-northeast-1.amazonaws.com/${AWS_REPOSITORY_NAME}:latest
# タグがついたか確認
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
${ACCOUNTID}.dkr.ecr.ap-northeast-1.amazonaws.com/my-flask-app latest 533d5b063fc0 8 minutes ago 1.03GB
flask-app latest 533d5b063fc0 7 minutes ago 1.03GB
# ECRにプッシュ
docker push ${ACCOUNTID}.dkr.ecr.ap-northeast-1.amazonaws.com/${AWS_REPOSITORY_NAME}:latest
# ECRのリポジトリ確認
aws ecr list-images --repository-name ${AWS_REPOSITORY_NAME} --region ${AWS_REGION}
3.ESCでコンテナ起動
3.1.タスク定義の作成
アカウントID
とリージョン
部分はそれぞれ修正する
vi task-definition.json
cat task-definition.json
{
"family": "my-flask-app-task",
"taskRoleArn": "arn:aws:iam::アカウントID:role/ecsTaskExecutionRole",
"executionRoleArn": "arn:aws:iam::アカウントID:role/ecsTaskExecutionRole",
"networkMode": "awsvpc",
"containerDefinitions": [
{
"name": "flask-app",
"image": "アカウントID.dkr.ecr.リージョン.amazonaws.com/my-flask-app:latest",
"cpu": 256,
"memory": 512,
"essential": true,
"portMappings": [
{
"containerPort": 8080,
"hostPort": 8080
}
]
}
],
"requiresCompatibilities": [
"FARGATE"
],
"cpu": "256",
"memory": "512"
}
# 上記設定したタスク定義を作成
# file://{task-definition.json}のパスを記載
aws ecs register-task-definition --cli-input-json file://path/to/task-definition.json
3.2.ECS SGの作成
# 環境変数
export VPC_ID=vpc-XXXXX
export ECS_SG_NAME=my-flask-app-SG
export MY_IP=YYY.YYY.YYY.YYY
#ECSのSG作成
export SG_ID=$(aws ec2 create-security-group \
--group-name ${ECS_SG_NAME} \
--description ${ECS_SG_NAME} \
--vpc-id ${VPC_ID} \
--query 'GroupId' \
--output text)
# ECSのSGに下記ルール追加
aws ec2 authorize-security-group-ingress \
--group-id $SG_ID \
--protocol tcp \
--port 8080 \
--cidr ${MY_IP}/32
3.2.ECS の作成
ECS Fargateで構築
# 環境変数
export SUBNET_PUB_A=subnet-XXXXX
export SUBNET_PUB_C=subnet-YYYYY
export CLUSTER_NAME=my-flask-app-cluster
export SERVICE_NAME=my-flask-app-service
export TASK_NAME=my-flask-app-task
# ECS クラスター作成
aws ecs create-cluster --cluster-name ${CLUSTER_NAME}
# ECS サービスの作成
aws ecs create-service --cluster ${CLUSTER_NAME} --service-name ${SERVICE_NAME} \
--task-definition ${TASK_NAME} --desired-count 1 \
--launch-type FARGATE --network-configuration "awsvpcConfiguration={subnets=[${SUBNET_PUB_A},${SUBNET_PUB_C}],securityGroups=[${SG_ID}],assignPublicIp=\"ENABLED\"}"
挙動の確認
ECS > クラスター > 「my-flask-app-cluster」 > サービス > タスク 押下
赤枠部分を押下するとhttp://13.115.249.61/
でブラウザが開くが、今回コンテナは8080ポート
でリッスンしているため、http://13.115.249.61:8080/
という形でURLを変更してアクセス
※既に、こちらのタスク削除済み
おわりに
思いついたことが検証できてなによりでした。
実際本番環境で CloudShellをつかう選択肢は限られてると思いますが(スペック的な面で)、簡単な構築であればサクッとECSを作れちゃうのは魅力かと思いました。