量子プログラミング入門→量子コンピューティングサービス構築入門

量子コンピューター初心者の筆者が日々学びながら、量子コンピュータ上で量子プログラミングできるようなるまでの学習日記を記録していきます。 内容は量子コンピューター入門者向けで、専門家の方からするとおかしな内容があるかもしれません。その際はコメント等でお知らせください!

カテゴリ: サイト構築



AWSのLightsailはお手軽にWebサーバを立ち上げることができます。Wordpressを使う場合はイメージがあるので一瞬で立ち上げられ、bitnamiのイメージを使ってるとSSL化も一瞬でできます。(参考)
自分のサイトをAWS Light Sailで立ててSSL化するときにちょっとはまったのでメモ

構成

構成概要
ベースAWS Lightsail 
OSUbuntu20.0.4
WebサーバNginx-uWSGI-flask
SSL化letsencrypt

準備するもの

  • UbuntuとDockerは入ってる前提
  • Dockerfile
  • 各種設定(nginx.conf, uwsgi.ini, supervisord.conf, crontab)
  • flaskアプリ(app.py)

Dockerfile

FROM ubuntu:latest

RUN apt update && apt install -y nginx
RUN apt-get update
RUN apt-get install python3 python3-pip -y
RUN apt install -y certbot python3-certbot-nginx
RUN pip3 install uwsgi flask supervisor

RUN apt install -y cron ADD crontab /var/spool/crontab/root RUN crontab /var/spool/crontab/root

VOLUME ["/home"]
COPY . /work WORKDIR /work RUN rm /etc/nginx/nginx.conf RUN ln -s /home/nginx/nginx.conf /etc/nginx/nginx.conf
RUN ln -s /home/etc/letsencrypt /etc/nginx/letsencrypt RUN mv etc/uwsgi.ini /etc/uwsgi.ini RUN mv etc/supervisord.conf /etc/supervisord.conf RUN rm -rf etc
RUN rm crontab EXPOSE 80 EXPOSE 443 CMD ["/usr/local/bin/supervisord"]

ローカルディスクをマウントするために/homeを定義しておきます。certbotが生成するファイルは、dcoker image内に格納するのではなく、ローカルディスクに格納するようにしておきます。下記のディレクトリ構成をみるともうちょっとわかりやすいかもしれません。鍵生成はdockerをbuildする段階ではやらずにDockerを立ち上げてからDockerの中から行うようにしています。そのためcertbotが生成したファイルをローカルディスクに保存するようにしています。

各種設定

下記の3つの設定ファイルを用意してローカルディレクトリにetcという名前のフォルダを作っておいておきます。

ディレクトリ構成
下記のような構成でファイルを配置します
./
|
docker
| |
| +- Dockerfile
| +- crontab
| |
| +-etc/
| |
| +- uwsgi.ini
| +- supervisord.conf
|
volume
|
+- app.py
+- crontab
|
+- etc/
|
+- nginx/
| |
| +- nginx.conf
|
+- letsencrypt/

nginx.conf

worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; keepalive_timeout 65; upstream uwsgi { server localhost:3031; } server { listen 80; server_name example.com; charset utf-8; location / { include uwsgi_params; uwsgi_pass 127.0.0.1:3031; } location /static { include uwsgi_params; uwsgi_pass 127.0.0.1:3031; } } }
letsencrypt(certbot)でのSSL化においてはserver_nameをきちんと定義しておく必要があるので事前にDomainを取得しておいてください。
uwsgi.ini
[uwsgi]
wsgi-file=/home/app.py
socket=127.0.0.1:3031
callable = app
supervisord.conf
[supervisord]
nodaemon=true

[program:uwsgi]
command=/usr/local/bin/uwsgi --ini /etc/uwsgi.ini --die-on-term
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0

[program:nginx]
command=/usr/sbin/nginx -g "daemon off;"
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0

[inet_http_server] port=127.0.0.1:9001 [rpcinterface:supervisor] supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface [supervisorctl] serverurl=http://127.0.0.1:9001
let's encryptの証明書は3か月で切れるので、自動更新用のcron設定をやらないと3か月後に突然証明書が切れることになります。Dockerにcron設定をして証明書を定期的に更新するようにします。
crontab
* * * * sun certbot renew --pre-hook "/usr/local/bin/supervisorctl stop nginx" --post-hook "/usr/loca\
l/bin/supervisorctl start nginx"
cronに設定してるコマンドがかなり長いですが毎週日曜日にcertbot renewコマンドを実行するようにします。renewする前にsupervisorctlでnginxをstopし、renewした後にsupervisorctlでnginxをスタートします。これはcertbot renewが証明書を更新する際にポート80番を使うためで、nginxが立ち上がったままだと80番が競合するためです。また今回のやり方ではnginxをsupoervisord経由で起動しているので、supervisorctlでnginxを制御させます。

Flaskアプリ

ここではflaskアプリの書き方は説明しないのでめちゃめちゃシンプルなもの
app.py
from flask import Flask, render_template, request

