🌐

Docker composeとAWS(ECR/ECS)デプロイ

2020/12/15に公開

React・DockerとAWS

みなさんDockerは使っているだろうか。
私は恥ずかしながら業務では使用していない。

だが、今回(2020/09)非常に興味深いdocker composeとECS統合という物が実装された。

Docker Compose for Amazon ECS Now Available

平たくいうと、dockerとAWSの連携コマンドなのだが
docker composedocker-composeコマンドのdocker cli版である。
今後はdoker cliを使用してね。という事だそうだ。

この魔法のようなコマンドはdockerのコマンドを使うことで自動でAWSにデプロイしてしまう。
という凄まじい物だった。

私としても備忘録にするため、筆を取った次第だ。

前提条件

実際にDockerを使用している皆様にはもう十分だろう。
随時参考リンクがあるので見てくれると嬉しい。
( ※もし、詳しく聞きたいというコメントしてくれれば対応するかもしれないね:) )

AWSアカウントの作成

AWSアカウントについては今更述べる必要は薄いとは思う。
やりたい事はIAM Userの作成なのだが、以下に私が昔参考にしたブログを載せておく

※上記の情報は古いが、ここで重要なのはどんなワードを元に検索するか?だ。

Dockerインストール

Dockerには様々なチュートリアルが存在している。
後で詳しく説明するがlinuxベースの仮想環境である。
と言えば少しは荷が軽くなったような気がする。

以下のサイトが参考になるかと思う。
Docker入門:Docker概要,基本操作,マウント,Dockerfile,マルチステージビルド

Dockerfile、docker-compose.ymlの作成

ここは重要なフェーズの一つだ。
docker composeコマンドの名が示す通り
docker-composeコマンドの亜種だ(同じコマンドではないので注意だ。)
なので複数コンテナが使う事を想定されている。

ここでcomposeをいまいち分かってない人は以下のブログを参考にすると良いだろう。
Docker Composeとは

さて、今回はapi用のDockerと、front用のDockerを用意する

Dockerfile.api

# ベースイメージの作成 
FROM node:14.15.1-buster
# コンテナ内で作業するディレクトリを指定
WORKDIR /usr/src/app
# package.jsonとyarn.lockを/usr/src/appにコピー
COPY ["./api/package.json", "./api/yarn.lock", "./"]
RUN yarn install
# ファイルを全部作業用ディレクトリにコピー
COPY ./api .
# ポートのエクスポート
EXPOSE 9999

CMD yarn start

Dockerfile.front

# ベースイメージの作成 
FROM node:14.15.1-buster
# コンテナ内で作業するディレクトリを指定
WORKDIR /usr/src/app
# package.jsonとyarn.lockを/usr/src/appにコピー
COPY ["./front/package.json", "./front/yarn.lock", "./"]
RUN yarn install
# ファイルを全部作業用ディレクトリにコピー
COPY ./front .
# ポートのエクスポート
EXPOSE 3000

CMD yarn start

以下の2つのDockerを纏めるdocker-compose.ymlを用意する。

  • Dockerfile.api
  • Dockerfile.front

docker-compose.yml

version: "3"

services:
  frontend:
    image: soreiyu/front
    build:
      context: .
      dockerfile: Dockerfile.front
    command: "yarn start"
    ports:
      - "3000:3000"
    volumes:
      - ./front:/usr/src/app
    tty: true

  api:
    image: soreiyu/api
    build:
      context: .
      dockerfile: Dockerfile.api
    command: "yarn start"
    ports:
      - "9999:9999"
    volumes:
      - ./api:/usr/src/app

上記は以下を参考にしているため、以下のサイトを参考に、まずは普通にコンテナ起動をしてみよう。
※あとでdocker contextというものを変更するが、ローカル環境はdefaltでないと動かないので気を付けよう

DockerのNodeをどれにするか?

Dockerのその他

コンテナの起動とReactの実行

ここまで出来ていれば以下のコマンドで一発だ。

docker-compose up

付録 Dockerでbabelのwatch機能が利かない

私がDockerでreactの開発をしているときに
自動でトランスパイルされない自体に陥った。

以下.envファイルを作成する事により
watch機能を有効にしたことで解決した。

.env

CHOKIDAR_USEPOLLING=true

babelのwatch機能がdockerコンテナ上で動かない

docker Compose でデプロイ

さて、以下のようなファイル構成になったと思う。

