Skip to content

Instantly share code, notes, and snippets.

@aidiary
Last active February 28, 2020 23:19
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aidiary/d34a700467f5c80cec6c96a51ee9f50d to your computer and use it in GitHub Desktop.
Save aidiary/d34a700467f5c80cec6c96a51ee9f50d to your computer and use it in GitHub Desktop.
Docker and Kubernetes: The Complete Guide

Docker and Kubernetes: The Complete Guide (vol.1)

https://www.udemy.com/course/docker-and-kubernetes-the-complete-guide/

2. Manipulating Containers with the Docker Client

Hello World

docker run hello-world
  • ローカルマシンに hello-world というimageがなかったらDocker Hubからダウンロードする
  • run でimageからcontainerを作成する
  • 2回目以降はローカルマシンのimageが使われるのでDocker Hubへアクセスはしない

Image

  • Imageは File System SnapshotStartup Command から成る
  • FS Snapshotはコンテナに展開される

docker run

  • docker run hello-world

  • imageからcontainerを起動する

  • imageに設定されているStartup Commandが実行される

  • docker run busybox echo hi there

  • docker run busybox ls

  • Startup Commandは新しいコマンドを指定することで上書きできる

  • ただし、そのimageに入っているコマンドのみ実行できる

docker ps

  • 起動中のコンテナを表示
  • docker run busybox ping google.com
  • バックグラウンドでコンテナが動き続けるのでpsで表示される
  • docker ps --all
  • これまでに起動した全てのコンテナが表示される

Container Lifecycle

  • docker run = docker create + docker start
  • docker create: imageからcontainerを作成する(FS Snapshotのコピー)
  • docker start : containerを開始する(Startup Commandの実行)
  • docker create hello-world -> コンテナIDを返す
  • docker start -a e4cf8aa
  • 終了したコンテナを再起動することができる
  • ただし、Startup commandを置き換えることはできない
  • -aattach コンテナの出力を表示する

docker system prune

  • 終了したコンテナやキャッシュを一括削除できる

docker logs

  • コンテナからログを取得する
  • docker logs e1816dd7ba
  • 終了してしまったコンテナIDでもOK

docker stop vs docker kill

  • docker stop はプロセスに対してSIGTERMシグナルを送る
  • クリーンアップ処理が入るので終了まで少し時間がかかる
  • docker kill はプロセスに対してSIGKILLシグナルを送る
  • 強制終了させる

docker exec

  • コンテナで「追加の」コマンドを実行する
  • docker run redis コンテナでredisサーバを起動
  • docker exec -it 0affbcc28d4e redis-cli
  • 上のコンテナでコマンドを実行する
  • -i ターミナルの入力をコンテナのstdinへつなげる
  • -t コンテナのstdoutとstderrをターミナルへつなげる

shellの実行

  • docker exec -it 0affbcc28d4e sh
  • デバッグに便利!
  • shはだいたい内蔵している、bashやzshが使えるコンテナも
  • docker run -it busybox sh
  • コンテナの起動時にshellを実行したいとき

3. Building Custom Images Through Docker Server

独自NodeアプリのimageをDockerで作成する。

Dockerfile

オリジナルのimageのテンプレートになる

  1. ベースイメージを指定する
  2. 追加のプログラムをインストールする
  3. コンテナを開始した時のStartup commandを定義する

docker build

  • Dockerfileからimageをbuildする
  • docker build .

Dockerfile

FROM alpine
RUN apk add --update redis
CMD ["redis-server"]
  • 各ステップにおいて前のimageの一時的なコンテナを作成してコマンドを実行する
  • 各ステップの最後で一時的なコンテナは削除して新しいimageを作る
Step 2/3 : RUN apk add --update redis
 ---> Running in 586d9af2f84e  # 一時的なコンテナを作成
 Removing intermediate container 586d9af2f84e  # 一時的なコンテナを削除
 ---> 2d406a836250  # 新しいimageを作成
Step 3/3 : CMD ["redis-server"]
 ---> Running in ea3c5a296c49  # 一時的なコンテナを作成
Removing intermediate container ea3c5a296c49  # 一時的なコンテナを削除
 ---> d037ccca4765  # 新しいimageを作成