app = Flask(__name__)

@app.route('/')
def index():
    return "Hello world!!"

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=80, debug=True)

構築手順

Docker buildコマンド

sudo docker build -t nginx-ssl .


Docker runコマンド

sudo docker run  -it --rm -p 80:80 -p 443:443 -v $(pwd)/volume:/home nginx-ssl /bin/bash

証明書作成

nginxオプションをつけておくと自動でconfファイルを更新してくれます。
certbot --nginx -d example.com

Webサーバ起動

下記のコマンドでWebサーバーを起動、ブラウザ経由でアクセスできることを確認する。
/usr/local/bin/supervisord

はまったこと

証明書がうまく作られて設定もうまくいってるようですが、SSLの通信が全く通らない。
Ubuntuの中のファイヤーウォールやホスト-Docker間のポートフォワードばかりを気にして、確認しまくっていたが、その外側のLightSailで完全に遮断されてた...
LightSail側でファイヤーウォールを開けてやらないといけない、ここが一番はまりました。
Networking Lightsail2

Lightsail + NGINX + uwsgi + flaskでサイト構築


AWSのLightsailを使ってNginx+uwsgi+flaskでwebサーバを立ち上げる方法の解説です。

Lightsailでインスタンス立ち上げ

まずAWSにログインしLightsailのコンソールに行きます

1) インスタンス選択
1
Lightsailのコンソールからcreate instanceをクリック
2

インスタンスの種類を選択します。ここではOS Onlyを選んでUbuntu20.04を選択します。
3
Ubuntuに直接入って作業することが多いのでSSH Keyをダウンロードしておきます。
4
インスタンスの種類を選びますが、あとから簡単にアップグレードできるので最初は一番小さなものでよいと思います。

2) 固定IP割り当て
5_2



3) DNS登録
本格的にサイトを立ち上げる場合はDNS登録が必要かと思いますがここでは割愛します。


4) Ubuntuへの接続
SSHでUbuntuへ接続する際は下記のように先ほどダウンロードした鍵ファイルを-iオプションで指定して接続します。
ssh -i ./LightsailDefaultKey-ap-northeast-1.pem ubuntu@54.95.xxx.xxx

Ubuntuの中の構築

Ubuntuが立ち上がって接続できるようになったところで、Ubuntuの中の構築をしていきます。

Dockerインストール

こちらの内容を参考にインストールします。

sudo apt update
sudo apt upgrade
sudo apt-get install \ apt-transport-https \ ca-certificates \ curl \ gnupg-agent \ software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -


sudo add-apt-repository \ "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) \ stable"
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io


Dockerをインストールした後、一般ユーザ(ここでは"ubuntu"というユーザー名)もdockerを使えるようにグループにつかしておきます。
sudo usermod -aG docker ubuntu

Dockerイメージの作成

nginx-uwsgi-flaskの入ったDockerイメージの作成はこちらを参考にしてください。





Auth0を試してみる

会員制サイトの立ち上げ方法の勉強のためにAuth0をを試してみる。自前でユーザーの個人情報などを抱えてしまうと管理が大変なのと万が一事故が起こった時に、めんどくさいので、無料で使えるAuth0を使って、ユーザー管理の機能を実験。

手っ取り早く始めるためのサンプルアプリケーションも公開されていて、ローカルのマシンで試すことができるので非常に便利。

サンプルコードを実行する

スクリーンショット (7)

Auth0のアカウントを作ってログインして、左のApplicationメニューを選択し、Deafult Appを選びQuick Startのタブから簡単なサンプルをダウンロードする。
Reactなどの環境が整っているとほんとに2分ぐらいでAuth0を使ったログインアプリを立ち上げられる。

スクリーンショット (3)


ここで新規ユーザー登録などもでき、順調と思ったところで...


Unhandled Rejection(Error): Unauthorized

ダウンロードしたコードには自分用のClident IDなどが埋め込まれているためエラーになるはずがないのだが、何回やっても、Reactだけでなくvueを試したり、Reactベースで自分で書いたりしてもやはりエラーになる。


スクリーンショット (5)
スクリーンショット (6)


ググってるとFailed Exchange, Unauthorizedになるのは、Application Typeの問題であるような記事を見かけるが、Application TypeをきちんとSingle Page Applicationにしてもエラーになる。
Auth0のコミュニティーをあさりまくってようやく有効な投稿に出くわす
スクリーンショット (8)

いったん、Auto0のApplicationのSettingsでApplication TypeをRegular Web Applicationに変更して、Token Endpoint Authentication MethodをNoneにしてやるとエラーが回避される。その後、Single Page Applicationに戻すとエラーは消える。Auth0の問題だと思うが、Application TypeをSingle Page Applicationにしても、Token Endpoint AuthenticationがNoneに切り替わらない場合があるのでは?(今となっては再現しなくなってしまったのでわからないが)

2分で終わるはずが4~5時間悩んでしまった...

↑このページのトップヘ