おさらい
前回までのエントリでは、Photon OS をデプロイして初期設定を行いました。
もともとの目的は、vCenter Server Appliance 6.5(vCSA 6.5)をお行儀のよい構成でインストールするために必要な DNS サーバを作ることです。よって今回は、前回構築した Photon OS 上で、bind をサービスする Docker コンテナを作ります。
設計
こんな感じにします。
- ベース OS は Alpine Linux にする
- bind を追加する
- bind の設定ファイル群はホスト OS 上のディレクトリに置き、コンテナからマウントさせる
- Docker Compose で起動・停止できるようにする
ベース OS の選択には特にこだわりはないので、流行に乗って Alpine Linux にします。最新版を使います。
設定ファイルの置き場所は悩みどころですが、設定の変更などがしやすくなるのでこうしました。ポータビリティは下がりますが、配布予定もないし単一のサーバでしかホストしないのでよしとします。
Docker Compose は蛇足です。本来は複数のコンテナを連携させるときに使うものですが、使ってみたかったので使ってみます。
以降、やっぱり文字ばかりになるので、きれいな孔雀の写真を載せておきます。配色が Photon OS のそれと似ていますね。
Dockerfile を作る
まずは Dockerfile です。作ります。コンテナイメージのレシピみたいなものです。
kuro@kuro-ph01 [ ~ ]$ vim Dockerfile kuro@kuro-ph01 [ ~ ]$ cat Dockerfile FROM alpine:latest RUN apk add bind --no-cache EXPOSE 53/udp CMD ["/usr/sbin/named", "-c", "/etc/bind/named.conf", "-u", "named", "-g"]
bind の設定ファイル群を作る
コンテナの中で動かす bind のための設定ファイルを作ります。
メインの named.conf と、ゾーン定義の二つのファイルを作りました。作ったファイルはひとつのディレクトリにまとめておきます。コンテナの中の named ユーザが読み取れるように、パーミッションも変更します。
kuro@kuro-ph01 [ ~ ]$ mkdir conf kuro@kuro-ph01 [ ~ ]$ vim conf/named.conf kuro@kuro-ph01 [ ~ ]$ cat conf/named.conf acl localnet { 127.0.0.1; 192.168.0.0/24; }; options { version "unknown"; directory "/var/bind"; pid-file "/var/run/named/named.pid"; recursion yes; notify no; listen-on { any; }; listen-on-v6 { none; }; allow-query { localnet; }; allow-query-cache { localnet; }; allow-recursion { localnet; }; allow-transfer { none; }; forwarders { 192.168.0.1; }; }; zone "kuro.local" IN { type master; file "/etc/bind/kuro.local.zone"; }; kuro@kuro-ph01 [ ~ ]$ vim conf/kuro.local.zone kuro@kuro-ph01 [ ~ ]$ cat conf/kuro.local.zone $TTL 1h @ IN SOA ns.kuro.local postmaster.kuro.local. ( 2017030501 ; serial 1h ; refresh 15m ; retry 1d ; expire 1h ; minimum ); @ IN NS ns.kuro.local. ns IN A 192.168.0.249 kuro-vc01 IN A 192.168.0.250 kuro-esx01 IN A 192.168.0.251 kuro@kuro-ph01 [ ~ ]$ chmod 755 conf kuro@kuro-ph01 [ ~ ]$ chmod 644 conf/*
コンテナイメージをビルドして起動する
ここまで用意ができたら、あとはビルドして起動させるだけです。
まずはビルドします。ビルドは build サブコマンドです。末尾でビルドしたい Dockerfile を含むディレクトリを指定します。今回はカレントディレクトリなのでドット(.)です。
kuro@kuro-ph01 [ ~ ]$ docker build -t bind . Sending build context to Docker daemon 11.78 kB Step 1 : FROM alpine:latest latest: Pulling from library/alpine 627beaf3eaaf: Pull complete Digest: sha256:58e1a1bb75db1b5a24a462dd5e2915277ea06438c3f105138f97eb53149673c4 Status: Downloaded newer image for alpine:latest ---> 4a415e366388 Step 2 : RUN apk add bind --no-cache ---> Running in 84d3fb22724e fetch http://dl-cdn.alpinelinux.org/alpine/v3.5/main/x86_64/APKINDEX.tar.gz fetch http://dl-cdn.alpinelinux.org/alpine/v3.5/community/x86_64/APKINDEX.tar.gz (1/5) Installing libgcc (6.2.1-r1) (2/5) Installing libxml2 (2.9.4-r1) (3/5) Installing bind-libs (9.10.4_p6-r0) (4/5) Installing libcap (2.25-r1) (5/5) Installing bind (9.10.4_p6-r0) Executing bind-9.10.4_p6-r0.pre-install Executing busybox-1.25.1-r0.trigger OK: 9 MiB in 16 packages ---> 29500538ea16 Removing intermediate container 84d3fb22724e Step 3 : EXPOSE 53/udp ---> Running in a8ea36f4c12f ---> f08f46db2947 Removing intermediate container a8ea36f4c12f Step 4 : CMD /usr/sbin/named -c /etc/bind/named.conf -u named -g ---> Running in a2fd9c1acd90 ---> bf1581067386 Removing intermediate container a2fd9c1acd90 Successfully built bf1581067386 kuro@kuro-ph01 [ ~ ]$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE bind latest bf1581067386 41 seconds ago 8.772 MB alpine latest 4a415e366388 2 weeks ago 3.984 MB
できたイメージは images サブコマンドで確認できます。無事にできたようなので動かしてみましょう。
起動は run サブコマンドです。バックグラウンドで起動(-d)させ、ホストのポートとディレクトリをコンテナに割り当て(-p、-v)ます。
kuro@kuro-ph01 [ ~ ]$ docker run -d -p 53:53/udp -v $(pwd)/conf:/etc/bind --restart always --name bind bind 442a5494f13328641cc3ba6c526a65591874f01476255a47f962dbc8922e0f3b kuro@kuro-ph01 [ ~ ]$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 442a5494f133 bind "/usr/sbin/named -c /" 3 seconds ago Up 2 seconds 0.0.0.0:53->53/udp bind
起動状態は ps サブコマンドで確認できます。この結果の STATUS が Up になっていれば、少なくともコンテナは正しく動いています。あとはコンテナ内で bind が正しく動いていれば問題ありません。
というわけで、まずは自分自身に DNS のクエリを投げてみます。ミニマル構成の Photon OS には nslookup も dig もないので、bindutils をインストールしてから試します。
kuro@kuro-ph01 [ ~ ]$ sudo tdnf install bindutils [sudo] password for kuro Sorry, try again. [sudo] password for kuro Installing: bindutils x86_64 9.10.4-1.ph1 6.86 M Total installed size: 6.86 M Is this ok [y/N]:y Downloading: bindutils 3116681 100% Testing transaction Running transaction Complete! kuro@kuro-ph01 [ ~ ]$ dig @192.168.0.249 kuro-vc01.kuro.local ; <<>> DiG 9.10.4-P1 <<>> @192.168.0.249 kuro-vc01.kuro.local ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 49190 ;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 2 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;kuro-vc01.kuro.local. IN A ;; ANSWER SECTION: kuro-vc01.kuro.local. 3600 IN A 192.168.0.250 ;; AUTHORITY SECTION: kuro.local. 3600 IN NS ns.kuro.local. ;; ADDITIONAL SECTION: ns.kuro.local. 3600 IN A 192.168.0.249 ;; Query time: 0 msec ;; SERVER: 192.168.0.249#53(192.168.0.249) ;; WHEN: Tue Mar 21 00:04:46 JST 2017 ;; MSG SIZE rcvd: 98 kuro@kuro-ph01 [ ~ ]$ nslookup google.com 192.168.0.249 Server: 192.168.0.249 Address: 192.168.0.249#53 Non-authoritative answer: Name: google.com Address: 172.217.25.238
定義したゾーンの情報も引けていますし、再帰問い合わせもできています。よさそうです。
別の端末からも叩いてみます。例えば Windows から。
C:\Users\kuro>nslookup kuro-vc01.kuro.local 192.168.0.249 サーバー: UnKnown Address: 192.168.0.249 名前: kuro-vc01.kuro.local Address: 192.168.0.250 C:\Users\kuro>nslookup google.com 192.168.0.249 サーバー: UnKnown Address: 192.168.0.249 権限のない回答: 名前: google.com Address: 216.58.197.142
よいですね。
うまく動かない場合は、以下のように logs サブコマンドで named のログを見るか、
kuro@kuro-ph01 [ ~ ]$ docker logs bind 20-Mar-2017 15:00:53.955 starting BIND 9.10.4-P6 <id:a6837d0> -c /etc/bind/named.conf -u named -g 20-Mar-2017 15:00:53.955 running on Linux x86_64 4.4.41-1.ph1-esx #1-photon SMP Tue Jan 10 23:46:44 UTC 2017 20-Mar-2017 15:00:53.955 built with '--build=x86_64-alpine-linux-musl' '--host=x86_64-alpine-linux-musl' '--prefix=/usr' '--sysconfdir=/etc/bind' '--localstatedir=/var' '--with-openssl=/usr' '--enable-linux-caps' '--with-libxml2' '--enable-threads' '--enable-filter-aaaa' '--enable-ipv6' '--enable-shared' '--enable-static' '--with-libtool' '--with-randomdev=/dev/random' '--mandir=/usr/share/man' '--infodir=/usr/share/info' 'build_alias=x86_64-alpine-linux-musl' 'host_alias=x86_64-alpine-linux-musl' 'CC=gcc' 'CFLAGS=-Os -fomit-frame-pointer -D_GNU_SOURCE' 'LDFLAGS=-Wl,--as-needed' 'CPPFLAGS=-Os -fomit-frame-pointer' 20-Mar-2017 15:00:53.955 ---------------------------------------------------- 20-Mar-2017 15:00:53.955 BIND 9 is maintained by Internet Systems Consortium, 20-Mar-2017 15:00:53.955 Inc. (ISC), a non-profit 501(c)(3) public-benefit 20-Mar-2017 15:00:53.955 corporation. Support and training for BIND 9 are 20-Mar-2017 15:00:53.955 available at https://www.isc.org/support 20-Mar-2017 15:00:53.955 ---------------------------------------------------- 20-Mar-2017 15:00:53.955 found 1 CPU, using 1 worker thread 20-Mar-2017 15:00:53.955 using 1 UDP listener per interface . . .
あるいは、以下のようにしてコンテナ内のシェルに入って調査します。ps や ls をしているのはただの例なので、実際は自由にトラブルシュートしてください。
kuro@kuro-ph01 [ ~ ]$ docker exec -it bind /bin/ash / # ps -ef PID USER TIME COMMAND 1 named 0:00 /usr/sbin/named -c /etc/bind/named.conf -u named -g 8 root 0:00 /bin/ash 12 root 0:00 ps -ef / # ls -l /etc/bind/ total 8 -rw-r--r-- 1 1000 1000 306 Mar 20 13:57 kuro.local.zone -rw-r--r-- 1 1000 1000 495 Mar 20 14:04 named.conf
なお、Dockerfile で記述した通り、今回は CMD 行で named を -g で起動させています。このため、exec サブコマンドでなく attach サブコマンドを利用しても、named につながるだけで何のトラブルシュートもできない点には注意が必要です。上記のように、exec サブコマンドを利用して明示的に新規プロセスとしてシェルを起動する必要があります。また、Alpine Linux のシェルは /bin/bash ではなく /bin/ash です。
exec サブコマンドは起動中のコンテナに対してしかできない操作なので、もしそもそもコンテナの起動がコケている場合は、上記のコマンドではシェルに入れません。この場合は、exec サブコマンドを run サブコマンドに置き換えて、明示的に起動させます。これによりコンテナの CMD 指定が /bin/ash でオーバライドされるので、named は起動されずに(=コンテナが落ちずに)シェルがフォアグラウンドで実行されます。
よくあるのは、docker ps したときの STATUS が Restarting のままになるトラブルです。大体の場合、named が設定ファイルの読み込みでコケてこうなります。コケて named が落ちてコンテナが終了するものの、restart オプションによって延々と再度の起動が試行されている状態です。この場合は、ファイルのパーミッションや、ボリュームマウントの指定が正しいか確認します。
Docker Compose で操作する
ここまでで当初の最低限の要件は満たせたので、あとはオマケです。
まっさらな状態にするために、動かしていたコンテナを停止し削除、イメージも全部消しておきます。
kuro@kuro-ph01 [ ~ ]$ docker stop bind bind kuro@kuro-ph01 [ ~ ]$ docker rm bind bind kuro@kuro-ph01 [ ~ ]$ docker rmi bind Untagged: bind:latest Deleted: sha256:bf1581067386a7eb1de3b86773c2d89a4f901ab190d6e74679c541a91e5c1d12 Deleted: sha256:f08f46db294799dbdf60b982abc0431ffb11bb046558888b434ba3cbbe47091e Deleted: sha256:29500538ea168fc7cee66a294b3ed90a3420cc299ac9d84896b2784ecf81f609 Deleted: sha256:c193e93d56d7b0dc758de256cf867bc724aa3ef55ddb14dfdb804b09303fb84e kuro@kuro-ph01 [ ~ ]$ docker rmi alpine Untagged: alpine:latest Untagged: alpine@sha256:58e1a1bb75db1b5a24a462dd5e2915277ea06438c3f105138f97eb53149673c4 Deleted: sha256:4a415e3663882fbc554ee830889c68a33b3585503892cc718a4698e91ef2a526 Deleted: sha256:23b9c7b43573dd164619ad59e9d51eda4095926729f59d5f22803bcbe9ab24c2 kuro@kuro-ph01 [ ~ ]$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES kuro@kuro-ph01 [ ~ ]$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE
あとは、以下な感じになるようにディレクトリを切って、これまでに作ったファイルを移動させておきます。
[~/docker] └ [bind] ├ Dockerfile └ [conf] ├ kuro.local.zone └ named.conf
kuro@kuro-ph01 [ ~ ]$ mkdir -p docker/bind kuro@kuro-ph01 [ ~ ]$ mv Dockerfile conf docker/bind
では、今回作ったコンテナを、Docker Compose で操作できるようにしてみます。
本来は複数コンテナを簡単に連携させるために使うものですが、旨味は少ないながらも単一のコンテナを操作したいだけの目的でも使えます。
まずは Docker Compose をインストールします。上記ドキュメントに記載があるコマンドをそのまま実行するだけです。
kuro@kuro-ph01 [ ~ ]$ sudo curl -L "https://github.com/docker/compose/releases/download/1.11.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 600 0 600 0 0 330 0 --:--:-- 0:00:01 --:--:-- 330 100 8066k 100 8066k 0 0 23737 0 0:05:47 0:05:47 --:--:-- 15090 kuro@kuro-ph01 [ ~ ]$ sudo chmod +x /usr/local/bin/docker-compose kuro@kuro-ph01 [ ~ ]$ sudo docker-compose --version docker-compose version 1.11.2, build dfed245
インストールができたら、設定ファイルを作ります。
kuro@kuro-ph01 [ ~ ]$ vim docker/docker-compose.yml kuro@kuro-ph01 [ ~ ]$ cat docker/docker-compose.yml version: "2.0" services: bind: container_name: bind build: bind image: bind volumes: - ./bind/conf:/etc/bind ports: - 53:53/udp restart: always
あとは起動させるだけです。バックグラウンドで実行させたいので、up サブコマンドに -d を付けます。
kuro@kuro-ph01 [ ~ ]$ cd docker kuro@kuro-ph01 [ ~/docker ]$ sudo docker-compose up -d Building bind Step 1 : FROM alpine:latest latest: Pulling from library/alpine 627beaf3eaaf: Pull complete Digest: sha256:58e1a1bb75db1b5a24a462dd5e2915277ea06438c3f105138f97eb53149673c4 Status: Downloaded newer image for alpine:latest ---> 4a415e366388 Step 2 : RUN apk add bind --no-cache ---> Running in 7cb9b9b1d9c5 fetch http://dl-cdn.alpinelinux.org/alpine/v3.5/main/x86_64/APKINDEX.tar.gz fetch http://dl-cdn.alpinelinux.org/alpine/v3.5/community/x86_64/APKINDEX.tar.gz (1/5) Installing libgcc (6.2.1-r1) (2/5) Installing libxml2 (2.9.4-r1) (3/5) Installing bind-libs (9.10.4_p6-r0) (4/5) Installing libcap (2.25-r1) (5/5) Installing bind (9.10.4_p6-r0) Executing bind-9.10.4_p6-r0.pre-install Executing busybox-1.25.1-r0.trigger OK: 9 MiB in 16 packages ---> 3f4617f7e3e7 Removing intermediate container 7cb9b9b1d9c5 Step 3 : EXPOSE 53/udp ---> Running in 828a66a3c5f8 ---> 47c21a9ae08f Removing intermediate container 828a66a3c5f8 Step 4 : CMD /usr/sbin/named -c /etc/bind/named.conf -u named -g ---> Running in 13e41b8d96c7 ---> 85edc496264d Removing intermediate container 13e41b8d96c7 Successfully built 85edc496264d WARNING: Image for service bind was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`. Creating bind
docker-compose.yml の記述に従って、各サービス(コンテナ)が起動されます。build が指定されていた場合は、Dockerfile に従ってコンテナイメージのビルドも行います。
起動状態は、ps サブコマンドで確認できます。
kuro@kuro-ph01 [ ~/docker ]$ sudo docker-compose ps Name Command State Ports ------------------------------------------------------------------ bind /usr/sbin/named -c /etc/bi ... Up 0.0.0.0:53->53/udp
ログの確認は logs サブコマンドです。
kuro@kuro-ph01 [ ~/docker ]$ sudo docker-compose logs Attaching to bind bind | 20-Mar-2017 16:20:24.015 starting BIND 9.10.4-P6 <id:a6837d0> -c /etc/bind/named.conf -u named -g bind | 20-Mar-2017 16:20:24.015 running on Linux x86_64 4.4.41-1.ph1-esx #1-photon SMP Tue Jan 10 23:46:44 UTC 2017 bind | 20-Mar-2017 16:20:24.015 built with '--build=x86_64-alpine-linux-musl' '--host=x86_64-alpine-linux-musl' '--prefix=/usr' '--sysconfdir=/etc/bind' '--localstatedir=/var' '--with-openssl=/usr' '--enable-linux-caps' '--with-libxml2' '--enable-threads' '--enable-filter-aaaa' '--enable-ipv6' '--enable-shared' '--enable-static' '--with-libtool' '--with-randomdev=/dev/random' '--mandir=/usr/share/man' '--infodir=/usr/share/info' 'build_alias=x86_64-alpine-linux-musl' 'host_alias=x86_64-alpine-linux-musl' 'CC=gcc' 'CFLAGS=-Os -fomit-frame-pointer -D_GNU_SOURCE' 'LDFLAGS=-Wl,--as-needed' 'CPPFLAGS=-Os -fomit-frame-pointer' bind | 20-Mar-2017 16:20:24.015 ---------------------------------------------------- bind | 20-Mar-2017 16:20:24.015 BIND 9 is maintained by Internet Systems Consortium, bind | 20-Mar-2017 16:20:24.015 Inc. (ISC), a non-profit 501(c)(3) public-benefit bind | 20-Mar-2017 16:20:24.015 corporation. Support and training for BIND 9 are bind | 20-Mar-2017 16:20:24.015 available at https://www.isc.org/support bind | 20-Mar-2017 16:20:24.015 ---------------------------------------------------- bind | 20-Mar-2017 16:20:24.015 found 1 CPU, using 1 worker thread bind | 20-Mar-2017 16:20:24.015 using 1 UDP listener per interface . . .
コンテナの停止や削除は、それぞれ stop サブコマンドや rm サブコマンドで実行できます。
kuro@kuro-ph01 [ ~/docker ]$ sudo docker-compose stop Stopping bind ... done kuro@kuro-ph01 [ ~/docker ]$ sudo docker-compose rm Going to remove bind Are you sure? [yN] y Removing bind ... done kuro@kuro-ph01 [ ~/docker ]$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
当然ながら、それぞれネイティブの docker コマンドによる操作も可能です。
イメージの削除は docker-compose コマンドではできないので、docker コマンドで個別に行う必要があります。ただし、イメージをビルドしなおしたいだけであれば、build サブコマンドを利用するか、up サブコマンドの実行時に –build オプションを付与することで実現できます。
まとめ
Docker 上で bind を動かし、Docker Compose で操作できるようにしました。
自前でがんばりたくない場合は、探せば Docker Hub に既成の bind サービス用コンテナがいくつかある(例えばこれとか)ので、そういうのを使うのも有効です。その手の既成コンテナはだいたい Webmin がくっついていて非常に楽です。
また、今回は Docker Compose を使いましたが、単一コンテナを扱いたいだけなのであれば、Makefile を利用することもできそうです。Photon OS にも make はインストールできます。
次回は vCSA 6.5 の導入を行います。