Successfully built d037ccca4765
  • imageにタグをつけると後から参照しやすい
  • docker build -t f2forest/redis:latest .

docker commit

  • コンテナからimageを作成する
  • コンテナの中に入って作業した後にオリジナルimageを作る時に使う

docker commit -c 'CMD ["redis-server"]' 32a278410a10 myimage:latest

  • コンテナ起動時に実行するコマンドは -c で指定できる

4. Making Real Projects with Docker

Node.jsのアプリケーションをDockerで動かす

alpine version

  • node:alpine などalpineがついているバージョンは余計なツールが付属していない最小イメージを意味する

COPY

  • package.jsonは事前に転送が必要
  • npm install を動かすために package.json が必要なのでローカルからコンテナへCOPYする
  • COPY . . でローカルファイル(package.json)をコンテナにコピー
  • .docker build で指定したコンテキストからの相対パス
  • キャッシュを有効的に使うために先に package.json だけ転送し、ビルドした後に残りのファイルを転送するとよい
WORKDIR /usr/app
COPY ./package.json ./
RUN npm install
COPY ./ ./

Port Mapping

  • ローカルマシンからコンテナの8080ポートにそのままではアクセスできない
  • docker runでPort Mappingを使う
  • docker run -p 8080:8080 <image_id>
  • ローカルマシンの8080:コンテナの8080

Working Directory

  • alpineのデフォルトではCOPYで / にファイルが転送される
  • 事前にWorking Directoryを指定しておくとよい
  • WORKDIR /usr/app

最終的なDockerfile

FROM node:alpine

WORKDIR /usr/app
COPY ./package.json ./
RUN npm install
COPY ./ ./

CMD ["npm", "start"]

5. Docker Compose with Multiple Local Containers

  • NodeアプリとRedisを異なるコンテナで実行する。
  • デフォルトではコンテナ間の通信はできない
  1. Docker CLIのネットワーク機能を使う
  2. Docker Composeを使う(おすすめ)

Docker Compose

  • Dockerとは別のツール
  • 複数のDockerコンテナを同時に起動できる
  • docker runに指定する必要がある複雑な引数を自動化できる
  • コンテナ間の通信も簡単にできる

docker-compose.yml

  • 複数のコンテナの設定を記述するファイル
version: "3"
services:
  redis-server:
    image: "redis"
  node-app:
    build: .
    ports:
      - "4001:8081"
  • docker-compose.ymlで書いたサービスは同一のネットワークに所属して互いにアクセス可能に
  • アプリケーションからはservicesの名前でホストにアクセスできる
const client = redis.createClient({
  host: "redis-server",
  port: 6379
});

docker-compose

  • 全てのコンテナを起動する docker-compose up

  • コンテナをbuildしてから起動する docker-compose up --build

  • コンテナをバックグラウンドで起動する docker-compose up -d

  • 全てのコンテナを停止する docker-compose down

Automatic Container Restarts

  • アプリケーションがcrashするとコンテナごと落ちてしまう

Restart Policies

version: "3"
services:
  redis-server:
    image: "redis"
  node-app:
    restart: always
    build: .
    ports:
      - "4001:8081"
  • "no": リスタートしない(予約語なので""が必要)
  • always: いつもリスタートする
  • on-failure: エラーコード(0以外)が返った時のみリスタート
  • unless-stopped: 開発者が強制終了しない限りリスタート

docker-compose ps

  • コンテナのプロセスを確認する
  • docker-compose.yml があるディレクトリのみ表示される

6. Creating a Production-Grade Workflow

  1. ローカルマシンで開発
  2. Githubのfeature branchにpush
  3. PRを出してmasterにmerge
  4. Travis CIにpushしてテスト
  5. Travis CIがAWS (Elastic Beanstalk) にデプロイ

DockerはこれらのFlowを簡単化するツールとして使われる。

React App

プロジェクトの開始方法

npm install -g create-react-app create-react-app client よりも npx create-react-app client がよい

npm command

  • npm run start: development serverを起動
  • npm run test: テストを実行
  • npm run build: production versionをbuild

