Azure Cloudflare

cloudflared をPythonでコンテナーに実装する

はじめに

cloudflared をPythonでコンテナーに実装する方法を紹介します。前回のPythonへの実装の続きです。

cloudflared を Pythonで実装する - 技術的な何か。
cloudflared を Pythonで実装する - 技術的な何か。

はじめに cloudflared はCloudflareが提供するサービスで無償で登録なしに利用できるトンネリングのサービスです。 そこでPythonに実装する方法を紹介します。 例えば、これを利用す

level69.net

これは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を取得して収集する方法も検討できるかと思います。

手軽にコンテナーで実装したい人向けの方法でした。

-Azure, Cloudflare
-