ロゴテキスト ロゴ

    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
    都内でフリーランスのエンジニアをやってます。フロントとアプリ開発メインに幅広くやってます。