Dockerfile.dev

development用のDockerfileを作るとよい

FROM node:alpine
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
CMD ["npm", "run", "start"]
  • Dockerfile 以外の名前の時は -f オプションを使う
  • docker build -f Dockerfile.dev .
  • COPY . . するとローカルの node_modules を転送してしまうのであらかじめ削除しておくこと!
  • コンテナ内の npm installnode_modules ができる
  • docker run -p 3000:3000 86a212 でReact Appを起動できる(port指定を忘れないこと!)

Docker Volumes

  • ローカルのソースの編集がコンテナのアプリに反映されない問題がある
  • ローカルのファイルをCOPYするのではなく、コンテナがローカルのファイルを参照するようにする仕組みがDocker Volumes
docker run -p 3000:3000 -v /app/node_modules -v $(pwd):/app 86a212
  • -v オプションは : を使う構文と使わない構文があるので注意!
  • -v $(pwd):/app ローカルのカレントディレクトリをコンテナの /app にマッピング
  • ローカルカレントディレクトリをマッピングすると、 node_modules がないという問題がある
  • コンテナにのみある node_modules をそのまま残したい場合に -v /app/node_modules を使う
  • : なしのオプションは コンテナにあるファイル を指定する
  • volumeを使う場合は、 COPY . . のファイルコピーは不要だが 残しておいたほうがよい

docker-compose

  • docker run のコマンドが長くなりがち => docker-composeで解決できる!
  • コンテナが1つでもdocker-composeは使える
  • デフォルトの Dockerfile 以外を使う場合は contextdockerfile を指定する
version: "3"
services:
  web:
    build:
      context: .
      dockerfile: Dockerfile.dev
    ports:
      - "3000:3000"
    volumes:
      - /app/node_modules
      - .:/app

Test

  • Dockerfileのデフォルトコマンドは npm run start になっている
  • docker run -it fe1a37cb8148 npm run test コマンドを置き換えれば、同じコンテナでtestを起動できる

Live Updating Tests

上の方法ではvolumeを使ってないため src/App.test.js を更新しても反映されない問題がある

  1. docker-compose up でボリュームをしたコンテナを起動する
  2. そのコンテナでテストを実行する docker exec -it ed9c9c1bc87a npm run test

で解決できるが、 docker exec のコマンドを実行するのは負荷が高い

docker-compose.yml に新しいコンテナを追加するアプローチもある。ただし、この方法はテストのキーボード入力が使えない & webのロギングと混ざるという欠点がある。

version: "3"
services:
  web:
    build:
      context: .
      dockerfile: Dockerfile.dev
    ports:
      - "3000:3000"
    volumes:
      - /app/node_modules
      - .:/app
  tests:
    build:
      context: .
      dockerfile: Dockerfile.dev
    volumes:
      - /app/node_modules
      - .:/app
    command: ["npm", "run", "test"]
  • 結局、webコンテナの中に入って npm run test やったほうが早いんじゃ・・・?
  • インタラクティブにコマンド入力もできる

Nginx

  • 開発環境で index.htmlmain.js を提供するのに使っていたDevelopment Serverは、製品環境では使えない
  • Development Serverの代わりになるProduction Serverである nginx が必要

Multi-step Docker Builds

製品環境用に Dockerfile を新しく作る

  1. Use node:alpine
  2. Copy the package.json file
  3. Install dependencies => これは npm run build をするためだけに必要(deployには不要、 build だけあればOK)
  4. Run npm run build
  5. Start nginx => nginx はどこにある???

この問題を解決するのが Multi-step Docker Builds

(1) Build Phase
  1. Use node:alpine
  2. Copy the package.json file
  3. Install dependencies
  4. Run npm run build
(2) Run Phase
  1. Use nginx
  2. Copy over the result of npm run build
  3. Start nginx
  • 複数のstageを1つのDockerfileの中に書ける
  • as でstageに名前をつけられる
  • COPY --from=XXX で別のstageのファイルをコピーできる
FROM node:alpine as builder
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
RUN npm run biild

