Heroku に登録して Express サーバをデプロイして動かしてみる

Heroku (ヘロク) という PaaS (Platform as a Service) がある。Debian・Ubuntu 系の Linux 仮想環境に、Ruby on Rails や Node.js 製のアプリをデプロイして公開できるサービスだ。DB に PostgreSQL などが使える。無料枠もあり、開発者がお試しで使うには十分な環境。

Rails チュートリアルで登場して名前が知られているかもしれないが、Node.js もサポートするようになっていて、Express サーバが動かしやすそうだったので、いまさらながら Heroku を試してみた。

実施環境は macOS Mojave と Windows 10 それぞれで検証。どちらでも同様に動作した。

目次

Heroku への登録

Heroku への登録は Web サイト上からすんなりと。

登録後、「Create new app」画面でアプリの名前 (URL) を決める。コレで https://【決めた名前】.herokuapp.com/ というサブドメイン形式でそのアプリにアクセスできるようになる。

当然、「Create new app」で登録しただけでは、参照するアプリがないので、コレからサンプルアプリを作ってデプロイしていこうと思う。

Heroku CLI のインストール

Heroku の管理操作は Web サイト上で行えるが、Heroku CLI というコマンドラインツールが提供されていて、コレを利用すると Git コマンドや GitHub などとの連携が大変やりやすくなる。

次の公式ページより Heroku CLI をダウンロードし、インストールする。インストーラ上での設定は特に変更なし。

インストールが完了すると、ターミナル上で $ heroku コマンドが使えるようになる。

サンプルアプリのリポジトリを作成する

さて、いよいよサンプルアプリの作成に入る。今回は Node.js 製のサーバフレームワークである Express を利用して、https://【アプリ名】.herokuapp.com/ にアクセスすると Hello World! と書かれたページが表示されるだけのアプリを作ってみる。

適当な作業ディレクトリを作り、git init を行う。もしくは、GitHub 上でリポジトリを作っておいてから git clone で持ってきてもどちらでも良い。

$ mkdir example-app && cd $_
$ git init

Heroku CLI でのログイン・サンプルアプリのリポジトリと Heroku アプリを紐付ける

次に、「この作業ディレクトリの資材を、この Heroku アプリにデプロイするよー」という紐付けを行う。

作業ディレクトリに移動し、Heroku CLI でログインする。

$ heroku login
heroku: Enter your login credentials
Email: 【Heroku 登録時に記載したメールアドレス】
Password: 【パスワード】

Logged in as 【メールアドレス】

このようにログインできる。

ログインができたら、作業ディレクトリの Git リポジトリを、Heroku アプリと紐付ける。

$ heroku git:remote -a 【Heroku アプリ名】
set git remote heroku to https://git.heroku.com/【Heroku アプリ名】.git

このように紐付けられる。

Node.js プロジェクトを作成していく

Git リポジトリ環境と Heroku アプリとの紐付けができ、環境が整ったので、これからは npm initpackage.json を生成し、サンプルアプリをコーディングしていく。

いくつか Heroku 向けの特有な設定の違いがあるので、注意点とともに紹介していく。

Express をインストールする

package.json ができたら、まずは Express をインストールする。

$ npm install --save express

ココでひとつ注意。今回の Express の場合はアプリの動作に必要なので --save オプションを使って dependencies に追加したワケだが、Heroku はデプロイ時に devDependencies に書かれているパッケージを無視するという仕様に注意が必要だ。

例えば Angular CLI で作成したプロジェクトは、デフォルトでは typescript などは devDependencies に追加されているが、この状態では Heroku 上で ng build コマンドによるビルドが失敗してしまうことになる。devDependencies のパッケージ群がインストールされないから、Heroku 上にトランスパイラがない状態になっているワケだ。

Heroku にデプロイする Node.js プロジェクトは、devDependencies の使い方に十分注意が必要ということである。

サンプルコードを実装する

Express をインストールしたら、サンプルコードを実装する。プロジェクトディレクト位r直下に index.js を作り、以下のように実装しよう。

const express = require('express');

const app = express();

app.get('/', (req, res) => {
  console.log('Access');     // コンソール出力
  res.send('Hello World!');  // ブラウザでのアクセス時に画面に表示されるモノ
});

// サーバ起動
const server = app.listen(process.env.PORT || 8080, () => {
  const host = server.address().address;
  const port = server.address().port;
  console.log(`Example app listening at http://${host}:${port}`);
});

