クモのようにコツコツと

フロントエンドエンジニア イイダリョウの技術ブログ。略称「クモコツ」

【Express】heroku configでHerokuに環境変数を設定(.envファイルとHerokuの同期)

Expressの続きです。前回はHerokuアプリをローカル環境で表示できるようにしました。その際に環境変数やPATHについて調べました。今回は、Herokuの中に環境変数を設定して、その値をブラウザに表示してみます。heroku configコマンドを使います。それではいきましょう!

【目次】

※参考:前回記事
【Express】環境変数とは?PATHを通すとは?けっきょく南極ローカルインストール!(Herokuコマンドでローカル起動) - クモのようにコツコツと

※参考:Node.js / Expressを習得するためにやったことまとめ qiita.com

前回のおさらい

Herokuコマンドのheroku local webでローカル起動しようとしたらエラー。NODE_PATHの環境変数を設定し、PATHを通した。それでもうまくいかず、ExpressとEJSをローカルインストールしたら起動できた。 f:id:idr_zz:20200922163851j:plain

※参考:【Express】環境変数とは?PATHを通すとは?けっきょく南極ローカルインストール!(Herokuコマンドでローカル起動) - クモのようにコツコツと

今回はOSではなくHerokuアプリの中に環境変数を設定し、そこから値を呼び出したい。

環境変数の設定

Herokuの環境変数の設定はこのチュートリアルを参考に進める。

※参考:Heroku スターターガイド (Node.js) | Heroku Dev Center

※参考:設定と環境設定 | Heroku Dev Center

ターミナルで環境変数を表示(heroku config)

まず、ターミナルで環境変数を表示してみる。

cdコマンドで前回作った「node-js-getting-started」フォルダに移動。

$ cd /(パス)/node-js-getting-started

環境変数の表示はheroku configというコマンド

$ heroku config

結果:表示された!

=== aqueous-mountain-80366 Config Vars
TIMES: 2

環境変数TIMES2という値が設定されている。

アプリフォルダ直下の「.env」ファイルを見ると同じ値が設定されている。

TIMES=2

ちなみにenvとはenvironment(環境)の略のようだ。

※参考:https://wa3.i-3-i.info/word11209.html

環境変数の値を変更と追加(:set)

次に環境変数の値を変更してみる。:setで変更できる。

$ heroku config:set TIMES=10

結果:TIMESの値が10に上書きされた!

Setting TIMES and restarting ⬢ aqueous-mountain-80366... done, v6
TIMES: 10

次に新規の環境変数を追加してみる。新規追加も:setでOK。

$ heroku config:set NAME=イイダリョウ

結果:追加された!

Setting NAME and restarting ⬢ aqueous-mountain-80366... done, v7
NAME: イイダリョウ

環境変数の一部を表示(:get)

再度、環境変数の一覧を表示してみる。

$ heroku config

結果:二つとも表示される。

=== aqueous-mountain-80366 Config Vars
NAME:  イイダリョウ
TIMES: 10

一部の環境変数だけ表示したい場合は:getで変数名を指定

heroku config:get NAME

結果:NAMEの値だけ表示された!

イイダリョウ

heroku configは.envファイルではなくHerokuに反映される

先ほどの「.env」ファイルを見てみるが、環境変数は最初と変わってない。

TIMES=2

クラウド上のHerokuの環境変数が変わっているようだ。

アプリのSettingsを下にスクロールし、「Config Vars」の「Reveal Config Vars」を押すと f:id:idr_zz:20200929070401j:plain

環境変数TIMESNAMEが設定されている! f:id:idr_zz:20200929070042j:plain

なお、環境変数はここでも編集が可能のようだ。

heroku-configでHerokuの環境変数と.envファイルを同期

ローカル起動時は環境変数表示はローカル上の.envファイルの値が読み込まれるため、クラウド上のHerokuの環境変数と.envファイルを同期したい。

調べるとデフォルトのコマンドでは用意されておらず、「heroku-config」というプラグインを追加するとできるようになるようだ。

※参考:[Heroku] .envファイルで環境変数を設定・管理する | エンジニアもどきの技術メモ

「heroku-config」をインストールするコマンド

heroku plugins:install heroku-config

Herokuの環境変数を.envに同期するコマンド

heroku config:pull

結果:コピーされた!が、TIMESの値は2のまま。

# this file was created automatically by heroku-config

NAME="イイダリョウ"
TIMES="2"

これは上書きの事故を防止するため、既存の変数の場合値はコピーされない仕様らしい。

値も上書きしたい場合は--overwriteオプションを追加する。

heroku config:pull --overwrite

結果:値も上書きされた!

# this file was created automatically by heroku-config

NAME="イイダリョウ"
TIMES="10"

逆に.envファイルの内容をHerokuに同期するにはheroku config:pushコマンドを使うようだ。

Expressで環境変数をブラウザに表示

次にローカル環境で環境変数を表示したい。

index.jsでExpressの設定を変更

チュートリアルを参考にExpressでブラウザに環境変数を表示する設定をする。

※参考:Heroku スターターガイド (Node.js) | Heroku Dev Center

express()の下に繋がっているメソッドチェーンに下記の処理を追加

.get('/times', (req, res) => res.send(countHitsuji()))
  • `.get()メソッドを実行
  • 第一引数はパスで/times
  • 第二引数は無名関数で引数は左からreqres
    無名関数の処理:res.send()メソッドで関数countHitsuji()の結果を返す

.get()メソッドはGET通信の実行。res.send()`は汎用的なデータをレスポンスで返す。

※参考:Express事始め(インストール〜ハローワールドまで) - クモのようにコツコツと

環境変数の値の回数分for文でループする

countHitsuji()の内容

