tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

heroku.rst (5508B)


      1 Deploy to Heroku
      2 ================
      3 
      4 This guide describes how to deploy a websockets server to Heroku_. The same
      5 principles should apply to other Platform as a Service providers.
      6 
      7 .. _Heroku: https://www.heroku.com/
      8 
      9 .. admonition:: Heroku no longer offers a free tier.
     10    :class: attention
     11 
     12    When this tutorial was written, in September 2021, Heroku offered a free
     13    tier where a websockets app could run at no cost. In November 2022, Heroku
     14    removed the free tier, making it impossible to maintain this document. As a
     15    consequence, it isn't updated anymore and may be removed in the future.
     16 
     17 We're going to deploy a very simple app. The process would be identical for a
     18 more realistic app.
     19 
     20 Create repository
     21 -----------------
     22 
     23 Deploying to Heroku requires a git repository. Let's initialize one:
     24 
     25 .. code-block:: console
     26 
     27    $ mkdir websockets-echo
     28    $ cd websockets-echo
     29    $ git init -b main
     30    Initialized empty Git repository in websockets-echo/.git/
     31    $ git commit --allow-empty -m "Initial commit."
     32    [main (root-commit) 1e7947d] Initial commit.
     33 
     34 Create application
     35 ------------------
     36 
     37 Here's the implementation of the app, an echo server. Save it in a file called
     38 ``app.py``:
     39 
     40 .. literalinclude:: ../../example/deployment/heroku/app.py
     41    :language: python
     42 
     43 Heroku expects the server to `listen on a specific port`_, which is provided
     44 in the ``$PORT`` environment variable. The app reads it and passes it to
     45 :func:`~websockets.server.serve`.
     46 
     47 .. _listen on a specific port: https://devcenter.heroku.com/articles/preparing-a-codebase-for-heroku-deployment#4-listen-on-the-correct-port
     48 
     49 Heroku sends a ``SIGTERM`` signal to all processes when `shutting down a
     50 dyno`_. When the app receives this signal, it closes connections and exits
     51 cleanly.
     52 
     53 .. _shutting down a dyno: https://devcenter.heroku.com/articles/dynos#shutdown
     54 
     55 Create a ``requirements.txt`` file containing this line to declare a dependency
     56 on websockets:
     57 
     58 .. literalinclude:: ../../example/deployment/heroku/requirements.txt
     59    :language: text
     60 
     61 Create a ``Procfile``.
     62 
     63 .. literalinclude:: ../../example/deployment/heroku/Procfile
     64 
     65 This tells Heroku how to run the app.
     66 
     67 Confirm that you created the correct files and commit them to git:
     68 
     69 .. code-block:: console
     70 
     71    $ ls
     72    Procfile         app.py           requirements.txt
     73    $ git add .
     74    $ git commit -m "Initial implementation."
     75    [main 8418c62] Initial implementation.
     76     3 files changed, 32 insertions(+)
     77     create mode 100644 Procfile
     78     create mode 100644 app.py
     79     create mode 100644 requirements.txt
     80 
     81 The app is ready. Let's deploy it!
     82 
     83 Deploy application
     84 ------------------
     85 
     86 Follow the instructions_ to install the Heroku CLI, if you haven't done that
     87 yet.
     88 
     89 .. _instructions: https://devcenter.heroku.com/articles/getting-started-with-python#set-up
     90 
     91 Sign up or log in to Heroku.
     92 
     93 Create a Heroku app — you'll have to pick a different name because I'm already
     94 using ``websockets-echo``:
     95 
     96 .. code-block:: console
     97 
     98    $ heroku create websockets-echo
     99    Creating ⬢ websockets-echo... done
    100    https://websockets-echo.herokuapp.com/ | https://git.heroku.com/websockets-echo.git
    101 
    102 .. code-block:: console
    103 
    104    $ git push heroku
    105 
    106    ... lots of output...
    107 
    108    remote: -----> Launching...
    109    remote:        Released v1
    110    remote:        https://websockets-echo.herokuapp.com/ deployed to Heroku
    111    remote:
    112    remote: Verifying deploy... done.
    113    To https://git.heroku.com/websockets-echo.git
    114     * [new branch]      main -> main
    115 
    116 Validate deployment
    117 -------------------
    118 
    119 Let's confirm that your application is running as expected.
    120 
    121 Since it's a WebSocket server, you need a WebSocket client, such as the
    122 interactive client that comes with websockets.
    123 
    124 If you're currently building a websockets server, perhaps you're already in a
    125 virtualenv where websockets is installed. If not, you can install it in a new
    126 virtualenv as follows:
    127 
    128 .. code-block:: console
    129 
    130    $ python -m venv websockets-client
    131    $ . websockets-client/bin/activate
    132    $ pip install websockets
    133 
    134 Connect the interactive client — you must replace ``websockets-echo`` with the
    135 name of your Heroku app in this command:
    136 
    137 .. code-block:: console
    138 
    139    $ python -m websockets wss://websockets-echo.herokuapp.com/
    140    Connected to wss://websockets-echo.herokuapp.com/.
    141    >
    142 
    143 Great! Your app is running!
    144 
    145 Once you're connected, you can send any message and the server will echo it,
    146 or press Ctrl-D to terminate the connection:
    147 
    148 .. code-block:: console
    149 
    150    > Hello!
    151    < Hello!
    152    Connection closed: 1000 (OK).
    153 
    154 You can also confirm that your application shuts down gracefully.
    155 
    156 Connect an interactive client again — remember to replace ``websockets-echo``
    157 with your app:
    158 
    159 .. code-block:: console
    160 
    161    $ python -m websockets wss://websockets-echo.herokuapp.com/
    162    Connected to wss://websockets-echo.herokuapp.com/.
    163    >
    164 
    165 In another shell, restart the app — again, replace ``websockets-echo`` with your
    166 app:
    167 
    168 .. code-block:: console
    169 
    170    $ heroku dyno:restart -a websockets-echo
    171    Restarting dynos on ⬢ websockets-echo... done
    172 
    173 Go back to the first shell. The connection is closed with code 1001 (going
    174 away).
    175 
    176 .. code-block:: console
    177 
    178    $ python -m websockets wss://websockets-echo.herokuapp.com/
    179    Connected to wss://websockets-echo.herokuapp.com/.
    180    Connection closed: 1001 (going away).
    181 
    182 If graceful shutdown wasn't working, the server wouldn't perform a closing
    183 handshake and the connection would be closed with code 1006 (abnormal closure).