Dokcerコンテナ上に開発環境を作った時の反省点をふまえてやりなおします。
基本方針
- ConoHaのDockerイメージ上にalpine1をベースにしてサーバーを構築する
- この記事を分割しないでいいようにシンプルに書く
サーバー作成
ConoHaコントールパネルで「サーバー追加-アプリケーション-Docker」を選択して「追加」ボタン押下。
USキーボードを使っているので「VPS設定 - コンソールキーマップ - en-us」も選択してあります。
# uname -a
で確認するとUbuntu14.04.1
ベースです。今回はrootで作業します。bashrcにキーマップを登録しておきます。
- echo loadkeys us >> ~/.bashrc
- ~/.ssh/authorized_keysに鍵を登録
- /etc/ssh/sshd_configでパスワード禁止
PermitRootLogin without-password
- ローカルPCのLOCALEがsshで転送されるので日本語ファイルを入れておきます。
apt-get install language-pack-ja-base
確認のためローカルのPCからログインし、その後docker-composeをインストールします。
curl -L https://github.com/docker/compose/releases/download/1.6.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
dns
FROM alpine:latest
RUN apk --update add bind && rm -rf /var/cache/apk/*
EXPOSE 53
CMD ["named", "-c", "/etc/bind/named.conf", "-g", "-u", "named"]
named.confとdbファイルはdocker-compose.yamlでマウントします。
dns:
container_name: dns
build: dns
volumes:
- "./dns/bind:/etc/bind"
ports:
- "53:53"
- "53:53/udp"
docker-compose.ymlを書いたらdocker-compose up -d
で起動します。-d
を付けなければフォアグラウンドで起動して出力を見ることが出来ます。これにdocker exec -it dns bash
で接続して動作確認します。この後に出てくるコンテナもこの方式で確認していきます。
しかしコンテナ内でnslookup dns.example.com 127.0.0.1
しても外部のdnsを見にいってしまいハマりました。alpineで使用しているbusyboxのnslookupにはバグがありserver指定が効かないようです。Dockerホストのnslookupから動作確認しました。
参考:bugs.busybox.net
http
FROM alpine:latest
RUN apk --update add nginx && rm -rf /var/cache/apk/*
RUN chmod 755 /var/lib/nginx /var/lib/nginx/tmp
CMD ["nginx", "-g", "daemon off;"]
無駄にハマったのがapkでnginxを入れた直後は/var/lib/nginxのパーミッションがdrwx------ root root
になっており、リバースプロキシする時に4kb以上のファイルがあると
open() "/var/lib/nginx/tmp/proxy/1/00/0000000001" failed (13: Permission denied) while reading upstream, client:
のようなエラーを吐いてうまくいかないことです。Dockerfileにchmodを書いて解決しました。
http:
container_name: http
build: http
volumes:
- "./http/nginx.conf:/etc/nginx/nginx.conf"
- "./http/conf.d:/etc/nginx/conf.d"
ports:
- "80:80"
apkで取得したnginx.confではserver{}の中にlistenが指定されているため、前回のgitbucket/jenkinsの設定は読み込めませんでした。デフォルトからコメント行とlisten行を削除し、conf.dのincludeとuploadサイズの設定を入れたものがこちらです。
#user nobody;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
server_name localhost;
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
# add
include /etc/nginx/conf.d/*.conf;
client_max_body_size 50m;
}
GitBucket
Alpineベースのf99aq8ove/docker-gitbucketを使います。
gitbucket:
image: "f99aq8ove/gitbucket"
container_name: gitbucket
volumes:
- "./gitbucket/data:/gitbucket"
- "/etc/localtime:/etc/localtime:ro"
ports:
- "8080:8080"
Jenkins
前回はJenkinsコンテナにXvfbやらfirefoxを入れていたのですが、それはJenkinsのスレーブノードにやらせればよさそうなので今回はJenkins単体にします。
参考:Docker ComposeでJenkinsとSelenium Gridを一気に立ち上げる
mkdir -p jenkins/data
chown 1000:1000 jenkins/data
jenkins:
image: "blacklabelops/jenkins:alpine"
container_name: jenkins
volumes:
- "./jenkins/data:/jenkins"
ports:
- "8081:8080"
smtp/pop/imapを一つのコンテナに立てます。docker的には1コンテナ1サービスが原則だと思いますが、特に送信サーバーをスケールする予定もないしどうせrsyslogdもあげるのでまとめてしまいました。
FROM alpine:latest
RUN apk --update add postfix dovecot rsyslog && rm -rf /var/cache/apk/*
ADD main.cf /etc/postfix/main.cf
ADD valias /etc/postfix/valias
ADD vmailbox /etc/postfix/vmailbox
RUN postmap /etc/postfix/valias
RUN postmap /etc/postfix/vmailbox
ADD 10-auth.conf /etc/dovecot/conf.d/10-auth.conf
ADD 10-mail.conf /etc/dovecot/conf.d/10-mail.conf
ADD auth-passwdfile.conf.ext /etc/dovecot/conf.d/auth-passwdfile.conf.ext
CMD ["sh", "-c", "rsyslogd; postfix start; dovecot; tail -f /dev/null;"]
alpineベースにpostfixとdovecotを入れ、バーチャルホストを使った複数ドメイン対応設定です。
mydomain = example.com
inet_interfaces = all
virtual_mailbox_domains = example.com, example.jp
virtual_mailbox_base = /var/spool/mail/vhosts
virtual_mailbox_maps = hash:/etc/postfix/vmailbox
virtual_alias_maps = hash:/etc/postfix/valias
virtual_minimum_uid = 89
virtual_uid_maps = static:89
virtual_gid_maps = static:89
recipient_delimiter = -
alias user@example.com
user@example.com example.com/user
user@example.jp example.jp/user
alpineではデフォルトでuid:89がvpopmailになっています。この権限でバーチャルホスト用のフォルダを用意し読み書きさせます。postfixではdbファイルの作成にpostmapコマンドを実行する必要があるので、DockerfileでRUNさせます。
以下dovecot用設定ファイルです。
disable_plaintext_auth = no
gmailからアクセスするのにSSLだと自己署名の証明書が使えないので、plaintextを許可してます。
mail_location = maildir:~/
namespace inbox {
inbox = yes
}
mail_uid = 89
mail_gid = 89
first_valid_uid = 89
first_valid_gid = 89
mbox_write_locks = fcntl
maildirの設定とuidの指定を行います。
passdb {
driver = passwd-file
args = /var/spool/mail/vhosts/passwd
}
userdb {
driver = passwd-file
args = /var/spool/mail/vhosts/passwd
}
user@example.com:{CRYPT}xxx::::/var/spool/mail/vhosts/example.com/user:/sbin/nologin
アカウントファイルの設定です。vhostsはpostfixのvirtual_mailbox_baseになっていて、postfixがここに配送したメールをdovecotが受け取ります。
mail:
container_name: mail
build: mail
volumes:
- "./mail/vhosts:/var/spool/mail/vhosts"
- "/etc/localtime:/etc/localtime:ro"
ports:
- "25:25"
- "110:110"
- "143:143"
- "993:993"
- "995:995"
まとめ
最終的なdocker-compose.yml
dns:
container_name: dns
build: dns
volumes:
- "./dns/bind:/etc/bind"
- "/etc/localtime:/etc/localtime:ro"
ports:
- "53:53"
- "53:53/udp"
http:
container_name: http
build: http
volumes:
- "./http/nginx.conf:/etc/nginx/nginx.conf"
- "./http/conf.d:/etc/nginx/conf.d"
- "./http/public_html:/usr/share/nginx/html"
- "/etc/localtime:/etc/localtime:ro"
ports:
- "80:80"
gitbucket:
image: "f99aq8ove/gitbucket"
container_name: gitbucket
volumes:
- "./gitbucket/data:/gitbucket"
- "/etc/localtime:/etc/localtime:ro"
ports:
- "8080:8080"
jenkins:
image: "blacklabelops/jenkins:alpine"
container_name: jenkins
volumes:
- "./jenkins/data:/jenkins"
- "/etc/localtime:/etc/localtime:ro"
ports:
- "8081:8080"
mail:
container_name: mail
build: mail
volumes:
- "./mail/vhosts:/var/spool/mail/vhosts"
- "/etc/localtime:/etc/localtime:ro"
ports:
- "25:25"
- "110:110"
- "143:143"
- "993:993"
- "995:995"
自分で立てたサーバーの設定資料としてまとめたのですが、dnsやmailの設定情報をちゃんと載せてないので、後からこの資料だけ見て同じサーバーを立てるのは厳しいですね。
alpineは情報が少ないのと、apkがこなれてなくてデフォルトだとうまく動かないといったことがあり注意が必要です。
-
2022/01追記 今は各ディストリビューションがcompactをリリースしてるのでAlpineを使うメリットは少ないです。libc非互換のバグとか踏みたくなければubuntuやdebial-slimでいいでしょう。ubuntu公式で30MiBくらいです。Alpineは5MiBですがライブラリ追加したら誤差の範囲、かな。大量のcontainerを扱うので少しでも小さい方がいい、という場合はAlpineやscratchから作るのもありですね。実行ファイルをstatic linkでコンパイルしてscratchに入れてる記事を見ましたが、それならdockerにしないで実行ファイルのまま配布すればいいのでは?ギャグのつもりなんでしょうけど。 ↩