FROM nginx
COPY --from=builder /app/build /usr/share/nginx/html
  • nginxのstaticファイルは /usr/share/nginx/html に置く
  • nginxはRUNは不要、ファイルをコピーするだけで動く
  • docker run -p 8080:80 656571ea6184

7. Continuous Integration and Deployment with AWS

  1. Profileをクリックして Legacy Services Integration から対象のリポジトリをチェック
  2. リポジトリに .travis.yml (Travisが何をするかを記述した設定ファイル)を作成

.travis.yml

sudo: required
services:
  - docker

before_install:
  - docker build -t f2forest/docker-react -f Dockerfile.dev .

script:
  - docker run -e CI=true f2forest/docker-react npm run test
  • dockerはsudoで実行なので sudo: required が必要
  • npm run test はプロンプトを出すので正常終了しない -e CI=true を付ける
  • GithubにpushするとTravis CIが動き出す
The command "docker run -e CI=true f2forest/docker-react npm run test" exited with 0.
Done. Your build exited with 0.

になっていればテストが通った状態。

Elastic Beanstalk

  1. アプリケーションの作成
  2. アプリケーションの環境を作成
  3. ウェブサーバー環境の作成
  4. プラットフォーム Docker にして環境作成
  5. ヘルスOKでURLにアクセスできれば成功
  • Elastic Beanstalkを起動するとLoad Balancerも作られる
  • リクエストがLoad Balancernに届くと、Appが動くDocker Containerに振り分ける
  • 負荷に応じて自動的にスケールする(Containerが複数起動する)
  • IAMの Usersdocker-react-travis-ci (任意)を作成して Programmatic access にチェック
  • Attach existing policies directlyAWSElasticBeanstalkFullAccess をチェック
  • 作成時に表示されるSecret access keyへはあとでアクセスできないのでCSVを保存しておくこと

Travis CIからAWSへデプロイ

sudo: required
services:
  - docker

before_install:
  - docker build -t f2forest/docker-react -f Dockerfile.dev .

script:
  - docker run -e CI=true f2forest/docker-react npm run test

deploy:
  provider: elasticbeanstalk
  region: "us-east-2"
  app: "docker-react"
  env: "DockerReact-env"
  bucket_name: "elasticbeanstalk-us-east-2-189406403391"
  bucket_path: "docker-react"
  on:
    branch: master
  access_key_id: $AWS_ACCESS_KEY
  secret_access_key:
    source: "$AWS_SECRET_KEY"
  • 本番環境のビルドはElastic Beanstalk側でやっている?
  • アプリに必要なファイルはTravis CIがS3へアップロードする
  • Elastic BeanstalkのS3は自動的に作られる elasticbeanstalk-us-east-2-189406403391
  • bucket_path は最初にデプロイした時に自動的に作られる
  • master にmergeされた時のみデプロイする
  • Travisの More Options > Settings > Environment Variables にAWSのキー AWS_ACCESS_KEYAWS_SECRET_KEY を保存
  • production環境のビルドのコマンドは不要? Dockerfileを自動的に使うようだ
  • AWS Elastic Beanstalkで動かすときは EXPOSE 80 の追加が必要
FROM nginx
EXPOSE 80
COPY --from=builder /app/build /usr/share/nginx/html

8. Building a Multi-Container Application

Fibonacci Calculatorを作る。 以下の複数のコンテナから成る。

  1. Nginx: リクエストを受け付けるWebサーバ
  2. React App: FrontendのGUIアプリ
  3. Express Server: Fibonacci数を計算するbackendのAPI
  4. Postgres: ユーザの入力したindexを永続的に保存
  5. Redis: indexと計算したFibonacci数のペアを保存
  6. Worker: Redisに新しいindexが入ったか監視し、Fibonacci数を計算して返す

Worker

  • nodemon は、開発環境でサーバを自動起動させるためのライブラリ
  • Fibonacciの再帰計算は遅いので、計算を担当するWorkerとして独立させる

Express Server

  • keys.js というファイルを作って環境変数はまとめておくと便利
  • 環境変数はdocker-composeで指定できる
