jwilder/nginx-proxyという超便利コンテナがあるのですが,こいつは/var/run/docker.sock
をReadOnlyとはいえ外側に晒すコンテナにマウントすることになり怖いので,推奨されているようにjwilder/docker-genとnginxを分けて同様の環境を構築します.
環境
- Ubuntu Server 16.04LTS
- Docker version 1.13.0
- docker-compose version 1.8.0
構築したい環境
macvlanドライバを用いたフロントのnginxへの静的IPアドレスの割り当て,及びdocker-genとJrCs/docker-letsencrypt-nginx-proxy-companionの機能を用いた各コンテナへのサブドメインの割り当てとSSL対応.(2)でgitlabを立ち上げて完成とします.
前準備
静的アドレス割り当て
まず,うちの環境ではこれまでYAMAHA RTX1200を使って,LXCで構築した外側に晒すコンテナ群のセグメントを分けて運用していました.つまり,それぞれのコンテナに対してブリッジを用いて静的なIPアドレスを割り当てていました.そしてルータのIPマスカレードでそれぞれのコンテナへとパケットを通していました.
しかしDockerで静的なIPを割り当てる方法を検索しても,直接NICの下にぶら下げる方法はあまり出てきませんでした.
そこで先輩に教えていただいたのがdocker networkのmacvlanドライバです.
これを用いてdocker networkを作り,それぞれのコンテナへとホストに割り当てられているものと同じ空間の静的なipv4アドレスを割り当てることが出来ました.
まず,ホストのNIC(何も使われていない余っているもの.以下hoge)をプロミスキャスモードにし,network create
します.
$ docker network create --driver macvlan \ --subnet=xxx.xxx.x.x/24 \ --gateway=xxx.xxx.x.y \ -o parent=hoge dmz_nw
docker-composeでのipの割り当て方は以下の様にします.
version: "2" services: front_test: image: nginx container_name: front_test networks: dmz_nw: ipv4_address: xxx.xxx.x.z networks: dmz_nw: external: name: dmz_nw
ブラウザからxxx.xxx.x.z
にアクセスしてWelcome to Nginx
が出てこれば成功です.
各コンテナを繋ぐネットワークの作製
macvlanドライバを用いると,gateway(ルータ)に直接問い合わせをするためdockerの名前解決は使えない*1ため,docker-genの機能を活用するために別のbridgeドライバを用いたnetworkを作製します*2.
$ docker network create --driver bridge \ -o "com.docker.network.bridge.name"="shared" \ shared
nginxとdocker-genを組み合わせる
ディレクトリ構造は以下の様にして進めます.
. ├── docker-compose.yml ├──proxy │ ├── certs │ ├── conf │ │ └── default.conf │ ├── html │ ├── templates │ │ └── nginx.tmpl │ └── vhost │ └── default └── web └── Dockerfile
nginxの設定
docker-compose.ymlに記述していきます.
version: "2" services: proxy: image: nginx container_name: proxy # そのままではコンテナ名が面倒なことになるので指定 volumes: - ./proxy/html:/usr/share/nginx/html:rw - ./proxy/conf:/etc/nginx/conf.d - ./proxy/vhost:/etc/nginx/vhost.d - ./proxy/certs:/etc/nginx/certs:ro # ReadOnlyでマウント restart: always networks: shared: aliases: - proxy dmz_nw: ipv4_address: xxx.xxx.x.N networks: shared: external: name: shared dmz_nw: external: name: dmz_nw
/usr/share/nginx/html
をrw
でマウントしないとなぜかJrCs/docker-letsencrypt-nginx-proxy-companionがエラーを吐きました.
docker-genの設定
本来はnginx-proxyに含まれているnginx.tmplファイルが必要となるので落としてきます.
$ curl https://raw.githubusercontent.com/jwilder/nginx-proxy/master/nginx.tmpl > ./proxy/templates/nginx.tmpl
nginxの設定に追記していきます.
version: "2" services: proxy: # 省略 nginx-gen: image: jwilder/docker-gen:latest container_name: nginx-gen volumes: - /var/run/docker.sock:/tmp/docker.sock:ro # ReadOnlyでマウント - ./proxy/templates/nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl:ro # tmplファイルをマウント volumes_from: - proxy restart: always entrypoint: /usr/local/bin/docker-gen -notify-sighup proxy -watch -wait 5s:30s /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf networks: - shared networks: # 省略
letsencryptの設定
version: "2" services: proxy: # 省略 nginx-gen: # 省略 letsencrypt: image: jrcs/letsencrypt-nginx-proxy-companion container_name: nginx-letsencrypt volumes_from: - proxy volumes: - /var/run/docker.sock:/var/run/docker.sock:ro # ReadOnlyでマウント - ./proxy/certs:/etc/nginx/certs:rw environment: NGINX_DOCKER_GEN_CONTAINER: nginx-gen depends_on: - nginx-gen restart: always networks: - shared networks: # 省略
webサーバをぶら下げてみる
以下,webサーバをぶら下げるアドレスをwww.hoge.com
として進めます.
設定
version: "2" services: proxy: # 省略 nginx-gen: # 省略 letsencrypt: # 省略 web: build: ./web container_name: web environment: VIRTUAL_HOST: www.hoge.com VIRTUAL_NETWORK: shared LETSENCRYPT_HOST: www.hoge.com LETSENCRYPT_EMAIL: hoge@mail.hoge.com depends_on: - nginx-gen - proxy restart: always networks: - shared networks: # 省略
web
ディレクトリ以下のDockerfileを編集しますが,これはgithubリポジトリに自分のwebサーバの静的ファイルを置いているためで必須ではないです.
FROM nginx:latest RUN apt update && \ apt install -y git && \ rm -r /usr/share/nginx/html && \ git clone https://github.com/pddg/poyo_web.git /usr/share/nginx/html
立ち上げてみる
$ docker-compose up --build
最初letsencryptでの証明書の取得に時間がかかります.うまく立ち上がったっぽい雰囲気を感じたらwww.hoge.com
にアクセスしてみて,うまく表示されれば完了です.
まとめ
RTX1200でフィルターを使ってアクセスに制限をかけているとはいえ,macvlan以下にぶら下げたコンテナは何の防御もしていないため,もう少し何かするべきかもしれませんがとりあえずはここまで.
かなり身構えてやり始めましたが,2~3時間で思っていたものが出来上がったので良かったです.
今回は全て同じdocker-compose.ymlに記述しましたが,上記で使用したshared
ネットワークにさえ接続すれば,docker run
でも,他のdocker-compose.ymlでも,VIRTUAL_HOST
など各種の環境変数を与えることでサブドメインの割り当てが出来ます.
もう少ししたらgitlabを立ち上げてgitlab.hoge.com
へとhttpsでアクセスできるようにした記事を書きたいと思います.
続き書きました