VIVITABLOG

VIVITAで活躍するメンバーの情報発信サイト

【2020年】AWS EC2でNext.jsの環境構築

f:id:vivita-kamakama:20200814164355p:plain

風になった不二子の話

息子が小学生の時、学校から一匹のザリガニを持ち帰りました。
彼はそのザリガニに「不二子(ふじこ)」と名前をつけ、ベランダで飼い始めました。
しかし間も無く、お世話はサボりがちになり、可哀想な不二子は、最後は干からびて死んでしまいました。

ある日ベランダを見てみると、ケースの中にいるはずの不二子がいなくなっていました。
どうやら干からびた不二子が、完全に風化してしまったのではないかという話になりました。
それ以来、我が家では、息子が「犬を飼いたい! ちゃんとお世話をするから!」と言っても、「嘘をつけ! 不二子を風にしたくせに!」と言って、二度と許されないのでした。

AWSでNext.jsの環境を構築したときの話

VIVITAエンジニアの、かまかまです。
AWSのEC2上に、Next.jsの環境を構築したときの手順を、余計なことを書かずにご紹介します。

git / nodejs

$ sudo yum update -y
$ sudo yum install -y gcc gcc-c++ make openssl-devel git
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash

一度、SSHをログアウトしてログインします。

$ nvm install 10.21.0
$ nvm use 10.21.0

GitHub用デプロイキー

$ cd ~/.ssh/
$ ssh-keygen

後で自動化しやすいよう、パスワードは空欄のままにします。
ブラウザで、GitHubの該当リポジトリを開きます。
Settings を選択します。
Deploy keys を選択します。
titledevelopment などと入力します。
Key に、ssh-keygen コマンドで生成した id_rsa.pub の内容をコピペします。
Allow write access はチェックを外します。
Add key を押下します。

$ cd
$ git clone git@github.com:vivitainc/xxxxx.git
$ cd xxxxx/
$ npm install

pm2

次の内容で、予めリポジトリに ecosystem-dev.config.js ファイルを追加しておきます。

module.exports = {
  apps: [
    {
      name: 'xxxxx',
      script: 'npm run dev',
    },
  ],
}

以下のコマンドを実行します。

$ npm install pm2 -g
$ pm2 startup
(上記コマンドを実行すると、実行すべきコマンドが下記のように出力されるので、それをコピペして実行する)
$ sudo env PATH=$PATH:/home/xxx/.nvm/versions/node/v10.21.0/bin /home/xxx/.nvm/versions/node/v10.21.0/lib/node_modules/pm2/bin/pm2 startup systemd -u xxx --hp /home/xxx
$ cd ~/xxxxx/
$ pm2 reload ecosystem-dev.config.js
$ pm2 save

nginx

$ sudo amazon-linux-extras install nginx1.12

/etc/nginx/nginx.conf に以下の内容を挿入します。

    set_real_ip_from   172.31.0.0/16;
    real_ip_header     X-Forwarded-For;
    client_max_body_size 100000m;
    client_body_buffer_size 512k;
    large_client_header_buffers 4 256k;
    proxy_buffers 8 32k;
    proxy_buffer_size 32k;

/etc/nginx/conf.d/0.dev.example.com.conf を次の内容で新規作成します。

map $sent_http_content_type $expires {
    "text/html"                 epoch;
    "text/html; charset=utf-8"  epoch;
    default                     off;
}

server {
    server_tokens off;
    listen          80; 
    server_name     dev.example.com; 

    access_log /var/log/nginx/dev.example.com/access.log main;
    error_log /var/log/nginx/dev.example.com/error.log error;

    client_max_body_size   1024m;
    client_body_buffer_size 512k;

    underscores_in_headers on;

    gzip            on;
    gzip_types      text/plain application/xml text/css application/javascript;
    gzip_min_length 1000;

    location / {
        expires $expires;
        proxy_redirect              off;
        proxy_set_header Host           $host;
        proxy_set_header X-Real-IP      $remote_addr;
        proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto  $scheme;
        proxy_read_timeout          5m;
        proxy_connect_timeout           5m;
        proxy_pass              http://127.0.0.1:3000;
    }
}

以下のコマンドを実行します。

$ sudo mkdir -p /var/log/nginx/dev.example.com
$ sudo chown nginx:nginx /var/log/nginx/dev.example.com
$ sudo service nginx start
$ sudo chkconfig nginx on

複数インスタンスで動かない

上記手順で、開発環境は問題なく動作したのですが、本番環境でなぜか動きません。
本番環境では、ロードバランサーの下に複数のEC2インスタンスがあったのですが、それが原因っぽいです。

調べてみると、こういった場合、Build IDを揃える必要がありました。

next.config.js: Configuring the Build ID | Next.js

Next.jsではビルド時に、ランダムな値でBuild IDが生成されるのですが、各インスタンスでこの値がバラバラだと、うまくアクセスできません。

幸い、この問題に対処するためのライブラリが見つかりました。

nexdrew/next-build-id: Easily set your next build BUILD_ID to the latest git commit hash

このライブラリを使用すると、Build IDの値として、gitの最終コミットハッシュの値が使用されるようになります。

$ npm i next-build-id

次の内容で、設定ファイル next.config.js を追加します。

const nextBuildId = require('next-build-id')
module.exports = {
  generateBuildId: () => nextBuildId({ dir: __dirname })
}

あとがき

調べればすぐに出てきそうな、チュートリアルのような手順をご紹介しました。
僕は普段、他の方の、こういった手順が事細かに書かれた情報を、非常に大切に思っています。

そう強く思うようになったのは、僕がVIVITAに入るずっと前、GitHubでブランチを削除していたときのことなのですが、その話はまた機会があれば、お話しします。

僕が、VIVITAの風になってなければ。