module.exports = {
  redisHost: process.env.REDIS_HOST,
  redisPort: process.env.REDIS_PORT,
  pgUser: process.env.PGUSER,
  pgHost: process.env.PGHOST,
  pgDatabase: process.env.PGDATABASE,
  pgPassword: process.env.PGPASSWORD,
  pgPort: process.env.PGPORT
};

9. Dockerizing Multiple Services

clientのDockerfile

  • React App
FROM node:alpine
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
CMD ["npm", "run", "start"]

serverとworkerのDockerfile

  • Express Server
  • npm run dev でnodemonが起動するように package.json を設定
FROM node:alpine
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
CMD ["npm", "run", "dev"]

docker-compose.yml

  • 複数のDockerコンテナやDBを束ねるためのdocker-composeを構成
  • Express Serverとredis/postgresはserverの環境変数で結び付く
  • variableName=value は、ランタイム(コンテナをrunしたとき)でセットする
  • variableName は、ランタイムでローカルマシンの環境変数から取られる(API_KEYなど)
  • HOST名は http:// を付けずに単にservice名を指定すればOK
  • depends_on がないと正常に動かないことがある
  • https://docs.docker.com/compose/compose-file/#depends_on
version: "3"
services:
  postgres:
    image: "postgres:latest"
  redis:
    image: "redis:latest"
  nginx:
    restart: always
    build:
      dockerfile: Dockerfile.dev
      context: ./nginx
    ports:
      - '8080:80'
    depends_on:
      - api
      - client
  api:  # Express Server
    build:
      dockerfile: Dockerfile.dev
      context: ./server
    volumes:
      - /app/node_modules
      - ./server:/app
    environment:
      - REDIS_HOST=redis
      - REDIS_PORT=6379
      - PGUSER=postgres
      - PGHOST=postgres
      - PGDATABASE=postgres
      - PGPASSWORD=postgres_password
      - PGPORT=5432
    depends_on:
      - postgres
  client:  # React App
    build:
      dockerfile: Dockerfile.dev
      context: ./client
    volumes:
      - /app/node_modules
      - ./client:/app
  worker:
    build:
      dockerfile: Dockerfile.dev
      context: ./worker
    volumes:
      - /app/node_modules
      - ./worker:/app
    environment:
      - REDIS_HOST=redis
      - REDIS_PORT=6379

Nginx

  • NginxはURLを見て React App と Express Server を切り替える役割がある
  • /index.html, /main.js ====> React App
  • /values/all, /values/current ====> Express Server
  • Express Serverは /values/all /values/current など記述
  • React Appは /api/values/all /api/values/current など /api/ を付けてアクセス
  • Nginxは /api/ が付いていたらExpress Serverへ、/ だったらReact Appへ流す
  • Nginxは /api/ を省いた残りをExpress Serverへ送る

default.conf

  • Nginxの設定ファイル
  • React Appは3000でlisten
  • Express Serverは5000でlisten
  • Nginxは80でlisten
  • rewrite /api/(.*) /$1 break; によってExpress Serverへは /api/ を除いたURLが送られる
  • default.confは セミコロンを忘れずに!
upstream client {
  # clientはReact AppのHOST名 @ docker-compose.yml
  server client:3000;
}

upstream api {
  # apiはExpress ServerのHOST名 @ docker-compose.yml
  server api:5000;
}

server {
  listen 80;

  location / {
    proxy_pass http://client;
  }

  location /api {
    rewrite /api/(.*) /$1 break;
    proxy_pass http://api;
  }
}

NginxのDockerfile.dev

FROM nginx
COPY ./default.conf /etc/nginx/conf.d/default.conf

docker-compose.yml にも追加

services:
  nginx:
    restart: always
    build:
      dockerfile: Dockerfile.dev
      context: ./nginx
    ports:
      - '8080:80'
    depends_on:
      - api
      - client

websocket warning

  • Chrome devtoolsで以下のWarningが出ることがある。
  • React.jsが開発時に使っている
websocket.js:6 WebSocket connection to 'ws://localhost:8080/sockjs-node/273/5leumlyb/websocket' failed: Error during WebSocket handshake: Unexpected response code: 400
  • Nginxの設定で /sockjs-node をReact Appへ接続する必要がある
  location /sockjs-node {
    proxy_pass http://client;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
  }

