なぜやるか
webの構造を知りたい。
今回の構成
アプリケーション flask
アプリケーション実行環境 wsgi
仮想環境コンテナ Docker
webサーバ nginx
HTTPS オレオレ証明書
ファイアウォール ufw
ラズパイVNC設定
sudo apt-get update
sudo apt-get upgrade
ラズパイIP固定
sambaファイル共有
ラズパイに必要なものインストール
【docker】
docker.io
docker-compose
【FW】
ufw
【nginx】
nginx
sudo apt install -y docker.io docker-compose ufw nginx
ディレクトリ構成
ユーザーフォルダの下に次のようなフォルダ構造にします。
project
├─App2
└─kajiApp
| └─flaskr
| ├─static
| ├─templates
| └─__pycache__
└─docker-compose.yml
projectフォルダの中にアプリケーションファイル kajiApp とApp2
今回はkajiAppだけ動かします。今後アプリケーション増やしたときのためにApp2置いときます。スケールすることを想定しています。
docker-composeファイルいれてあります。
アプリはdockerで動かして nginxはコンテナの外で動かします。
フォルダ構造を作る。
アプリを作る or コピペ or git clone する。
今回はgit clone
cd /home/pcmainte/project
git clone https://github.com/arisaEN/kajiApp.git
こんなかんじになった。
Dockerfileの用意
git cloneしたものの中にはいっている。
書き換えます。
FROM python:3.9-slim
WORKDIR /app
# 必要なパッケージをインストール
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
# アプリケーションコードをコピー
COPY . .
# Gunicornを使用してアプリケーションを起動
CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:5000", "flaskr:app"]
Docker-Composeファイルの作成
Projectフォルダ下に作ったものに書き込みます。
version: '3.8'
services:
kajiapp:
build:
context: ./kajiApp
dockerfile: Dockerfile
volumes:
- ./kajiApp/flaskr/static:/app/flaskr/static
container_name: kajiapp
ports:
- "127.0.0.1:5000:5000"
networks:
- app-network
networks:
app-network:
driver: bridge
ホストマシンの127.0.0.1:5000(ローカルホスト)へのアクセスをコンテナ内のポート5000に転送します。つまり、ホストマシンの127.0.0.1:5000に接続することで、コンテナ内のFlaskアプリケーションにアクセスできるようになります。
nginx.confファイルの作成
user pcmainte;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
events {
worker_connections 1024;
}
http {
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;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 4096;
include /etc/nginx/mime.types;
default_type application/octet-stream;
include /etc/nginx/conf.d/*.conf;
upstream kajiApp {
server 127.0.0.1:5000;
}
server {
listen 80;
server_name kajiApp.example.com;
charset UTF-8;
location / {
proxy_pass http://kajiApp;
}
}
server {
listen 80;
server_name unko.com;
location / {
root /home/pcmainte/project/App2;
index index.html;
}
}
}
クライアントにDNS設定
windowsの場合
C:\windows\system32\drivers\etc\hosts ここに管理者として
100.64.16.104 kajiapp.example.com
100.64.16.104 unko.com
みたいな感じで追加 メモ帳で編集すればOK
【windowsの設定】
kajiapp.example.comにアクセスしたら100.64.16.104に行きなさいってこと。
【nginxの設定】
100.64.16.104(nginxサーバ)はkajiapp.example.comというリクエストは127.0.0.1:5000に飛ばしてkajiAppを表示させるという設定になっています。
ここまでできれば、dockerコンテナ立ち上げてアプリ稼働させて、
nginxも稼働させれば、クライアントはkajiapp.example.comとブラウザで入力すればnginxを通してコンテナアプリに接続できます。
テストとして、コンテナ立ち上げてみます。
コンテナ立ち上げ
cd project
sudo docker-compose up --build
nginxサーバ(ラズパイ)から接続するとつながるはずです。
ブラウザで、 127.0.0.1:5000 enter
繋がりました。クライアントからhttp://100.64.16.104:5000/ には接続できないようにdockerfileとcomposeファイルで設定してあります。
クライアントはnginxを通してdockerコンテナにアクセスさせるためです。
でお次は↓HTTP通信をHTTPS通信にします。
HTTPSの設定
今回は自己証明書を使います。通称:オレオレ証明書
nginxサーバで証明書を作って、クライアントには証明書をインストールしてもらいます
↓設定手順
nginxサーバー上で実行
mkdir -p ~/ssl-certs
cd ~/ssl-certs
/home/pcmainte/ssl-certs ここに鍵生成されます
ここからこちらの記事参照
一応本記事でもメモしていますが、こちらの見やすい記事とやっていることは同じです。
ここに
subjectnames.txt を作る
中身↓
subjectAltName = DNS:kajiapp.example.com, IP:127.0.0.1
秘密鍵の生成
openssl genrsa 2048 > server.key
証明書署名要求(CSR)の作成
openssl req -new -key server.key -subj "/C=JP/ST=Some-State/O=Some-Org/CN=kajiapp.example.com" > server.csr
パスワード 任意 覚えとく
国コード JP
Province 都道府県名 空白でOK
Locality 市区町村名 空白でOK
Organization 組織名
Organizational Unit 部署名
Common Name 証明書を使いたいFQDN 今回は kajiapp.example.com
メールアドレス
challenge password 空白でOK
optional company name 空白でOK
自己署名証明書の作成
openssl x509 -days 3650 -req -extfile subjectnames.txt -signkey server.key < server.csr > server.crt
秘密鍵(private.key)が暗号化されている場合に表示されます。秘密鍵を生成する際に設定したパスフレーズを入力する
Certificate request self-signature ok
証明書署名要求(CSR)の自己署名が正常に完了したということ。
証明書確認
openssl x509 -in server.crt -text -noout
nginxの設定
nginxの設定ファイルに HTTPS接続設定をする
↑の方で設定したnginxのファイルに追記します。
sudo nano /etc/nginx/nginx.conf
user pcmainte;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
events {
worker_connections 1024;
}
http {
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;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 4096;
include /etc/nginx/mime.types;
default_type application/octet-stream;
include /etc/nginx/conf.d/*.conf;
upstream kajiApp {
server 127.0.0.1:5000;
}
server {
listen 443 ssl;
server_name kajiapp.example.com;
ssl_certificate /home/pcmainte/ssl-certs/server.crt;
ssl_certificate_key /home/pcmainte/ssl-certs/server.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384';
location / {
proxy_pass http://kajiApp;
}
}
server {
listen 80;
server_name kajiApp.example.com;
charset UTF-8;
location / {
proxy_pass http://kajiApp;
}
}
server {
listen 80;
server_name unko.com;
location / {
root /home/pcmainte/project/App2;
index index.html;
}
}
}
nginxを再起動
sudo systemctl restart nginx
ブラウザでHTTPS接続
現状だとまだ保護されていない通信となる。 これは、HTTPS通信できてるけど、証明書がブラウザに認証されていなくて疑われている状態。
疑いを晴らす作業をしていきます。
windowsならばnginxサーバに作った/home/pcmainte/ssl-certs/server.crt これをコピーしてwindowsのローカルにいれる。
ローカルコンピューター
証明書をすべて次のストア
参照
信頼されたルート証明書
インストール終わったら再度 https://kajiapp.example.com/ に接続。
完了。
UFWの設定
アクセスする必要のないポートは閉じて、脅威からデバイスを守りましょう。
ポート開放
上から順に
HTTP
HTTPS
VNC
ssh
sambaを使ったクライアントからのファイル共有・操作
sudo ufw allow 80
sudo ufw allow 443
sudo ufw allow 5900/tcp
sudo ufw allow OpenSSH
sudo ufw allow from any to any port 137,138,139,445 proto tcp
sudo ufw allow from any to any port 137,138,139,445 proto udp
ファイアウォールを有効化(未有効の場合)
sudo ufw enable
docker コンテナ自動起動設定
サーバーのコンソールで打つ。
docker update --restart=always kajiapp
参考
感想
◎クライアント側の課題
クライアントはURLを貼り付けるだけでアプリを見れる環境を作りたい。
現状クライアント側の操作は:
①サーバの自己証明書をクライアントにインストール。
②URLに対するサーバのIPアドレスをアプリごとにhostsファイルに書き込み。
③URLをブラウザに貼る。
①と②をなくすためになにか考えるのが今の課題。
◎サーバー側の課題
アプリごとに証明書を発行しなければいけないのが面倒。
自分用メモ
nginx , docker , nanoで使ったコマンドまとめです。
nginx設定ファイル
sudo nano /etc/nginx/nginx.conf
nginx起動
sudo systemctl start nginx
Nginx を有効化(自動起動設定)
sudo systemctl enable nginx
nginx再起動
sudo systemctl restart nginx
Nginx の動作確認コマンド
sudo systemctl status nginx
ポート仕様状況確認
sudo lsof -i :80
nginxダウン
sudo systemctl stop nginx
ログのパス
/var/log/nginx
nginxの設定ファイル
/etc/nginx
起動コンテナ一覧
sudo docker ps
起動・停止コンテナ一覧
sudo docker ps -a
コンテナ削除
docker rm 6c796c021e54
dockerコンテナ起動
sudo docker-compose up --build
docker の中見る
sudo docker exec -it 1b8a90a5fb4e /bin/bash
dockerのなかのフォルダ確認
ls -l /app/flaskr/static/
docker exec コマンドを実行するには、現在のユーザーが docker グループに属している必要があります。
sudo usermod -aG docker pcmainte
コンテナ内の /app/flaskr/static/ にアクセスする権限付与
sudo docker exec -it kajiapp bash
ls -ld /app/flaskr/static/
chmod -R 755 /app/flaskr/static/
nanoエディタ
1行切り取り 削除にも使える
Ctrl K
1行コピー
Alt ^
HTTPS設定
sudo nano /usr/lib/ssl/openssl.cnf