はじめに
cloudflared をPythonでコンテナーに実装する方法を紹介します。前回のPythonへの実装の続きです。
これはcloudflared をコンテナーに実装する場合にはCloudflare のZero Trust 機能を利用する方法が紹介されています。
しかし、Zero Trust 機能ではログインや支払いの登録などがあり気軽に利用出ません。
そこでcloudflared をPythonでコンテナーに実装することで回避します。
検証環境としてAzure Container InstancesをPravateで起動し、VNET内に作成したコンテナーを外部からアクセスできるようにしたい思います。

コンテナーの準備
用意するコンテナーはPython でWebサーバーを起動します。
準備するPythonのコードです。
import logging
import http.server
import socketserver
from http import HTTPStatus
from pycloudflared import try_cloudflare
class SilentRequestHandler(http.server.SimpleHTTPRequestHandler):
def do_GET(self):
if self.path == "/":
self.path = "/index.html"
try:
file = open(self.path[1:]).read()
self.send_response(HTTPStatus.OK)
self.send_header("Content-type", "text/html")
self.end_headers()
self.wfile.write(bytes(file, "utf-8"))
except FileNotFoundError:
self.send_error(HTTPStatus.NOT_FOUND, "File not found")
def log_message(self, format, *args):
pass
PORT = 8000
Handler = SilentRequestHandler
server = http.server.HTTPServer(("", PORT), Handler)
server.allow_reuse_address = True
logging.basicConfig(filename='server.log', level=logging.INFO,
format='%(asctime)s %(levelname)s: %(message)s')
logging.info(f"Serving on port {PORT}")
try:
logging.info("Setting up Cloudflare tunnel...")
logging.info(try_cloudflare(port=PORT))
server.serve_forever()
except KeyboardInterrupt:
logging.info("Shutting down...")
server.shutdown()
表示するindex.htmlを作成します。
<!DOCTYPE html> <html> <body> Hello World </body> </html>
Dockrfileを作成します。
FROM python:3 RUN pip install pycloudflared ADD index.html index.html ADD server.py server.py EXPOSE 8000 ENTRYPOINT ["python3", "server.py"]
ビルドします
docker build -f Dockerfile . -t web-server
これで準備は完了です。
起動確認
web-serverを起動します。
docker run -d web-server-test
コンテナのIDもしくは名前を確認します。
docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 30f96d7f8908 web-server-test "python3 server.py" 6 minutes ago Up 6 minutes 8000/tcp friendly_bhaskara
cloudflared に接続するためのURL確認します。
URLはserever.logに出力されます。
docker container exec 30f96d7f8908 cat server.log
2023-03-20 08:05:22,670 INFO: Serving on port 8000 2023-03-20 08:05:22,670 INFO: Setting up Cloudflare tunnel... 2023-03-20 08:05:26,631 INFO: Urls(tunnel='https://supplements-setup-cats-leg.trycloudflare.com', metrics='http://127.0.0.1:44557/metrics', process=<Popen: returncode: None args: ['/usr/local/lib/python3.11/site-packages/clo...>)
アクセスして確認します。

Azure Container Instances にデプロイ
デプロイするためにはDokcer Hubにアップロードします。
tagを設定します。
docker tag web-server-test jkudo/web-server-test
ビルドしたものをPushします。
docker push jkudo/web-server-test
Docker Hubの準備は完了です。
Azure Container Instancesに設定していきます。イメージソースにDocker Hubのレポジトリを指定します。

VNET内に構築します。これで外部からのアクセスは行えなくなります。

起動後にsever.logを確認します。
az container exec -g web-server-test --name web-server-test --exec-command "cat server.log"
URLを確認します。
2023-03-20 08:31:29,369 INFO: Serving on port 8000 2023-03-20 08:31:29,369 INFO: Setting up Cloudflare tunnel... 2023-03-20 08:31:33,553 INFO: Urls(tunnel='https://puerto-holmes-caps-quarters.trycloudflare.com', metrics='http://127.0.0.1:33327/metrics', process=<Popen: returncode: None args: ['/usr/local/lib/python3.11/site-packages/clo...>)
アクセスして確認します。

本文はHello World 2に変更しています。
以上のように本来外部からのアクセスが行えないリソースに対しても外部からのアクセスできるようになりました。
*サンプルの一部コードはGPT-4により生成しています
まとめ
cloudflared をPythonでコンテナーに実装する方法をAzure Container Instancesを参考に解説しました。
ユーザー登録を行う手順を省きたいがためのちょっとした手法です。
もっと上手くコードを書けば、起動時にURLを取得して収集する方法も検討できるかと思います。
手軽にコンテナーで実装したい人向けの方法でした。
