ラズパイ上のPython+FlaskローカルWebサーバにネットからngrok経由でアクセス
ラズパイ上で立てたローカルサーバに手軽にインターネットからアクセスしたい
ラズパイ(Raspberry Pi)上に立てたサーバに一時的に外からアクセスできるようにする方法です。
昔はルータのポートを開けたりしていたのですが、ネットワーク環境によっては繋げなかったり、セキュリティ的にも不安だったりするので、何か良い方法ないかなと思っていたのですが、ngrokという便利なものがありました。
イメージ的には以下のようにngrokサーバがローカルサーバとネットをいい感じに中継してくれる感じのようです(あんまりネットワーク詳しくないので間違ってたらすみません)。
ブラウザ -> Internet -> ngrokサーバ -> ローカルサーバ(ラズパイ)
これを使えば手軽にサーバを構築することができそうです。無料である程度使えるので、長期間の運用する前の、ちょっとしたデモやPoCにピッタリですね。
Python+FlaskでローカルWebサーバ構築
ラズパイ側のローカルサーバですが、Python+Flaskでサクッと用意します(もちろんApache2とかでもOKです)。
ここからは、ラズパイのターミナルで実行していきます。まずは、以下コマンドでFlaskをインストールします。
$ python -m pip install flask
続いてapp.py
というファイルを作成します。中身はflask公式のサンプル(flaskのhello world)とします。
具体的なコードは以下です。
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'Web App with Python Flask!'
app.run(host='0.0.0.0', port=5000)
上記コードは、ポートだけport=81
からport=5000
に変更しています。81
のままだと自分の環境では、このあとプログラムを実行するとpermission denied
のエラーが発生したためです。実行コマンドにsudo
をつければ81
でも実行できますが、今回は5000番のポートを使うことにしました。
あとは以下コマンド実行すると、サーバが立ち上がります(ポートを81にする場合はsudo python app.py
としてください)。
$ python app.py
これでローカルにサーバが立ち上がりました。簡単ですね。ラズパイのブラウザで以下アドレスにアクセスして確認しましょう。
http://localhost:5000
以下のように表示されたらOKです。お手軽!
ngrokのインストールと動作確認
ラズパイのターミナルで以下コマンド事項しましょう。
$ wget https://bin.equinox.io/c/bNyj1mQVY4c/ngrok-v3-stable-linux-arm64.tgz
$ tar xvzf ngrok-v3-stable-linux-arm64.tgz
$ sudo mv ngrok /usr/local/bin/
上記コマンドはRaspberry Pi OSが64bitバージョンのものです。32bitの場合はngrok-v3-stable-linux-arm64.tgz
をngrok-v3-stable-linux-arm.tgz
に置き換えれば大丈夫だと思います。
動作確認は、以下のコマンドを実行してください。
$ ngrok version
ngrok version 3.0.3
と表示されたらOKです(バージョンは実行したタイミングによっては異なるかもしれません)。
ngrokの実行
まずは以下にアクセスしてユーザー登録をしておきましょう。
以下にアクセスします。
2. Connect your account
に記載されている以下のようなコマンドをコピペしてラズパイ上で実行しましょう。
$ ngrok config add-authtoken xxxxxxxxxxxxxxxxxxx
さらにラズパイ上でngrokを実行して、トンネルを掘ります。5000
は先程立ち上げたローカルサーバのポート名です。
$ ngrok 5000
ngrokが起動すると、以下のように表示されます。
ngrok (Ctrl+C to quit)
Session Status online
Session Expires 1 hour, 59 minutes
Terms of Service https://ngrok.com/tos
Version 3.0.3
Region Japan (jp)
Latency calculating...
Web Interface http://127.0.0.1:4040
Forwarding https://e953-111-98-113-33.jp.ngrok.io -> http://localhost:5000
Connections ttl opn rt1 rt5 p50 p90
0 0 0.00 0.00 0.00 0.00
以下がトンネルが掘られていることを意味します。アドレスはngrok
を実行するたびに変化します。
Forwarding https://e953-111-98-113-33.jp.ngrok.io -> http://localhost:5000
上記のアドレス(上記の場合は https://e953-111-98-113-33.jp.ngrok.io )に、ブラウザでアクセスしましょう。ラズパイだけでなく、インターネットに繋がっているあらゆるPC・手元のスマートフォンからでも繋がります。
応用例
ちょっとした応用例をいくつか書いておきます。
Webサイトでボタンを押したらサーバで何か処理を実行
サーバー側でボタンを押したら、押したボタンに応じて何かしらサーバーで処理を行うようなプログラムの例です。
ファイルの構成は以下のようにします。
flask
├─ app.py
└─ templates
└─ index.html
app.pyの中身は以下です。app.run(host='0.0.0.0', port=5000, debug=True)
のdebug=True
はデバッグモードにしています。
from flask import Flask, render_template, request
app = Flask(__name__)
@app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
if request.form['send'] == 'left':
m = 'left'
return render_template('index.html', message=m)
if request.form['send'] == 'center':
m = 'center'
return render_template('index.html', message=m)
if request.form['send'] == 'right':
m = 'right'
return render_template('index.html', message=m)
else:
return render_template('index.html')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)
HTML側のコードは以下です。
<!DOCTYPE html>
<html>
<head>
<title>controller</title>
</head>
<body>
<p>{{ message }}</p>
<form method="POST">
<input type="submit" name="send" value="left">
<input type="submit" name="send" value="center">
<input type="submit" name="send" value="right">
</form>
</body>
</html>
以下は表示例です。ボタンを押すたびに`{{ message }}'部分が押したボタンに応じて書き変わります。
これをベースに色々応用できるのではないかなと思います。
まとめ
ラズパイ上のサーバを手軽にインターネット経由でアクセスする方法に関してまとめました。
ちょっとしたIoT的なデモにピッタリですね。
参考リンク
Discussion