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

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

https://qiita.com/ohhara_shiojiri/items/d5543afc616c0f117157

# 更新内容
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です。

https://github.com/ngoduykhanh/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のユーザーが修正すべき設定ファイルは、以下の２ファイルです。

```: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番なのでブラウザで以下を指定すれば表示されます。最初はアカウント作成のログイン画面になります。

http://127.0.0.1:9191

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

![操作画面](https://user-images.githubusercontent.com/6447444/44068603-0d2d81f6-9fa5-11e8-83af-14e2ad79e370.png)

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

http://127.0.0.1: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
```