やもりの技術ブログ

日々の生活で行った技術的な活動や日頃感じたことを書きます。

【自宅サーバ】コンテナ環境で自宅用DNSサーバを動かす(Docker/BIND 9.16)

f:id:yamori-tech:20210923170031p:plain

こんにちは、yamori(yamori-tech)です。

今まで自宅内のDNSサーバをCentOS仮想マシン上で運用していたのですが、Dockerの練習がてらコンテナでの運用に変えてみました。

DNSサーバに利用するアプリケーションはBINDで、ISCから9.16.xのstable yumレポジトリの公開も行われていたのでバージョンアップとパッケージの移行も併せて行いました。

ISCのBIND9.16レポジトリを利用したい方も参考になるかと思います。

環境情報
ベースイメージ: CentOS7
アプリケーション: BIND 9.16

Dockerfileの作成

まずはDockerfileを作成していきます。

CentOS7のベースイメージを起動して、ログイン後試行錯誤しながら作成するような形です。

ディレクトリ配置などはisc-bindをインストールしたあとに /etc/opt/isc/isc-bind/named.conf を確認するとわかりやすいです。

通常のサーバにisc-bindをインストールする場合はRUNにかかれているコマンドを実行し、適宜named.confとzoneファイルを置いた後にsystemctlにて稼働できます。

FROM centos:7

# ISCのyumレポジトリファイルをyum.repos.dに配置
RUN curl -o /etc/yum.repos.d/isc-bind.repo https://copr.fedorainfracloud.org/coprs/isc/bind/repo/epel-7/isc-bind-epel-7.repo

# isc-bindとchronyをインストール
RUN yum install isc-bind chrony -y

# named.confの配置
COPY named.conf /etc/opt/isc/isc-bind/named.conf

# ゾーンファイルの配置
COPY zones /var/opt/isc/isc-bind/named/data

# ルートサーバファイルの配置
RUN curl -o /var/opt/isc/isc-bind/named/data/named.ca -LO ftp://ftp.rs.internic.net/domain/named.root

# ディレクトリ権限の設定
RUN chown -R named:named /var/opt/isc/isc-bind/named

# 53 TCP/UDPでのListen
EXPOSE 53/tcp 53/udp

# namedのフォアグラウンドでの起動
CMD /opt/isc/isc-bind/root/usr/sbin/named -u named -c /etc/opt/isc/isc-bind/named.conf -g

BINDの設定ファイル

named.confは以下のような感じです。

allow-query等を入れる場合はContainer環境が稼働しているローカルNWを入れてあげる必要がありました。(今回は172.17.0.0/24)

ゾーンファイルは適宜書いてください。

named.conf

options{
  version "unknown";
  directory "/var/opt/isc/isc-bind/named/data";

  recursion yes;
  dnssec-validation auto;

  allow-query         { localhost; 172.17.0.0/24; 192.168.xx.0/24;};
  allow-recursion     { localhost; 172.17.0.0/24; 192.168.xx.0/24;};
  allow-query-cache   { localhost; 172.17.0.0/24; 192.168.xx.0/24;};
};

zone "." {
  type hint;
  file "named.ca";
};

zone "localhost" IN {
  type master;
  file "localhost.zone";
};
zone "0.0.127.in-addr.arpa" IN {
  type master;
  file "localhost.rev";
};
zone "yamori.com" IN {
  type master;
  file "yamori.com.zone";
};
zone "xx.168.192.in-addr.arpa" IN {
  type master;
  file "yamori.com.rev";
};

動作確認

先程作成したDockerfileをもとにコンテナをビルドして起動し、動作確認を行います。

うまく動いていない場合は、Dockerコンテナ内でconfファイルを編集してプロセスの再起動を行ったりしてデバッグします。

# イメージのBuild
$ docker image build -t yamori.com/bind . 

# イメージの確認
$ docker images                                                                                                               [main]
REPOSITORY        TAG       IMAGE ID       CREATED          SIZE
yamori.com/bind   latest    40588f7affe0   11 seconds ago   357MB

