🐳

Cloudflare TunnelをDockerで使うための設定

に公開

手ごろなセルフホストコンテナ環境を作るために、Docker Swarmを導入しました。コンテナへのアクセスにはCloudflare Tunnelを使用したのですが、いくつかハマった点があったのでまとめておきます。

Docker Swarmを使用しましたが、docker-composeでもk8sでも(?)適用できるかもしれません。

要件

  • Cloudflare Tunnel経由でコンテナにアクセスできるようにする
  • Tunnelのトークンはsecret経由で渡す

実装

composeファイルは次のような感じになりました。

compose.yaml
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-autoupdatetunnelサブコマンドの引数なので、run --autoupdateとすると、そんな引数はないとエラーになります。

Discussion