dockerProject
  ├─api                     ← api用プロジェクト
  ├─front                   ← front用プロジェクト(react)
  │  └─.env                 ← react用のenvファイル
  ├─Dockerfile.api          ← api用のDockerfile
  ├─Dockerfile.front        ← front用のDockerfile
  └─docker-compose.yml      ← compose用のymlファイル

いよいよAWSにデプロイする。
今回使用するAWSサービスは以下の二つだ

大まかな流れとしてはECRにpushしたものをECSで公開するという流れだ
(※別段ECRで管理する必要はないが、AWSの認証の関係でECR,ECSの連携の方が楽なため、この方式にしている)

以下のコマンドを使用し、まずはコマンドラインのawsのログインをしよう。

aws ecr get-login-password | docker login --username AWS --password-stdin https://<aws_account_id>.dkr.ecr.<region>.amazonaws.com

参考資料
AWS CLIでECRにログインする時はget-loginではなくget-login-passwordを使おう

docker-compose コマンドでECRにpush

さて、次にECRに今回作成したdocker imageをpushしたい。
その為にまずはAWSでレポジトリを作成しよう

ここでプライベートレポジトリにしないと、コマンドで使用できないため、プライベートにしよう。

次にymlファイルのpush先を変更しなければならない。
これは、AWSのプッシュコマンドを表示というところをクリックすれば細かい詳細がみれるので
そこから使用すればよいだろう。

docker-compose.yml

version: "3"

services:
  frontend:
    # image: soreiyu/front
    image: 000000000000.dkr.ecr.ap-northeast-1.amazonaws.com/soreiyu/front
    build:
      context: .
      dockerfile: Dockerfile.front
    command: "yarn start"
    ports:
      - "3000:3000"
    volumes:
      - ./front:/usr/src/app
    tty: true

  api:
    # image: soreiyu/api
    image: 000000000000.dkr.ecr.ap-northeast-1.amazonaws.com/soreiyu/api
    build:
      context: .
      dockerfile: Dockerfile.api
    command: "yarn start"
    ports:
      - "9999:9999"
    volumes:
      - ./api:/usr/src/app

dockerをbulidしtag名を付けて以下のコマンドで実際にpush出来るかためそう。
tag名に関しては、細かい詳細で確認しよう

docker-compose push

※私がここで良く失敗するのは
docker context を default 以外にしてしまっている時だ。

さて実際にECRレポジトリにpushされたか確認しよう

aws ecr describe-repositories

これで以下のような表示がされれば無事push出来ている
(※パブリックだとこのコマンドで表示されない。)

{
    "repositories": [
        {
            "registryId": "012345678910",
            "repositoryName": "ubuntu",
            "repositoryArn": "arn:aws:ecr:us-west-2:012345678910:repository/ubuntu"
        },
        {
            "registryId": "012345678910",
            "repositoryName": "test",
            "repositoryArn": "arn:aws:ecr:us-west-2:012345678910:repository/test"
        }
    ]
}

魔法のdocker compose

さて、ここまできてようやく下地が整った。
今回追加されたdocker composeコマンドを使用しよう

以下の通りにAWS コンテキストの生成を行う。
ECS での Docker コンテナーのデプロイ

次にAWSコンテキストを以下コマンドで使用しよう。

docker context use myecscontext

今なんのcontextを使用しているかは以下コマンドで確認できる。

docker context ls

そして次に重要なのはcompose ymlファイルの編集だ。
compose コマンドは対応していないルールがあるので、そこだけコメントアウトする必要がある。
(※消しても良いが、コメントを外したりする機会があるかと思うので私はこうしている。)

docker-compose.yml

version: "3"

services:
  frontend:
    # image: soreiyu/front
    image: 000000000000.dkr.ecr.ap-northeast-1.amazonaws.com/soreiyu/front
    # build:
    #   context: .
    #   dockerfile: Dockerfile.front
    command: "yarn start"
    ports:
      - "3000:3000"
    # volumes:
    #   - ./front:/usr/src/app
    # tty: true

  api:
    # image: soreiyu/api
    image: 000000000000.dkr.ecr.ap-northeast-1.amazonaws.com/soreiyu/api:latest
    # build:
    #   context: .
    #   dockerfile: Dockerfile.api
    command: "yarn start"
    ports:
      - "9999:9999"
    # volumes:
    #   - ./api:/usr/src/app

さて、以下コマンドを祈りながら発行しよう。

docker compose up

うまく出来ていればAWSで公開されている。

では最後に一括完全消去して終わりにしよう。

docker compose down

ここまで読んでくれてありがとう。
良いDockerライフを!;)

エラーになったときの対処

クラスターが作成されない → route53のサービスが中途半端に削除されているなど

Discussion