10. A Continuous Integration Workflow for Multiple Images

TravisCIを経由してAWSのElastic Beanstalkへデプロイするまで

Multi Container Setup Flow

  1. Push code to github
  2. Travis automatically pulls repo
  3. Travis builds a test image, test code
  4. Travis builds prod images
  5. Travis pushes built prod images to Docker Hub
  6. Travis pushes project to AWS EB
  7. EB pulls images from Docker Hub, deploys
  • オリジナルのimageとnginx/postgres/redisなど既存imageが混ざった状況
  • オリジナルのimageはDocker Hubに登録できるので活用するとデプロイが容易に
  • TravisCIでアプリをビルドしてDocker HubにアップロードしておけばElastic Beanstalkでビルドが不要になる

Production Dockerfile

  • worker/serverに関しては npm run devnpm run start に置き換えるだけ
  • package.jsonnode index.js が指定されている
FROM node:alpine
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
CMD ["npm", "run", "start"]
  • clientはReact Appなのでビルドが必要
  • Routingを担当するNginxと、ビルドしたReactAppを提供するNginxの2つを用意する
  • clientのNginxは3000ポートにアクセスされた時にビルドしたReactAppを提供する

client/nginx/default.conf

server {
  listen 3000;

  location / {
    root /usr/share/nginx/html;
    index index.html index.htm;
    try_files $uri $uri/ /index.html;
  }
}

client/Dockerfile

FROM node:alpine as builder
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
RUN npm run build

FROM nginx
EXPOSE 3000
COPY ./nginx/default.conf /etc/nginx/conf.d/default.conf
COPY --from=builder /app/build /usr/share/nginx/html

Travis CIの設定

  1. React Appのテスト
  2. imageのビルド
  3. Docker Hubへimageをpush

.travis.yml

sudo: required
services:
  - docker

before_install:
  # build image for test
  - docker build -t f2forest/react-test -f ./client/Dockerfile.dev ./client

script:
  # run test
  - docker run -e CI=true f2forest/react-test npm run test

after_success:
  # build image
  - docker build -t f2forest/multi-client ./client
  - docker build -t f2forest/multi-nginx ./nginx
  - docker build -t f2forest/multi-server ./server
  - docker build -t f2forest/multi-worker ./worker

  # Log in to the docker CLI
  # ユーザ名とパスワードは見えないようにTravis CIの環境変数に登録しておく
  - echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_ID" --password-stdin

  # Take those images and push them to docker hub
  - docker push f2forest/multi-client
  - docker push f2forest/multi-nginx
  - docker push f2forest/multi-server
  - docker push f2forest/multi-worker

11. Multi-Container Deployments to AWS

  • 単一コンテナの場合は、Elastic BeanstalkがDockerfileから自動的にビルドしてデプロイしていた
  • 複数コンテナ(複数のDockerfile)からなる場合は、追加の設定 Dockerrun.aws.json が必要
  • docker-compose.ymlと違ってすでにbuildされたimageを設定する
  • ECS (Elastic Container Service) の task definition と仕様がほとんど同じなのでドキュメントが参考になる
  • https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/task_definitions.html

Dockerrun.aws.json

  • essential: true は対象コンテナが落ちたら他のコンテナも落ちるようにする設定
  • nginxが落ちると他のコンテナへはアクセスできなくなるのでessentialにする
  • Dockerrun.aws.jsonでのタイポは厄介なので https://jsonlint.com/ などで確認するとよい
{
  "AWSEBDockerrunVersion": 2,
  "containerDefinitions": [
    {
      "name": "client",
      "image": "f2forest/multi-client",
      "hostname": "client",
      "essential": false
    },
    {
      "name": "server",
      "image": "f2forest/multi-server",
      "hostname": "api",
      "essential": false
    },
    {
      "name": "worker",
      "image": "f2forest/multi-worker",
      "hostname": "worker",
      "essential": false
    },
    {
      "name": "nginx",
      "image": "f2forest/multi-nginx",
      "hostname": "nginx",
      "essential": true,
      "portMappings": [
        {
          "hostPort": 80,
          "containerPort": 80
        }
      ],
      "links": ["client", "server"]
    }
  ]
}