サーバのポートは process.env.PORT || 8080 と記述しておくことで、環境変数での指定があればそのポートで、なければ 8080 で起動するようにしてある。

サンプルコードはコレで終わり。

npm start でサーバが起動するようにする

Heroku にデプロイした Node.js プロジェクトは、package.json 内の start コマンドを自動的に実行してアプリを起動してくれるので、今回は index.js を起動するスクリプトを記述しておこう。

"scripts": {
  "start": "node index.js"
}

コレだけ。

package.jsonengines を記述する

最後に、Heroku 上で使用する Node.js および npm のバージョンを指定する必要があるので、package.jsonengines プロパティを記述しておく必要がある。バージョン番号は x を使用して曖昧指定もできるので、現行の最新メジャーバージョンである Node.js v10、npm v6 系を指定しておくことにする。

"engines": {
  "node": "10.x",
  "npm": "6.1.x"
}

ということで、最終的に出来上がった package.json の内容は以下のとおり。Heroku に Node.js プロジェクトをデプロイする際は、この記述が最低限必要になるということである。

{
  "name": "example-app",
  "private": true,
  "scripts": {
    "start": "node index.js"
  },
  "dependencies": {
    "express": "4.16.4"
  },
  "engines": {
    "node": "10.x",
    "npm": "6.1.x"
  }
}

Heroku にデプロイする

ソースを作ったので、Git にコミットしておく。Heroku へのデプロイは、git push するだけで自動的に開始される。

Heroku への Git Push は、先程 git remote add したとおり、$ git push heroku master といった形で Push できる。以下、実際にコマンドを叩いてみた様子だ。

$ git push heroku master
Counting objects: 9, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (9/9), done.
Writing objects: 100% (9/9), 2.59 KiB | 331.00 KiB/s, done.
Total 9 (delta 1), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Node.js app detected
remote:
remote: -----> Creating runtime environment
remote:
remote:        NPM_CONFIG_LOGLEVEL=error
remote:        NODE_ENV=production
remote:        NODE_MODULES_CACHE=true
remote:        NODE_VERBOSE=false
remote:
remote: -----> Installing binaries
remote:        engines.node (package.json):  10.x
remote:        engines.npm (package.json):   6.1.x
remote:
remote:        Resolving node version 10.x...
remote:        Downloading and installing node 10.13.0...
remote:        Bootstrapping npm 6.1.x (replacing 6.4.1)...
remote:        npm 6.1.x installed
remote:
remote: -----> Building dependencies
remote:        Installing node modules (package.json)
remote:        added 48 packages from 36 contributors and audited 121 packages in 4.962s
remote:        found 0 vulnerabilities
remote:
remote:
remote: -----> Caching build
remote:        - node_modules
remote:
remote: -----> Pruning devDependencies
remote:        audited 121 packages in 0.917s
remote:        found 0 vulnerabilities
remote:
remote:
remote: -----> Build succeeded!
remote: -----> Discovering process types
remote:        Procfile declares types     -> (none)
remote:        Default types for buildpack -> web
remote:
remote: -----> Compressing...
remote:        Done: 22M
remote: -----> Launching...
remote:        Released v3
remote:        https://【アプリ名】.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/【アプリ名】.git
 * [new branch]      master -> master

git push 後、リモート (Heroku) のログが表示される。Node.js app detected と最初に表示されているとおり、Push したソースの中に package.json があれば自動的に Node.js プロジェクトとして扱ってくれる。

次に、engines.node (package.json): 10.x と表示されているように、package.json の記述から使用する Node.js・npm のバージョンを特定し、Installing node modules (package.json) と表示されているとおり npm install 相当の処理を行ってくれる。この時に devDependencies のパッケージはインストールされない、というところが、前述の注意である。

その後、Launching... 表示のあたりで、npm start コマンドを見つけて実行してくれている。最後に https://【アプリ名】.herokuapp.com/ deployed to Heroku と表示されているように、コレでこの URL にアクセスすれば自作の Express サーバが動いている様子が確認できるワケだ。試しにアクセスしてみて、「Hello World」と返されることを確認してみよう。

Jenkins なんかだったら npm installnpm start は「自動実行したいモノ」として自分で書かないと動いてくれなかったが、Heroku は至れり尽くせり。これは便利である。

今回はものすごく簡素な Web サーバを立ち上げてみたが、次は Angular アプリをデプロイしてみたり、PostgreSQL を導入して DB を扱ってみたりしようと思う。