countHitsuji = () => {
    let result = ''
    const times = process.env.TIMES || 5
    for (i = 0; i < times; i++) {
      result += i + ' '
    }
    return result;
  }
  • 変数resultを設定。値は空
  • 変数timesprocess.env.TIMESまたは5
  • for文でiを0からtimesの数まで繰り返す
    resultiと半角スペースを追記
  • returnresultを返す

process.envで環境変数TIMESにアクセスしている。

const times = process.env.TIMES || 5

※参考:設定と環境設定 | Heroku Dev Center

||(または)で5を設定しているのは環境変数がない場合の保険のようだ。

ブラウザで環境変数を表示する

ブラウザで確認する。Herokuアプリをローカル起動

$ heroku locak web

※参考:【Express】環境変数とは?PATHを通すとは?けっきょく南極ローカルインストール!(Herokuコマンドでローカル起動) - クモのようにコツコツと

パスで指定した/timesを開くと

http://localhost:5000/times

0〜9までの表示が表示された! f:id:idr_zz:20200929070026j:plain

テキストをループしてみる

timesのfor文の処理を改造。

countHitsuji = () => {
    let result = ''
    const times = process.env.TIMES || 5
    for (i = 0; i < times; i++) {
      result += '羊が' + i + '匹 '
    }
    return result;
  }

先ほどはiの数値のみだったが「羊がi匹 」というテキストにしてみる。

ホットリロードの方法がわからないので一旦Control + CでHerokuを閉じて、再起動

$ heroku locak web

テキストに変更された! f:id:idr_zz:20200929070032j:plain

Expressのコード全体

index.js

const express = require('express')
const path = require('path')
const PORT = process.env.PORT || 5000

express()
  .use(express.static(path.join(__dirname, 'public')))
  .set('views', path.join(__dirname, 'views'))
  .set('view engine', 'ejs')
  .get('/', (req, res) => res.render('pages/index'))
  .get('/times', (req, res) => res.send(countHitsuji())) // ←追記
  .listen(PORT, () => console.log(`Listening on ${ PORT }`))

  // ↓追記:countHitsuji()
  countHitsuji = () => {
    let result = ''
    const times = process.env.TIMES || 5
    for (i = 0; i < times; i++) {
      // result += i + ' '
      result += '羊が' + i + '匹 '
    }
    return result;
  }

追記したのは下記の2つ

  • express()のメソッドチェーンの.get()/timesへのリクエストに対してcountHitsuji()の結果を返す
  • その下のcountHitsuji()関数。process.env.で環境変数TIMESの値を読み込み、その回数分for文をループ

その他のExpressの基本的な処理はこちらを参照。

※参考:Express事始め(インストール〜ハローワールドまで) - クモのようにコツコツと

Herokuにデプロイ

gitコマンドでデプロイ

次に、クラウド上のHeroku上でもこの画面を表示したい。前回の手順でgitコマンドでアップする。

※参考:【Express】環境変数とは?PATHを通すとは?けっきょく南極ローカルインストール!(Herokuコマンドでローカル起動) - クモのようにコツコツと

git add .
git commit -m "環境変数設定を追加"
git push heroku HEAD:master

すると…

エラー発生!

デプロイされず、下記のエラーが発生!

 ! [remote rejected] HEAD -> master (pre-receive hook declined)
error: failed to push some refs to 'https://git.heroku.com/aqueous-mountain-80366.git'

! [リモート拒否] HEAD->マスター(受信前フックが拒否されました) エラー:一部の参照を「https://git.heroku.com/water-mountain-80366.git」にプッシュできませんでした

ふむう。Herokuさんに拒否されてしまった。。

エラーの原因を調べる

ターミナルのメッセージに下記のトラブルシューティングのURLが示されていた。

※参考:Troubleshooting Node.js Deploys | Heroku Dev Center

読んでみるとここが当てはまるかも

Make sure the lockfile is up to date
If a lockfile is present (ie. package-lock.json or yarn.lock) checked into the app’s repository, make sure that the lockfile is both up to date and that the changes are checked into git.

(和訳)

ロックファイルが最新であることを確認してください
ロックpackage-lock.jsonファイルが存在する場合(つまり、またはyarn.lock)、アプリのリポジトリにチェックインされている場合は、ロックファイルが最新であり、変更がgitにチェックインされていることを確認してください。

対処法はnpm installか。

npm
In order to update the package-lock.json, run npm install and check in the changes to the file to git.

(和訳)

npm
更新するためにはpackage-lock.json、実行npm installしてgitのにファイルへの変更をチェックイン。

エラーメッセージの中にもそれに該当する内容がある。

 npm ERR! cipm can only install packages when your package.json and package-lock.json or npm-shrinkwrap.json are in sync. Please update your lock file with `npm install` before continuing.

npm ERR! cipmは、package.jsonとpackage-lock.jsonまたはnpm-shrinkwrap.jsonが同期している場合にのみパッケージをインストールできます。 続行する前に、ロックファイルを npminstallで更新してください。

npm installでモジュールを再インストール(デプロイ成功!)

npm installを実行してみる。

npm install

Herokuさんへデプロイ、リベンジ!

git add .
git commit -m "環境変数テストを追加"
git push heroku HEAD:master

次はエラーが起きず、成功したっぽい!

ブラウザで確認。表示された! f:id:idr_zz:20200929070047j:plain

※参考:https://aqueous-mountain-80366.herokuapp.com/times

最後に

ということで、ローカルの.envファイルとHerokuの環境変数を同期して、ローカル環境でもクラウドのHeroku上でも環境変数の値を呼び出してブラウザに表示することができました!

次は、ブラウザ側からFetch APIを使ってリクエストして、それに対して環境変数の値を返すというのをやってみたく思います。

それではまた!


※参考:Node.js / Expressを習得するためにやったことまとめ qiita.com