Elastic Beanstalkの設定

  • Platformに Multi-container Docker を指定
  • あとはデフォルトで環境を作成

Managed Data Service Providers

  • Redisは AWS Elastic Cache に置き換えるとよい
  • Postgresは AWS Relational Database Service に置き換えるとよい

AWS Elastic Cache

https://aws.amazon.com/jp/elasticache/

  • Redisインスタンスを自動的に作成してくれる
  • スケールが簡単
  • ロギングやメンテナンスがしやすい
  • 強固なセキュリティ
  • AWS以外のサービスへの移植が簡単

AWS Relational Database

https://aws.amazon.com/jp/rds/

  • Postgresインスタンスを自動的に作成してくれる
  • スケールが簡単
  • ロギングやメンテナンスがしやすい
  • 強固なセキュリティ
  • 自動バックアップとロールバック
  • AWS以外のサービスへの移植が簡単

VPC & Security Groups

  • デフォルトでは、Elastic BeanstalkからRDSやECにアクセスできない
  • 同じ VPC (Virtual Private Cloud) にEB/RDS/ECをまとめる
  • VPCはRegionをまたぐことはできない
  • Security Group (Firewall Rules)
  • Elastic Beanstalkの環境を作るとVPCとSecurity Groupsができている (?)
  • 同じセキュリティグループに属するAWSサービスからの接続を許可するようにEB/RDS/ECを設定

RDS

  • データベースの作成でPostgresSQLを選択
  • テストなので db.t2.micro を選択
  • DBインスタンス識別子: multi-docker-postgres
  • Master username: postgres
  • Master password: postgres_password
  • VPCセキュリティグループ: 新規作成 > multi-docker
  • 最初のデータベース名: fibvalues

Elastic Cache

  • Redisで作成
  • 名前: multi-docker-redis
  • ノードのタイプ: t2.micro
  • サブネットグループの名前: redis-group
  • VPC ID: EBで作られたVPC

Security Group

  • 名前: multi-docker
  • インバウンドルール: カスタムTCP 5432-6379
  • 5432は PGPORT、6379は REDIS_PORT
  • ソース: multi-dockerのsg
  • EB/RDS/ECをこのSecurity Groupに所属させる!
  • Redisにアクセスできないエラー(Timeout)があったが、Security Group追加してないためだった。要注意!

EBの環境変数の設定

  • EBからRedisやRDSへアクセスするための設定
  • EB > 設定 > ソフトウェア から環境変数を設定する
  • redis/postgresのエンドポイントのURLはAWSのサービスから取得できる
  - REDIS_HOST=multi-docker-redis.yf6uwv.0001.use1.cache.amazonaws.com
  - REDIS_PORT=6379
  - PGUSER=postgres
  - PGHOST=multi-docker-postgres.cfyostac2ypt.us-east-1.rds.amazonaws.com
  - PGDATABASE=fibvalues
  - PGPASSWORD=postgres_password
  - PGPORT=5432

IAM Key

  • Travis CIからAWSへアクセスするためのkeyを取得
  • ユーザを作成してアクセスキーIDとシークレットアクセスキーを取得
  • Travis CIの環境変数に AWS_ACCESS_KEYAWS_SECRET_KEY を追加

.travis.yml

  • Travis CIからAWSにdeployする設定を追加
deploy:
  provider: elasticbeanstalk
  region: us-east-1
  app: multi-docker
  env: MultiDocker-env
  bucket_name: elasticbeanstalk-us-east-1-189406403391
  bucket_path: multi-docker
  on:
    branch: master
  access_key_id: $AWS_ACCESS_KEY
  secret_access_key: $AWS_SECRET_KEY

Memory Error

  • GithubにpushしてTravis CIからデプロイするとElastic Beanstalkで以下のエラー
Service:AmazonECS, Code:ClientException, Message:Invalid setting for container 'client'. At least one of 'memory' or 'memoryReservation' must be specified., Class:com.amazonaws.services.ecs.model.ClientException
  • Dockerrun.aws.jsonmemory を追加
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment