TL; DR
http://localhost:8000へのリバースプロキシ設定を行いましょう。
はじめに
Rocketと呼ばれる、RustのWebアプリケーションフレームワークが存在します。
また、Rocketを用いたWebサーバ構築手法についての記述ページも多く存在します。
RustのRocketでWebアプリケーションを作ってみる
https://qiita.com/hhatto/items/b118442051a67babcc0dRust RocketでのWebAPIサーバーの書き方を解説してみる
https://qiita.com/yukinarit/items/c5128e67d168b4f39983
しかし、どのサイトを見ても実際にポート番号80で一般公開する手法が存在しませんでした。
RocketのWebサーバ構築手法では、ポート番号8000でローカル上に構築し、構築したページを確認する(いわゆるhttp://localhost:8000)までに留まっています。
また、GCPのようなクラウドシステム上で構築する場合、そもそもローカル上での確認手法自体がわからないという問題点もあります。
ここでは、表題の通り、GCPでNginxを利用してRocketによるWebサーバを一般公開する手法について記します。
Nginxを使いたくない場合
おまけ:Nginxを使わない場合の問題点(未解決)の節を参照してください。
以外と難しいことがわかります。
GCPにおけるGCEの構築
これは数多くの他サイトで紹介されているため、あまり野暮な詳細説明は省きます。
下記サイトの「Google Compute Engineインスタンスを作成する」節を参考にしました。
【クラウド初心者向け】Google Cloud Platform(GCP)でWebサイトを公開してみよう!
http://yebisupress.dac.co.jp/2018/08/23/publish_website_with_google-cloud-platform/
また、僕はUbuntu18.04を使ったため、以降のコマンドなどが異なる場合があります。
その際は適宜読み替えてください。
注意点としては、インスタンス作成時にファイアウォールとして「HTTPトラフィックを許可する」と「HTTPSトラフィックを許可する」の両方にチェックを入れることです。
せっかくなのでHTTPSでも通信したいですよね。
恐らくここでチェックを入れなくても、後で設定すればできるようになると思います。
また、構築したGCEとSSH通信する手法については、下記サイトを参考にしました。
【GCP入門編・第3回】難しくない! Google Compute Engine (GCE) でのインスタンス起動方法!
https://www.topgate.co.jp/gcp03-google-compute-engine-launch-instance
……後半に、Nginxのインストール方法をちゃっかり書いてますね。
僕が最初に見た際は、Nginxを使うという発想がそもそもなかったため見てませんでした。
RustおよびRocketのインストール
これについても多くは語りません。
下記サイトを参考にしました。
UbuntuにRustをインストールする
https://qiita.com/yoshiyasu1111/items/0c3d08658560d4b91431Getting Started – Rocket Programming Guide
https://rocket.rs/v0.4/guide/getting-started/
注意点としては、ちゃんとupdateとupgradeをしましょう!ってことくらいです。
Rust: error: could not exec the linker cc: No such file or directory
https://qiita.com/Morix1500/items/f4a71a037bd267ef62d7
……はい、僕はしっかり引っかかりましたよ。
Rocketの動作確認
ここが本題1です。
GCEインスタンスに別のコンソールからSSH接続してください。
全く同じユーザで構いません。
そこで、下記curlコマンドを叩けば、動作確認ができます。
curl http://localhost:8000
……言われてみたらその通りですよね。
僕は上記の発想に至るまで1日かかってしまいました。
NginxのインストールおよびHTTPS接続設定
これについても省略します。
下記サイトを参考にしました。
GCP(GCE)にNode.jsアプリケーションをデプロイする
https://qiita.com/yfujii01/items/41c15d885830deea8ed1
ついでに、ドメイン取得とHTTPS接続の確認もしました。
注意点としては、外部IPアドレスを固定していない点です。
そこまで難しいことは無いと思いますが、以下の理由により行っていません。
-
- 外部IPアドレスを固定化することによる金銭的デメリットなどの把握不足
- 将来的なDNSやロードバランサなどの構築による外部IPアドレス再設定の手間
既に理解できている方は、適宜設定してください。
GCPでのIPアドレス固定化については調べたら簡単に出てくると思います。
NginxとRocketの連携
本題2であり、この記事を書いた動機でもあります。
色々調べましたが、根本原因までは理解が及んでいません。
下記サイトを参考にしました。
ASP.NET Core アプリを公開する(Nginx, CentOS 7.2) # リバースプロキシの設定
https://webbibouroku.com/Blog/Article/aspcore-centos-nginx#outline__5_3
Nginxの設定ファイルを修正します。
デフォルトではserverを中括弧で囲んだ設定が3つ存在しますが、2番目の中身を書換えます。
# 省略
server {
# 省略
}
# 省略
server {
# 省略
# 以下をコメントアウト
# root /var/www/html;
#
# # Add index.php to the list if you are using PHP
# index index.html index.htm index.nginx-debian.html;
# server_name your-domain.tld; # managed by Certbot
#
#
# location / {
# # First attempt to serve request as file, then
# # as directory, then fall back to displaying a 404.
# try_files $uri $uri/ =404;
# }
# 以下を追記
location / {
proxy_pass http://localhost:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
# 省略
}
# 省略
server {
# 省略
}
root、index、およびserver_nameの項目をコメントアウトし、location /の項目を書換えます。
location /の項目では、proxy_passをhttp://localhost:8000に設定します。
これにより、Rocketの確認時に利用したURLおよびポート番号をWebサーバ内部で利用するため、Webサーバ外部からのリクエストをlocalhost:8000にリダイレクトできます。
おまけ:Nginxを使わない場合の問題点(未解決)
Rocketのみで公開Webサーバを構築する際の問題点として、ポート番号80を受信するアプリの起動はルート権限が必要である点が挙げられます。
つまり、cargo runでのRocket実行時は、ルート権限での打上げが必要というわけです。
しかし、解決策には次のような壁が潜んでいました。
ポート番号の設定方法がわからない
cargo runで実行できるWebアプリのポート番号は、デフォルトで8000番です。
ポート番号80に変更する必要がありますが、その設定をする方法を探すのに苦労しました。
答えとしては、cargo runを実行するディレクトリにRocket.tomlファイルを置き、次のような設定を記述すればよいです。
[development]
address = "localhost"
port = 8000
log = "normal"
[staging]
address = "0.0.0.0"
port = 80
log = "normal"
[production]
address = "0.0.0.0"
port = 80
log = "critical"
上記ファイルでは、受け付けるIPアドレス、受け付けるポート番号、および出力ログファイル名を記述しています。
上記以外の設定も可能です。
各項目についてはDevelopment版、Staging版、およびProduction版として、ビルド時に次のコマンドにおけるオプションで設定できます。
ROCKET_ENV=production cargo run
RustのWebアプリ(Rocket)をHerokuにデプロイする
https://qiita.com/ovrmrw/items/b316f01f4a936fec9b85RustでWebアプリケーション作成 メモ
https://qiita.com/miyagaw61/items/1dcb2526bbc6668337b4
sudo cargo runが実行できない
sudo時に環境変数PATHを引き継いでくれない問題がありました。
この問題については解決できず、次の策に移りました。
Vagrant + CentOS7 で、RustのWebフレームワークRocketを発射する – My Favorite Things – Coding or die.
http://tobi462.hatenablog.com/entry/2016/12/30/211440
rootユーザでのcargo runが実行できない
これについては全くわかりませんでした。
Rustインストール時にnightlyの設定を忘れていたのか、あるいは別の問題だったのかは定かではありません。
調べていく途中に、次の壁にぶつかりました。
ルート権限でポート番号80を開くのは危ない
よく考えたらその通りですね。
ということで、sudo cargo runは止めて別の手法を探らなくてはなりません。
How do I run sudo cargo? : rust
https://www.reddit.com/r/rust/comments/82slu0/how_do_i_run_sudo_cargo/
おわりに
Rustの勉強をしたくて、ちょうどいい教材としてRocketがあることは数年前から知っていたのですが、公開Webサーバとして運用する手法がわからず、長期間ずっと温めていたネタが消化できました。
また、昨年公開したGoogle Assistantアプリの報酬として頂いたGCP利用料を使えるいい機会だったため、GCEを使って遊んでみました。
localhostへのリバースプロキシ設定は、他のWebアプリケーションフレームワークでも利用できそうですから、もし公開方法がわからないWebアプリケーションフレームワークを利用している方は、使ってみる1つの手法として参考にしてみてください。
負荷などの影響はわかりません。
他:参考サイト
Client Area – Freenom
https://my.freenom.com/yukinarit/rocket-webapi: Making JSON webapi server with Rust and Rocket ?
https://github.com/yukinarit/rocket-webapiDeploy Rocket using Letsencrypt and nginx
https://gist.github.com/belst/ff36c5f3883f7bf9b06c379d0a7bed9eRust Webserver
https://vishus.net/content/rust-webserverHow to deploy Rust Web Application – Steadylearner – Medium
https://medium.com/@steadylearner/how-to-deploy-rust-web-application-8c0e81394bd5