# コンテナの起動 (tcp,udp 53をフォワード)
$ docker run -itd -p 53:53/udp -p 53:53/tcp yamori.com/bind

# コンテナのIDを確認
$ docker ps                                                                                                                   [main]
CONTAINER ID   IMAGE             COMMAND                  CREATED         STATUS         PORTS                                                                  NAMES
0b1fbce2b579   yamori.com/bind   "/bin/sh -c '/opt/is…"   6 seconds ago   Up 5 seconds   0.0.0.0:53->53/tcp, 0.0.0.0:53->53/udp, :::53->53/tcp, :::53->53/udp   wizardly_goldberg

# コンテナ内でbashを実行して入る
$ docker exec -it 0b1fbce2b579 bash

# プロセスの稼働を確認
[root@1e4edc09ddc0 /]# ps a | grep bind | grep -v grep
    1 pts/0    Ssl+   0:00 /opt/isc/isc-bind/root/usr/sbin/named -u named -c /etc/opt/isc/isc-bind/named.conf -g

# digコマンドを入れ忘れていたのでインストール
[root@1e4edc09ddc0 /]# yum install bind-utils -y

# 内部のドメインを解決
[root@1e4edc09ddc0 /]# dig @localhost ns.yamori.com +short
192.168.11.xx

# 外部のドメインを解決
[root@1e4edc09ddc0 /]# dig @localhost www.google.com +short
142.250.196.100

# Dockerコンテナから抜けて、フォワードしたポートに向けて同様に解決可能か確認
$ dig @localhost ns.yamori.com +short
192.168.11.xx
$ dig @localhost www.google.com +short
142.250.196.100

DNSサーバとして稼働させる

DNSサーバとして稼働させたいDockerサーバ上で、以下のようにrestart policyを設定して起動させます。

これで、Dockerコンテナが稼働しているサーバの53/tcpと53/udpにてBINDサーバが稼働している状態になります。

あとはDHCPかか何かでnameserverをDockerコンテナが稼働しているサーバのIPアドレスに向ければOKです。

$ docker run -d -p 53:53/udp -p 53:53/tcp --restart always yamori.com/bind

AnsibleでDockerイメージのDeployをする

以下のような感じのAnsible PlaybookでDockerの稼働サーバにbindコンテナをDeployできます。

これを実行することで最新のイメージをbuildしてrestartさせることができ、DNS設定の更新が簡単になります。

deploy-bind.yaml

- hosts: all
  become: yes
  tasks:
  - name: Build用ディレクトリ作成
    file:
      path=/var/docker/bind
      state=directory

  - name: named.confのコピー
    copy:
      src=named.conf
      dest=/var/docker/bind/named.conf

  - name: ゾーンファイルのコピー
    copy: 
      src=zones/
      dest=/var/docker/bind/zones

  - name: Dockerfileのコピー
    copy:
      src=Dockerfile
      dest=/var/docker/bind/Dockerfile

  - name: イメージのビルド
    docker_image:
      build:
        path: /var/docker/bind
      name: jimaoka.com/bind
      tag: latest
      force_source: yes
      force_tag: yes
      source: build

  - name: bindコンテナの作成
    docker_container:
      name: bind-container
      image: yamori.com/bind:latest
      state: started
      recreate: yes
      published_ports: 
        - "{{ ansible_ens192.ipv4.address }}:53:53/udp"
        - "{{ ansible_ens192.ipv4.address }}:53:53/tcp"
      restart: yes
      restart_policy: always

  - name: 不要イメージ/コンテナの削除
    docker_prune:
      images: yes
      containers: yes

まとめ

DNSサーバをDockerコンテナでの稼働に変更しました。

Dockerコンテナで動作させることで、利用リソースがかなり少なくなり、更新や再構築が簡単になりました。

いつの間にかISCのyumレポジトリも公開されており、新しいバージョンの導入にBuildも必要なくなったので簡単に導入できるようになっていたのもいいところでした。