CloudflareをDDNSとして使うためのDockerイメージを作ってみました【GitHub Actions・Buildx】

先日、CloudflareをDDNS(Dynamic DNS)として使いたいと思い、グローバルアドレスを自動更新する仕組みをDockerで動かそうと考えました。
そこで、既存のDockerイメージを探して試してみたのですが、どうも要件に合い、かつうまく動作するものが見つかりませんでした。

求めていた機能などは以下の通りです。

  • 取得したグローバルIPアドレスを複数のレコードを更新できる
  • IPv6アドレスも取得できる
  • レコードによりIPv4アドレスのみ、IPv6アドレスのみを設定できる
  • 複数のゾーン(ドメイン)に含まれるレコードを更新できる

普通、1つのホスト名(サブドメイン)にAレコードとAAAAレコードを1つずつ設定し、あとは必要に応じてCNAMEレコードを設定すれば十分なので、わざわざIPv4とIPv6のみのホスト名を作りたいとか、複数のゾーンを更新したいとかいった変なことをする人は少ないのでしょう。

一応、上記の機能を持ってそうなイメージもありましたが、私の環境ではうまくIPv6アドレスが取れなかったりしました。1レコードのみ更新できるDockerイメージから複数のコンテナを起動するという方法も考えましたが、それも不細工な話です。

そこで、ひとつ自分で書いてしまおうと考え、何番煎じか分かりませんが、CloudFlareをDDNSとして使うDockerイメージ(マルチゾーン・マルチレコード対応)を作ってみました。

https://hub.docker.com/repository/docker/jkbys/cloudflare-ddns-multi
GitHub - jkbys/cloudflare-ddns-multi: Cloudflare DDNS Multiple Zone/Recoerd Updater - Docker micro image / Shell script
Cloudflare DDNS Multiple Zone/Recoerd Updater - Docker micro image / Shell script - jkbys/cloudflare-ddns-multi

最初はPythonで少し書き始めたのですが、他の人にも使ってもらうにはイメージサイズが小さいほうがよさそうですし、ルーターなどDockerやPythonが入っていない環境でも使えたほうが良いかなと考え、シェルスクリプトで書きました。Alpineの公式イメージに入っているBusyBoxで動くように書いています。Alpineのイメージにcurlとjqだけ追加すれば動くようにしたので、ダウンロードサイズは4MB弱まで小さくすることができました。

書いているうちに、グローバルアドレスの変更時にWebhookを叩いたりするために任意のコマンドを実行する機能を入れたり、レコードによっては固定のアドレスを設定したり、終了時にレコードを削除したりといった、自分でも使うかどうか分からない機能を入れた結果、以下のような特徴を持つスクリプトとなりました(README.ja.mdから抜粋)。

小さなDockerイメージ
このイメージのダウンロードサイズ(圧縮サイズ)は4MB未満です。
複数のアーキテクチャに対応
Dockerイメージはamd64, 386, arm64, arm/v7, arm/v6に対応しています。さらに、他のアーキテクチャであってもDockerを使わずにこのシェルスクリプトを実行することができます。
BusyBoxで実行可能なシェルスクリプト
BusyBox のシェルで動作するように設計されています。他にも、Bashはもちろん、DebianやUbuntuの/bin/shとして採用されているdashでも動作します。
複数のゾーン・レコードに対応
複数のゾーンに含まれる、複数のレコードを更新することができます。
IPv4とIPv6の両方をサポート
IPv4 アドレスだけでなく、IPv6 アドレスにも対応しています。
グローバルIPアドレスの確実な取得
間違ったグローバルIPアドレスを設定しないよう、複数の取得元からアドレスを取得し、一致することを確認してから処理を実行します。
IPアドレス取得方法のカスタマイズが可能
デフォルトでは、IPアドレスを外部HTTPSサーバーより取得します。設定により、外部DNSサーバーから取得させることも可能です。また、IPアドレスを取得する独自のコマンドを設定することもできます。レコードごとに、固定IPアドレスや独自のIPアドレス取得用コマンドの指定も可能です。
キャッシュ機能によるCloudflare API呼び出し回数の節約
各レコードの設定状態をキャッシュすることにより、API呼び出し回数を節約します。キャッシュの期限が切れるまで、グローバルIPアドレスが変わらない限り、APIアクセスを行いません。キャッシュの有効期間は設定ファイルで変更できます(デフォルトは1時間)。
処理にあわせて実行する外部コマンドを設定可能
レコードの作成・更新・削除時などに、外部コマンドを実行することができます。curlコマンドを使って、WebhookにPOSTリクエストを送信するといったことも可能です。

Dockerイメージの生成は、Github Actionsで行いました。以下のアクションを使えば、GitHubで各アーキテクチャ(amd64,i386,arm64,armhfなど)のイメージ生成と、Docker HubとGitHub Container Registry(ghcr.io)へのアップロードを自動でやってくれます。

Build and push Docker images - GitHub Marketplace
Build and push Docker images with Buildx

.github/workflows/docker-publish.ymlを作成し、とりあえず手動で実行したところ、問題なくアップロードされ、Docker Hubから取得できるようになりました。普通は、特定のブランチ(普通はmainもしくはmaster)にpushされると自動でテスト・生成・アップロードを行う形で運用するようです。

コメント

タイトルとURLをコピーしました