Herokuにsocket.ioサーバを立ち上げる

投稿日
Herokuにsocket.ioサーバを立ち上げる

socket.ioのサーバをリモートで動かして技術検証がしたい。

サクッと動かせるsocket.ioに対応したサーバがないかな、と調べた時Herokuが対応している事を知りました。


Herokuの魅力としては制約はあるものの、なんといっても無料でsocket.ioサーバを試す事が出来るというところ!



この記事ではHerokuでsocket.ioのサーバを動かす方法を記載します。

検証した環境

1 heroku 7.60.2

ローカル環境を作成

まずローカルでsocket.ioサーバを立ち上げられるようにします。




以前書いた以下の記事のコードを使用します。



本題とそれるため要点のみ記載していきます。



まずsocket.ioサーバを動かすのに必要なパッケージを追加

$ yarn add express socket.io

app.js にsocket.ioを用いたsocket通信を行えるようにし、

app.js
const express = require('express')
const app = express()
const http = require('http')
const server = http.createServer(app)
const { Server } = require('socket.io')
const io = new Server(server)
 
const port = process.env.PORT || 8000
 
app.get('/', (req, res) => {
  res.sendFile(__dirname + '/index.html')
})
 
io.on('connection', socket => {
  console.log('a user connected')
 
  socket.on('my-event-a', message => {
    console.log(`from client. ${message}`)
    // 送信元も含めすべてのsocketに対してメッセージを送信する
    io.sockets.emit('my-event-b', `from server. ${message}`)
  })
})
 
server.listen(port, '0.0.0.0', (err, _) => {
  if (err) throw err
  console.log(`Example app listening on port ${port}`)
})


Herokuでの確認をしやすくするため、socket.ioでの通信を行えるhtmlファイルも追加します。

index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>socket.io sample</title>
    <script src="/socket.io/socket.io.js" ></script>
    <script src="https://code.jquery.com/jquery-1.11.1.js" ></script>
    <script>
      var socket = io();
 
      $(function(){
        $('#form').submit(function(){
          // inputに入力した内容を my-event-a という名前のイベントを送る
          socket.emit('my-event-a', $('#input').val());
          $('#input').val('');
          return false;
        });
 
        // my-event-b という名前のイベントを受け取ったら li を作る
        socket.on('my-event-b',function(msg){
          $('#messages').append($('<li>').text(msg));
        });
      });
    </script>
</head>
<body>
<ul id="messages"></ul>
<form id="form">
    <input id="input" autocomplete="off" /><button>Send</button>
</form>
</body>
</html>


npm-scripts で動くようにしておきます

package.json
"scripts": {
  "serve": "node app.js"
},


この状態でyarn run serveでサーバを起動すればsocket通信が試せる状態になり、

http://localhost:3000/ にアクセスするかPostmanを使う事で簡単に試す事が出来ます!



以前の記事の動画そのまま貼っちゃいますが、

以下のようにPostmanでもsocket.ioを用いた通信が確認出来ます。



Herokuにデプロイする

Herokuが公式でsocket.ioを用いたサーバをデプロイする方法の記事を公開しています。

Node.js での Heroku の WebSocket の使用 | Heroku Dev Center


せっかくなので上記記事を参考にしつつ進めます。



Heroku CLIの用意

CLIを用いた方法が書かれているので、せっかくなのでHerokuのCLIを使ってみます。


CLIのインストール方法は同じく公式ページに記載があります

Heroku スターターガイド (Node.js) | Heroku Dev Center

$ brew install heroku/brew/heroku


インストール出来た事を確認

$ heroku -v
   Warning: Our terms of service have changed: https://dashboard.heroku.com/terms-of-service
heroku/7.60.2 darwin-x64 node-v14.19.0

warningが出ていますが、とりあえずインストールが出来たようなので先に進めます。



CLIでログインする

CLIとアカウントを紐付けるためCLIでログインします。

ログインが成功すると 「Logged in as <メールアドレス>」 というメッセージが表示されます。

# 実行して何かキーを謳歌するとブラウザが開いてログインすると Logged in メッセージが表示される
$ heroku login
heroku: Press any key to open up the browser to login or q to exit:
・・・
Logged in as <メールアドレス>


アプリをデプロイする

デプロイの仕方は公式のやり方を参考にします

Heroku スターターガイド (Node.js) | Heroku Dev Center



まずHerokuにアプリを作成します。

$ heroku create
Creating app... done,  sharp-xxxxxx-12345
・・・

このコマンドを実行するとコマンドを叩いたリポジトリとHerokuのアプリケーションが連携出来るようになります。



Heroku でアプリを作成すると、Heroku でソースコードを受け取ることができるよう準備できます。


アプリを作成すると、heroku​ という名前の git リモートリポジトリも作成され、ローカルの git リポジトリと関連付けられます。


公式で↑のように書かれていて、

Gitコマンドを確認すると確かに「heroku」というremoteブランチが出来ている事が分かります。

git remote -v
heroku	https://git.heroku.com/sharp-xxxxxx-12345.git (fetch)
heroku	https://git.heroku.com/sharp-xxxxxx-12345.git (push)
origin	ssh://git@github.com/yuki-takara/xxxx.git (fetch)
origin	ssh://git@github.com/yuki-takara/xxxx.git (push)


Procfileを追加

Herokuでは、プロジェクトのルートフォルダに Procfileを追加する事でHerokuにpushしたアプリケーションが起動時に実行するコマンドを指定することが出来ます。


詳細な説明は端折ってしまいますが、

今回は以下のように書く事でyarn run serveが実行されてsocket.ioサーバが起動します。

Procfile
web: yarn run serve



ここまで出来たらherokuにデプロイします!

「Verifying deploy… done.」と表示されれば成功です。

$ git push heroku main
・・・
remote: Verifying deploy... done.



最後にHerokuでsocket.ioを実施する記事に戻ります。

Node.js での Heroku の WebSocket の使用 | Heroku Dev Center


すると「セッションアフィニティ」というものを有効にするように、と書かれているため有効にします

$ heroku features:enable http-session-affinity
Enabling http-session-affinity for  sharp-xxxxxx-12345... done



ここまで実行してデプロイされたであろうURLを開くと

Herokuのエラーページ

おっと、、エラーが、、、



エラーの対応

エラーの確認は上記画像に書かれているようにherokuのコマンドで確認が出来ます

$ heroku logs --tail
・・・
Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 60 seconds of launch

↑のようなエラーメッセージが出ていました。


調べてみるとアプリケーションで設定しているポートがHerokuが設定するポートと違うのが問題の模様。



これは1行変更する事で対応が出来ました!

const port = process.env.PORT || 3000

Herokuではprocess.env.PORTにHerokuが設定しているポート番号が環境変数で流れてくるんでしょうね。



これで再度デプロイするとページが開けるようになります!

↑ めちゃくちゃ分かりづらいんですが、

  • 左: Postnam
  • 右: Herokuにデプロイしたwebページ

です。



動画の8,9秒あたりでPostmanから投稿するとHerokuにデプロイしたwebページでもsocket通信を通じてメッセージを受信出来ていることが確認出来ます!

プロフィール画像
Yuki Takara
都内でフリーランスのエンジニアをやってます。フロントとアプリ開発メインに幅広くやってます。