EC2にdocker-composeでRailsをデプロイする (CI/CDまでの道⑥)

2022/01/24に公開

はじめに

前回はRailsをProductionモードで起動しました。今回はEC2にDockerをインストールして、そのうえでProductionモードで起動して、独自のドメインで実際にアクセスできるところまでチャレンジしていきます。

作成に利用するリポジトリはこちら

注意

このハンズオンでは以下の書籍を用います。

AWSではじめるインフラ構築入門 安全で堅牢な本番環境のつくり方

このハンズオンですべてインフラ環境構築の手順を画像付きで載せてもよかったのですが、ほぼこの本通りになってしまい、本を模写することになってしまい著作権に触れてしまう可能性があるためほぼ書籍通りに環境構築をおこないながら進めていきます。一部変更箇所があるのでそこだけ説明を別途入れたいと思います。EC2にドメインでアクセスできるような環境があればインフラ構築は飛ばしていただいて大丈夫です。

本ハンズオンの構成は以下となります。

CI/CDまでの道シリーズ

環境

  • WSL2 (Ubuntu20.04)
  • Docker 20.10.9
  • docker-compose 1.29.1
  • Git 2.25.1
  • VSCode

AWSインフラ環境の構築

上で説明した通り基本的には書籍通りにインフラ環境を行います。一部だけ変更がありますのでそこは説明を行います。

第1章 AWSをはじめよう

今回は関係ないのでスキップで大丈夫です。

第2章 AWSアカウントを作ろう

書籍通りに作業を行ってください

第3章 安全に作業するための準備

関係ないのでスキップで大丈夫です。

第4章 仮想ネットワークを作ろう

書籍通りに作業を行ってください

第5章 踏み台サーバーを用意しよう

書籍通りに作業を行ってください

第6章 Webサーバーを用意しよう

書籍通りに作業を行ってください

第7章 ロードバランサーを用意しよう

ここは一部修正を行います。
書籍のハンズオンではNginxのポートを3000番で開いているためロードバランサーはEC2の3000番をみにいくように設定していますが、私たちの作成している環境はNginxが80番ポートで受け付けているのでターゲットグループ作成で3000と設定しているところを80に変更します。

具体的な修正箇所は以下です。

ここの80は変更せずターゲットグループを作成します。

このように設定をします。

ターゲットの登録でweb01web02を選択してinclude as pending belowでしっかりと登録してからターゲット登録するのを忘れないようにしてください。

あとは書籍通りですが7.3.1の動作確認で

$ python -m SimpleHTTPServer 3000

をしていますが、これは今回80番ポートにしたので動作確認はできません。 飛ばして大丈夫です。
その代わりに実際にデプロイして確認します。

第8章 データベースサーバーを用意しよう

基本的には書籍通りです。
しかし、データベースのパスワードに関してはこのハンズオンではpasswordにしたいと思います。

あとで.envにこのパスワードを設定しますが、passwordとしましたので各自読み替えて設定してください。

9章以降について

これ以降で行う必要があるのは10章のみとなりますが、これはデプロイ後に行いますので9章まで行ったらデプロイにチャレンジします。

9, 11, 12, 13, 14, 15章はこのハンズオンには不要です。

EC2にデプロイする

まずはWebサーバー(web01)にssh接続します。

$ ssh web01

ここでWSL2でなぜか多段階接続ができず、PowershellでC:\Users\ユーザー名\.sshconfigpemをおいて接続(ssh web01)を行ったあとにWSL2で多段階接続するといけました。
Windows環境との競合などが発生しているようです。

以下の記事を参考にEC2にDockerdocker-composeGitをインストールしていきます。

【AWS】EC2にDockerとDocker Composeをインストール
AWS EC2 AmazonLinux2 Gitをインストールする

$ sudo amazon-linux-extras install -y docker
$ sudo systemctl start docker
$ VER=v2.2.3
$ sudo curl -L https://github.com/docker/compose/releases/download/${VER}/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose
$ sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
$ sudo yum install git

次にGitから作成したDocker環境をクローンしてきます。

$ git clone https://github.com/jinwatanabe/CICD_Road

VSCodeのリモートSSHを利用してweb01CICD_Road/chapter05にはいります。

※ web01のCI_CD_Road_4となっていますが、皆様の画面ではCICD_Roadとなっているかと思います

リモートSSHについては以下を参考に入れてみてください。

VSCode の Remote - SSH 機能を使って EC2 上で開発する

CICD_Road/chapter05のディレクトリに移動します。

config/credentials.yml.encを削除します(ない場合は省略)
前回作成したconfig/credentials.yml.encconfig/master.keyconfig/にコピーします。

以下の記事を参考にProductionモードをEC2ように修正していきます。

EC2上でRailsアプリケーションにDockerを導入する(Rails、Nginx、RDS)

まずは.envの内容を以下に変更します。

.env
DB_USERNAME="admin"
DB_PASSWORD="password"
DB_HOST="RDSのエンドポイント名"
DB_DATABASE="myapp"

RDSのエンドポイント名のところには、書籍のP178で確認したエンドポイントを入れてください。

次にDBのProduction時の設定を変えます。config/database.ymlproduction部分を以下に修正します。

