DRF+Nuxt+MySQLな環境を作るための備忘録
作業ログ的な感じなので説明省いてますので質問がある方はコメントください。
本記事のポイント
- ローカルでDRF(Django REST framework) + Nuxt + MySQLの環境構築
- Docker Compose for ECSでDRF(Django REST framework) + Nuxt + RDSの環境構築
- ECSのコンテナにSSHできるようにする。ECS Exec
- ALBを使ってHTTPSアクセスできるようにする。
Docker Compose for ECSは構築してしまえば、1コマンドでECSを起動できるのでオススメ
ただしSSH接続やALBを含めた構築はAWS周りの知識、特にCloudFormationが必要なので結構大変です。。。
Qiitaやネット上にほとんど情報がないので自分と他のエンジニアのために記録を残す。グッドラック
※ DRFやNuxtのインストールやセットアップは省く
ローカル対応
各種コンテナ用のDockerファイル作成
MySQL
./dockerfiles/mysql_docker/dockerfile
FROM mysql:latest
COPY ./mysql/my.cnf .
EXPOSE 3306
DRF(Django REST framework)
./dockerfiles/django_docker/dockerfile
FROM python:3.7
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
COPY ./django/ /code/
RUN pip install --upgrade pip
RUN pip install -r requirements.txt
Nuxt
./dockerfiles/nuxt_docker/dockerfile
FROM node:16-alpine
RUN mkdir -p /code
COPY ./nuxt/ /code/
WORKDIR /code
ENV NODE_ENV=development
RUN yarn install
RUN yarn add @nuxtjs/axios
RUN yarn build
EXPOSE 80
docker-compose-local.yml
# ローカル用
services:
db:
container_name: mysql
build:
context: .
dockerfile: ./dockerfiles/mysql_docker/dockerfile
environment:
MYSQL_DATABASE: xxx
MYSQL_USER: xxx
MYSQL_PASSWORD: xxx
MYSQL_ROOT_PASSWORD: xxx
TZ: 'Asia/Tokyo'
command: --default-authentication-plugin=mysql_native_password
ports:
- 3306:3306
volumes:
- mysqldata:/var/lib/mysql
- ./mysql/conf.d:/etc/mysql/conf.d
restart: always
web:
container_name: django
build:
context: .
dockerfile: ./dockerfiles/django_docker/dockerfile
command: bash -c "sh entry_point.sh && python manage.py runserver 0.0.0.0:8000"
volumes:
- ./django:/code
ports:
- "8000:8000"
depends_on:
- db
links:
- db
front:
container_name: nuxt
build:
context: .
dockerfile: ./dockerfiles/nuxt_docker/dockerfile
command:
yarn dev
volumes:
- ./nuxt:/code
ports:
- "80:80"
depends_on:
- db
tty: true
volumes:
mysqldata:
イメージ作成・コンテナ起動
$ docker-compose -f docker-compose-local.yml build --no-cache
$ docker-compose -f docker-compose-local.yml up -d
ECR対応
リポジトリ作成、デプロイ
プロファイル作成
※ IAMでグループ・ユーザー追加し予めAccess Key ・Secret Access Keyを取得
$ aws configure --profile xxx
AWS Access Key ID [None]: xxx
AWS Secret Access Key [None]: xxx
Default region name [None]: ap-northeast-1
Default output format [None]:
コンテキスト作成
$ docker context create ecs xxx
ECRリポジトリ作成
$ aws ecr create-repository --repository-name xxx_front --region ap-northeast-1 --profile xxx
$ aws ecr create-repository --repository-name xxx_web --region ap-northeast-1 --profile xxx
タグ
※ 予めローカルでdocker-compose up -build でイメージ作成
$ docker tag xxx_front:latest xxx.dkr.ecr.ap-northeast-1.amazonaws.com/xxx_front:latest
$ docker tag xxx_web:latest xxx.dkr.ecr.ap-northeast-1.amazonaws.com/xxx_web:latest
ログイン
$ aws ecr get-login-password --region ap-northeast-1 --profile xxx | docker login --username AWS --password-stdin xxx.dkr.ecr.ap-northeast-1.amazonaws.com
Login Succeeded
デプロイ
※ タグは作り直さないと反映されないので注意
$ docker push xxx.dkr.ecr.ap-northeast-1.amazonaws.com/xxx_web:latest
$ docker push xxx.dkr.ecr.ap-northeast-1.amazonaws.com/xxx_front:latest
ネットワーク作成
-
ECS、RDS用のVPC、サブネット、インターネットゲートウェイを作成
-
ECS、RDS、ロードバランサ用のセキュリティグループを作成
- インバウンドルールにHTTPS、HTTP、MySQLを追加しておく、VPC IDは上記で作成したものを追加
-
ロードバランサ作成
※ コンソール画面だと作成できないのでAWSコマンドで作成
上記で作成したサブネットとセキュリティグループを選択$ aws elbv2 create-load-balancer --name xxx-alb \ --scheme internet-facing --type application \ --security-groups sg-xxx \ --subnets subnet-xxx subnet-xxx \ --profile xxx
RDS作成
- 上記で作成したVPCとセキュリティグループを選択
- 最初はサーバーレスで最小構成で作成
ECS対応
ECS用のdocker-compose.ymlを作成
version: '3'
x-aws-vpc: "vpc-xxx"
x-aws-loadbalancer: "arn:aws:elasticloadbalancing:ap-northeast-1:xxx:loadbalancer/app/xxx-alb/xxx"
# ECS用
services:
web:
image: xxx.dkr.ecr.ap-northeast-1.amazonaws.com/xxx_web:latest
command: >
bash -c "python manage.py migrate --settings=config.settings.production &&
python manage.py runserver --settings=config.settings.production 0.0.0.0:8000"
ports:
- target: 8000
x-aws-protocol: http
x-aws-role:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- ssmmessages:CreateControlChannel
- ssmmessages:CreateDataChannel
- ssmmessages:OpenControlChannel
- ssmmessages:OpenDataChannel
Resource: '*'
front:
image: xxx.dkr.ecr.ap-northeast-1.amazonaws.com/xxx_front:latest
command: yarn start
ports:
- "80:80"
- "443:443"
x-aws-cloudformation:
Resources:
WebService:
Properties:
LoadBalancers:
- ContainerName: web
ContainerPort: 8000
TargetGroupArn:
Ref: Web8000TargetGroup
EnableExecuteCommand: true
Web8000Listener:
Properties:
Port: 8000
Protocol: HTTP
Web8000TargetGroup:
Properties:
HealthCheckPath: /admin
Matcher:
HttpCode: 200-499
FrontService:
Properties:
LoadBalancers:
- ContainerName: front
ContainerPort: 80
TargetGroupArn:
Ref: FrontTCP80TargetGroup
FrontTCP80Listener:
Properties:
DefaultActions:
- Type: redirect
RedirectConfig:
Port: 443
Protocol: HTTPS
StatusCode: HTTP_301
FrontTCP443Listener:
Properties:
Protocol: "HTTPS"
Certificates:
- arn:aws:acm:ap-northeast-1:xxx:certificate/xxx-xxx-xxx-xxx-xxx
DefaultActions:
- Type: "fixed-response"
FixedResponseConfig:
ContentType: "text/plain"
MessageBody: "BAD DOMAIN NAME"
StatusCode: "200"
FrontTCP443WWWRule:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
ListenerArn:
Ref: FrontTCP443Listener
Priority: 50000
Conditions:
- Field: host-header
HostHeaderConfig:
Values:
- xxx.toyscreation.jp
Actions:
- Type: redirect
RedirectConfig:
Host: xxx.toyscreation.jp
Port: 443
Protocol: HTTPS
StatusCode: HTTP_301
FrontTCP443BaseRule:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
ListenerArn:
Ref: FrontTCP443Listener
Priority: 40000
Conditions:
- Field: host-header
HostHeaderConfig:
Values:
- xxx.toyscreation.jp
Actions:
- Type: forward
ForwardConfig:
TargetGroups:
- TargetGroupArn:
Ref: FrontTCP80TargetGroup
コンテキスト切替
$ docker context use xxx
起動
$ docker compose up
削除
$ docker compose down
SSH接続
タスク確認
$ aws ecs list-tasks --cluster xxx --profile xxx
コマンド実行
$ aws ecs execute-command \
--cluster xxx \
--task arn:aws:ecs:ap-northeast-1:xxx:task/xxx/xxx \
--container web \
--interactive \
--command "/bin/sh" \
--profile xxx
※ DRFユーザー作成だけECS ExecでSSHして作成
$ python manage.py createsuperuser --email xxx@toyscreation.jp --username xxx --settings=config.settings.production