DockerでDNSにアクセスできない時の対処法

最近Dockerを触っています。Dockerを使うと今までChefとかで設定していたサーバを生のシェルスクリプトを使って設定できます。しかも起動は一瞬だしこれは一度触ってみないと凄さが分からないのではないかと。

とりあえず試したい方はubuntu13.04をVirtualBoxにインストールして下記のコマンドをたたきましょう

curl http://get.docker.io | sudo sh -x

これで簡単にDockerはインストールできます。あとの細かい設定は仮想環境構築に docker を使う - apatheia.infoを参照してもらうとして、今回の本題はいろいろ使っていると、DockerのバグなのかDNSがからで仮想環境が立ち上がってしまうことがあります。そういうときは下記のコマンドをたたきます。

sudo docker run -dns=8.8.8.8 -t -i base /bin/bash

ミソは-dnsオプションで、これを指定すると立ち上がった仮想環境の/etc/resolv.confは8.8.8.8を参照するようになります。これで万事解決かと思ったら大間違いでした。

docker buildで-dnsオプションがない

そうなんです、docker buildには-dnsオプションがありません。すごく困っていたんですが、docker daemonのオプションに-dnsオプションがあることを発見。これを指定すればデフォルトで起動するdockerの仮想環境のDNSを変更できます。

ubuntuは/etc/init/docker.confに起動スクリプトがあるので、これを編集して下記のようにします。

description "Docker daemon"
start on filesystem or runlevel [2345]
stop on runlevel [!2345]
respawn
exec env LANG="en_US.UTF-8" /usr/local/bin/docker -d -dns=8.8.8.8

あとはdockerdを再起動するだけ。

sudo stop dockerd # restartだとdocker.confが読み込まれない
sudo start dockerd

これで万事解決!

DockerでApacheを動かす

Dockerの上でApache2を動かすときにはDockerfileを以下のようにする。

FROM ubuntu:12.04

RUN apt-get update
RUN apt-get install -y apache2

ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_LOG_DIR /var/log/apache2

EXPOSE 80

CMD ["/usr/sbin/apache2", "-D", "FOREGROUND"]

そしてビルドする。

mkdir apache2
cd apache2
vi Dockerfile # 上のDockerfileを作成
docker build -t="apache2" .

これでapache2というREPOSITORYが出来上がるのでこれを指定して起動することが出来る。

docker run -d apache2

/usr/sbin/apache2の-D FOREGROUND引数について

Apache2.2のドキュメントを見ると、

-D parameter

Sets a configuration parameter which can be used with sections in the configuration files to conditionally skip or process commands at server startup and restart. Also can be used to set certain less-common startup parameters including -DNO_DETACH (prevent the parent from forking) and -DFOREGROUND (prevent the parent from calling setsid() et al).

つまりFOREGROUNDオプションを指定したときにはsetsid()を行わないというようにかいてある。そもそもこのsetsid()はC言語システムコール-setsidに書いてあるようにプロセスをデーモン化する際に使用するシステムコール。下記のコードはC言語システムコール-setsidより引用させてもらった。

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>

int
main(void)
{
    pid_t pid = 0;
    int rc = 0;

    printf("sid = %d\n", getsid(0));

    pid = fork();
    if(pid < 0){
        printf("Error: fork(%d) %s\n", errno, strerror(errno));
        return(-1);
    }
    if(pid > 0){
        /* 親プロセスを終了する */
        _exit(0);
    }

    rc = setsid();
    if(pid < 0){
        printf("Error: setsid(%d) %s\n", errno, strerror(errno));
        return(-1);
    }

    printf("sid = %d\n", getsid(0));

    return(0);
}

setsid()を抑制するということはデーモン化しないということなのでFOREGROUNDで実行するってこと。だからDockerfileのCMDに-D FOREGROUNDと入れてるんですね。

ubuntuのnginxでIPベースのリバースプロキシを設定する方法

Dockerを使ったお手軽PaaS環境を作ろうと考えています。最近だとDokkuというものあるけど、いろいろソフトウェアをインストールしたりしたいので、俺俺PaaS環境を整えたいのです。

そのためにリバースプロキシを用意しようと考えています。今まではApacheしか使ったこと無かったけれども、どうも最近はnginxの方が人気があるみたいだし、そっちをそろそろ勉強がてら使い始めてみようかと思ってます。

ということで、まずはnginxのインストール

$ sudo apt-get install nginx

設定ファイルは/etc/nginx/に配置されているけど、この下を直接設定するのではなくて、/etc/nginx/conf.d/の下にファイルをおくと自動的に読み込んでくれる。なので、今回は設定するホストごとにファイルをおくことで管理しやすくする。/etc/nginx/conf.d/server1.confというファイル名で下記の内容でファイルを作成する。

server {
  listen    172.16.35.2:80; # IP:PORT とすることで特定のIPとポートのIPベースのバーチャルホストを設定できる
  location / {
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://localhost:49153; # 実際はここのURLのページ内容が返される
  }
}

参考:http://wiki.nginx.org/LikeApache

あとはnginxのリロードを行えば良い。

sudo service nginx reload

ハイパフォーマンスHTTPサーバ Nginx入門

ハイパフォーマンスHTTPサーバ Nginx入門