config/database.yml
(省略)
production:
  <<: *default
  database: <%= ENV['DB_DATABASE'] %>
  adapter: mysql2
  encoding: utf8mb4
  charset: utf8mb4
  collation: utf8mb4_general_ci
  host: <%= ENV['DB_HOST'] %>
  username: <%= ENV['DB_USERNAME'] %>
  password: <%= ENV['DB_PASSWORD'] %>

今回はRDSを利用するのでdocker-compose.production.ymlのDBに関する部分をコメントアウトします。

docker-compose.production.yml
version: "3.9"
services:
  rails:
    build: .
    container_name: rails
    command: bundle exec puma -C config/puma.rb -e production
    volumes:
      - .:/myapp
      - public-data:/myapp/public
      - tmp-data:/myapp/tmp
      - log-data:/myapp/log
      - /myapp/node_modules
    env_file:
      - .env
    # depends_on:
    #   - db
    user: root

  # db:
  #   image: mysql:8.0.27
  #   container_name: db
  #   environment:
  #     TZ: Asia/Tokyo
  #     MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
  #   ports:
  #     - "3306:3306"
  #   volumes:
  #     - db:/var/lib/mysql
  
  web:
    build:
      context: containers/nginx
    volumes:
      - public-data:/myapp/public
      - tmp-data:/myapp/tmp
    ports:
      - 80:80
    depends_on:
      - rails

volumes:
  # db:
  #   driver: local
  public-data:
  tmp-data:
  log-data:

次にNginxの設定をします。containers/nginx/nginx.confserver_nameを変更します。

containers/nginx/nginx.conf
# プロキシ先の指定
# Nginxが受け取ったリクエストをバックエンドのpumaに送信
upstream myapp {
  # ソケット通信したいのでpuma.sockを指定
  server unix:///myapp/tmp/sockets/puma.sock;
}

server {
  listen 80;
  # ドメインもしくはIPを指定
  server_name [Web01のプライベートIP]; #修正

(省略)

Web01のプライベートIPをいれます。

※ 注意 Web02の場合はWeb02のプライベートIPをいれます

次にコンテナを起動するための準備としてコンパイルDB作成(Web01とWeb02で共有しているのでWeb01でやる1回でOK)を行います。

またDockerコマンド、docker-composeコマンドはすべてsudoで実行する必要があります。

$ sudo docker-compose -f docker-compose.production.yml build
$ sudo docker-compose -f docker-compose.production.yml run rails rails assets:precompile RAILS_ENV=production

# DB作成はweb01でのみ
$ sudo docker-compose -f docker-compose.production.yml run rails rails db:create  RAILS_ENV=production

# 起動
$ sudo docker-compose -f docker-compose.production.yml up

実際にデプロイが成功しているか踏み台サーバーbastionから確認します。別のターミナル(Powershellなど)を開きbastionssh接続して確認します。

$ ssh bastion
$ curl [web01のプライベートIP]/test

以下のように出力されていればうまくデプロイができています。

[ec2-user@ip-10-0-0-236 ~]$ curl 10.0.71.6/test
<!DOCTYPE html>
<html>
<head>
<meta content='text/html; charset=UTF-8' http-equiv='Content-Type'>
<title>Myapp</title>
<meta content='width=device-width,initial-scale=1' name='viewport'>
<meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="wOB_duwKTFg2RWJThBSxhJyRM0ZhZpiM5StGDa648VnVaTP7VqhFIVGV8rLIa63WDcoO83cA5s22BgtDo96LBA" />

<script src="/packs/js/application-5c597b4d3c61e38cc616.js"></script>
<link rel="stylesheet" media="screen" href="/packs/css/application-8b2e0365.css" />
<script src="/packs/js/main-4c9d47074ceee9ee29cb.js"></script>
</head>
<body>
<h1>Hello World</h1>
<h2>CSSが適応されると色が変わる</h2>
<button class='btn btn-primary' type='button'>Bootstrap適応</button>
こんにちは

/testがないとproductionモードでは404エラーになります。(万歳画面はなくなるので)

ここまでできたら、Web02に関しても同じ手順でコンテナを起動します。nginx.confのプライベートIPをWeb02のプライベートIPにして、DB作成は行わないが違う点です。

ドメインを登録する

ここまでできたら書籍の第10章 独自ドメインとDNSを用意しようを行います。

こちらも書籍通りに行います。

Webサイトを確認する

https://www.自分のドメイン/testにアクセスしてページが表示され、CSSやJavascriptが適応されていれば成功です。

JavascriptのアラートはChoromeだと最初の1回のみしか(リロードでは)表示されませんので注意してください。Choromeをすべて閉じてから再度開いてください

Chromeでアラートが表示されないときの対処方法

/testを忘れるとNginxのエラー画面になるので注意してください。

おわりに

作成したものはこちらのリポジトリに用意しています。

ひとまずデプロイができるようになりました。
しかしこの状態ではコンテナを差し替えるときに起動までの時間ユーザーに利用できない時間ができたり、手間がかかったりと問題は多いので次はコンテナに適したデプロイにチャレンジしていきたいです。

参考

GitHubで編集を提案

Discussion