Cloudflare TunnelをDockerで使うための設定
手ごろなセルフホストコンテナ環境を作るために、Docker Swarmを導入しました。コンテナへのアクセスにはCloudflare Tunnelを使用したのですが、いくつかハマった点があったのでまとめておきます。
Docker Swarmを使用しましたが、docker-composeでもk8sでも(?)適用できるかもしれません。
要件
- Cloudflare Tunnel経由でコンテナにアクセスできるようにする
- Tunnelのトークンはsecret経由で渡す
実装
composeファイルは次のような感じになりました。
version: "3.9"
services:
cloudflared:
image: cloudflare/cloudflared:latest
command: tunnel --no-autoupdate run
networks:
- tunnel_network
secrets:
tunnel_token
environment:
TUNNEL_TOKEN_FILE: /run/secrets/tunnel_token
deploy:
placement:
constraints: [ node.role == manager ]
secrets:
tunnel_token:
external: true
networks:
tunnel_network:
external: true
ハマった点
トークンをsecretで渡すのが難しい
DockerにはAPIトークンなどの機密情報を安全に扱うためのsecretという機能があります。これを使うことで、コンテナの定義ファイルにトークンを記述することなく実行することができます。
一方で、このsecretに設定した値は環境変数などから直接読み込むことはできず、/run/secrets/{id}
にあるファイルとしてコンテナに渡されます。そのため、通常のコマンドラインによる設定(--token {token}
)は使用することができません。
どうやら少し前までは、一度ファイルから何らかの手段で値を取り出して渡すというような複雑なステップを踏む必要があったようなのですが、今ではTUNNEL_TOKEN_FILE
という環境変数にファイルのパスを設定することで、起動できるようになったようです。参考Issue
自動更新の無効化
Cloudflare Tunnelには自動でアプリケーションを更新する機能が搭載されています。通常の環境であればセキュリティ的にも良く、便利な機能なのですが、Dockerで使用する場合には書き込みが制限されており、更新しようとするとエラーが発生するため、無効化する必要があります。
これは、command
に--no-autoupdate
の引数を追加することで設定できます。ここで注意しなければいけないのは、tunnel --no-autoupdate run
の順でなければならないことです。--no-autoupdate
はtunnel
サブコマンドの引数なので、run --autoupdate
とすると、そんな引数はないとエラーになります。
Discussion