Dockerで権威DNSサーバーのPowerDNS+PowerDNS-Adminを動かす


注意

この2018年に投稿した内容では古くてそのままでは動作しなくなっているので2022年版を別に投稿しました。

更新内容

2019/11/20 PowerDNS Authoritative Server 4.2.0に対応修正

背景

昨年にDockerでPowerDNS+poweradminを動かした投稿をしましたが、

[Dockerで権威DNSサーバーのPowerDNSを動かす]
(https://qiita.com/ohhara_shiojiri/items/1705f0045b8d860f771d)

フロントエンドのGUIが今時のイケてるPowerDNS-Adminに変えて最新バージョンに対応させて運用しています。
という訳で諸々の背景や前提は前回の投稿を参照して頂くとして、変更点などを記録しておきます。

Docker環境

ホストOSには、ubuntu server 18.04 LTS を使用、Docker CEとDocker-composeでコンテナを作成します。
インストール方法は公式ガイドを参照下さい。一例も記録しておきます。

Docker CE インストール
https://docs.docker.com/install/linux/docker-ce/ubuntu/

$ sudo apt-get update
$ sudo apt-get install apt-transport-https ca-certificates
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
$ sudo apt-get update
$ sudo apt-get install docker-ce
$ apt-cache madison docker-ce
$ sudo docker run hello-world

Docker Compose インストール
https://docs.docker.com/compose/install/

$ sudo -i
# curl -L https://github.com/docker/compose/releases/download/1.25.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
# chmod +x /usr/local/bin/docker-compose
# exit
$ docker-compose --version

PowerDNS-Admin

PowerDNS用のフロントエンドのGUIツールでは活発に開発されているのがPowerDNS-Adminです。

各種ユーザー認証にも対応していて複数ドメインとユーザー管理が出来るのが特徴です。画面表示はpoweradminと違って日本語には対応していませんが、特に難しい事は無く使えると思います。
また、予めdocker-compose.ymlファイルも用意されていますので、GitHubからcloneして来て設定を少し修正するだけで動作しました。

データベースのGUI管理 Adminer

PowerDNSはゾーンとレコードの管理に、PowerDNS-Adminはユーザー管理にそれぞれMySQLのデータベースを使用しています。Dockerコンテナで運用している事もあり、MySQLデータベースのGUI管理がいろいろと便利ですのでdocker-composeに組み込みました。

docker-compose.yml
  adminer:
    image: adminer
    container_name: mysql-adminer
    restart: always
    ports:
      - 8080:8080
    depends_on:
      powerdns-admin-mysql:
        condition: service_healthy
      pdns-mysql:
        condition: service_healthy

サービスポート番号の8080番を指定するとMySQLデータベースがGUIで管理出来ます。

Step 1:GithubからClone

$ git clone https://github.com/ngoduykhanh/PowerDNS-Admin.git
$ cd PowerDNS-Admin

Step 2:設定ファイル

PowerDNS-Adminのユーザーが修正すべき設定ファイルは、以下の2ファイルです。

configs/development.py
SECRET_KEY = 'changeme'
.env
PDA_DB_PASSWORD=changeme
PDNS_DB_PASSWORD=changeme
PDNS_API_KEY=changeme

「SECRET_KEY」と「PDNS_API_KEY」を同じにしてAPI接続が出来ます。
「PDA_DB_PASSWORD」がPowerDNS-Admin用のデータベースのパスワード、
「PDNS_DB_PASSWORD」がPowerDNS用のデータベースのパスワードになります。

docker-compose.yml
  pdns-server:
    container_name: pdns-server

コンテナ名が無指定だったので追加修正

Step 3:Docker Imageの作成

PowerDNS-Adminコンテナのイメージをローカル環境でビルドします。
コンテナイメージの作成が完了するまでPCの性能によってしばらく時間がかかります。ただし最初の作成時だけでコンテナイメージの変更が無ければ次回からは再ビルドしなくても構いません。

$ docker-compose build

Step 4:Dockerコンテナを実行

$ docker-compose up -d

動作確認

無事にDockerコンテナが起動していれば、以下のような状態になります。
PowerDNSのコンテナpdns-serverは外部に対してTCP/UDP:5053でLISTENしています。
ローカルDNSとの競合を避けるためですが、docker-compose.ymlファイルを編集する事でポート番号は変更出来ます。
このままポート番号を変更せずにローカルDNSと共存させてポートフォワードで運用する方法もあります。

$ docker-compose ps
        Name                      Command                  State                         Ports                   
-----------------------------------------------------------------------------------------------------------------
mysql-adminer          entrypoint.sh docker-php-e ...   Up             0.0.0.0:8080->8080/tcp                    
pdns-mysql             /entrypoint.sh mysqld            Up (healthy)   3306/tcp, 33060/tcp                       
pdns-server            /entrypoint.sh --api=yes - ...   Up             0.0.0.0:5053->53/tcp, 0.0.0.0:5053->53/udp
powerdns-admin         /entrypoint.sh                   Up             0.0.0.0:9191->9191/tcp                    
powerdns-admin-mysql   /entrypoint.sh mysqld            Up (healthy)   3306/tcp, 33060/tcp

PowerDNSのバージョンを確認する為に実行中のコンテナに接続して見ます。

$ docker exec -it pdns-server /bin/sh
/ # /usr/sbin/pdns_server --version
Nov 20 08:43:51 PowerDNS Authoritative Server 4.2.0 (C) 2001-2019 PowerDNS.COM BV

ローカルDNSの停止(Ubuntu 16.04)

ubuntu 16.04 ではローカルDNSのdnsmasqが動作しています。
当然にTCP/UDP:53番ポートをLISTENするのでポート番号が競合する為に事前に停止します。

$ sudo lsof -i:53
COMMAND  PID   USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
dnsmasq 1107 nobody    4u  IPv4  20801      0t0  UDP localhost:domain 
dnsmasq 1107 nobody    5u  IPv4  20802      0t0  TCP localhost:domain (LISTEN)

DNS設定をコメントアウト

/etc/NetworkManager/NetworkManager.conf
#dns=dnsmasq

NetworkManagerを再起動

$ sudo service network-manager restart

このままだとDNS名前解決できないので、DNSリゾルバを設定します。

/etc/resolv.conf
#nameserver 127.0.1.1
nameserver 8.8.8.8

NetworkManager経由のサブデーモンとしてdnsmasqが起動している為か、
ホスト自体を再起動しないとdnsmasqが無効になりませんでした。

ローカルDNSの停止(Ubuntu 18.04)

ubuntu 18.04ではローカルDNSのsystemd-resolveが動作しています。
当然にTCP/UDP:53番ポートをLISTENするのでポート番号が競合する為に事前に停止します。

$ sudo lsof -i:53
COMMAND   PID            USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
systemd-r 685 systemd-resolve   12u  IPv4  18787      0t0  UDP localhost:domain 
systemd-r 685 systemd-resolve   13u  IPv4  18788      0t0  TCP localhost:domain (LISTEN)
/etc/systemd/resolved.conf
DNSStubListener=no
$ sudo systemctl restart systemd-resolved
$ sudo lsof -i:53
sudo: unable to resolve host vuls: Resource temporarily unavailable

このままだとDNS名前解決できないので、DNSリゾルバを設定します。

/etc/resolv.conf
#nameserver 127.0.0.53
nameserver 8.8.8.8

しかしsystemd-resolvedにより
/etc/resolv.conf -> ../run/systemd/resolve/stub-resolv.conf
とシンボリックリンクされていて元に戻ってしまいます。
やはりsystemd-resolvedを停止させます。

$ sudo systemctl stop systemd-resolved
$ sudo systemctl disable systemd-resolved

シンボリックリンクを消して設定ファイルを作成します。

$ sudo rm /etc/resolv.conf
/etc/resolv.conf
nameserver 8.8.8.8

操作管理画面

PowerDNS-AdminのGUI画面は、サービスポート番号が9191番なのでブラウザで以下を指定すれば表示されます。最初はアカウント作成のログイン画面になります。

また、Dockerコンテナのホスト側にサービスポートをブリッジしていますので、127.0.0.1の部分はDockerコンテナを実行しているホスト側のIPアドレスになります。

MySQLデータベース管理のAdminerは、サービスポート番号は8080番なのでブラウザで以下を指定すれば表示されます。最初はデータベースへのログイン画面になります。

同様に、Dockerコンテナのホスト側にサービスポートをブリッジしていますので、127.0.0.1の部分はDockerコンテナを実行しているホスト側のIPアドレスになります。
データベース名やアカウント、パスワードは設定ファイル「.env」で指定した通りに作成されます。

オプション設定

PowerDNSのオプション設定は、docker-compose.ymlファイルのcommand:行で指定できます。
例えば標準ではZone転送が制限されていますが、オプションの「--allow-axfr-ips=」を指定すればセカンダリDNSサーバーへのZone転送が出来ます。

docker-compose.yml
  pdns-server:
    image: psitrax/powerdns
    command: --api=yes --api-key=${PDNS_API_KEY} --webserver-address=0.0.0.0 --webserver-allow-from=0.0.0.0/0 --allow-axfr-ips=192.168.0.1