Edited at
DockerDay 12

docker-compose + nginx-proxy でウェブアプリ楽々検証

More than 1 year has passed since last update.

この記事は Docker Advent Calendar 2017 の12日目です。

昨日は vankobe さんの「golangでdockerをはじめる ~ goのwebサーバーをdockerでたててみた ~」でした。


はじめに

巷には便利なオープンソースのアプリケーションが溢れている。試してみたいものが山ほどあるが、その度に仮想マシンを用意したりデータベースの設定をしたりと、何かと手間がかかる。

そこで今回は Docker + docker-compose + nginx-proxy を利用して、ウェブアプリを気軽に動かしてみよう。


docker-compose とは

複数の Docker コンテナをよしなに起動してくれるツール。

https://docs.docker.com/compose/


nginx-proxy とは

同じ環境下で動いている Docker コンテナ上の Web サーバを見つけて、自動的にリバースプロキシを設定してくれるコンテナ。

https://github.com/jwilder/nginx-proxy


用意するもの


  • Docker を動かすための適当なサーバ (VM で OK)


下準備

まず Docker が動く環境を用意する。既にある場合は読み飛ばしてください。


CoreOS のインストール

VMware ESXi 上に、仮想マシンとして CoreOS をインストールする。

まずは公式サイトから iso イメージを落としてくる。今回は Stable の coreos_production_iso_image.iso を使う。

https://coreos.com/os/docs/latest/booting-with-iso.html

iso イメージを仮想マシンにマウントし、起動する。

coreos01.png

この状態では、まだインストールされていない。とりあえず ssh で入れるように、core ユーザにパスワードを設定し、ネットワークの設定をする (NIC の名前や IP アドレスは適宜読み替え)。

$ sudo passwd core

(適当なパスワード)
$ sudo ifconfig ens32 192.168.0.10/24
$ sudo route add default gw 192.168.0.1
$ sudo sh -c 'echo "nameserver 8.8.8.8" > /etc/resolv.conf'

この VM に到達できるネットワーク環境から、ssh でログインする。

ログインできたら、ホームディレクトリ直下に、インストール情報を設定するファイル cloud-config.yaml を作成する。


~/cloud-config.yaml

#cloud-config

hostname: coreos

write_files:
- path: /etc/systemd/network/10-static.network
permissions: 0644
content: |
[Match]
Name=ens32
[Network]
Address=192.168.0.10/24
Gateway=192.168.0.1
DNS=8.8.8.8

ssh_authorized_keys:
- ssh-rsa AAAAB3N...



  • 1行目の #cloud-config は必須


  • hostname は適当に設定


  • ssh-rsa AAAAB3N... の箇所には、ssh でログインする元のマシンの公開鍵を記述

そしてディスクに CoreOS をインストールする (今回は /dev/sda)。

$ sudo coreos-install -d /dev/sda -C stable -c ~/cloud-config.yaml

インストールが終わったら OS を再起動する。

$ sudo reboot

※ 1回再起動しただけだと、なぜか IP アドレスを DHCP から取ってきてしまったので、2回再起動した。


docker-compose のインストール

CoreOS が入ったので、次に docker-compose をインストールする。

公式の GitHub レポジトリから適当なバージョンを選ぶ。今回は 1.17.1 を使う。

https://github.com/docker/compose/releases/

$ sudo mkdir -p /opt/bin

$ curl -L "https://github.com/docker/compose/releases/download/1.17.1/docker-compose-Linux-x86_64" \
| sudo tee /opt/bin/docker-compose > /dev/null
$ sudo chmod +x /opt/bin/docker-compose

入ったかどうか確かめる。

$ docker-compose

Define and run multi-container applications with Docker.

Usage:
docker-compose [-f <arg>...] [options] [COMMAND] [ARGS...]
docker-compose -h|--help

Options:
-f, --file FILE Specify an alternate compose file (default: docker-compose.yml)
-p, --project-name NAME Specify an alternate project name (default: directory name)
--verbose Show more output
--no-ansi Do not print ANSI control characters
-v, --version Print version and exit
-H, --host HOST Daemon socket to connect to

--tls Use TLS; implied by --tlsverify
--tlscacert CA_PATH Trust certs signed only by this CA
--tlscert CLIENT_CERT_PATH Path to TLS certificate file
--tlskey TLS_KEY_PATH Path to TLS key file
--tlsverify Use TLS and verify the remote
--skip-hostname-check Don't check the daemon's hostname against the name specified
in the client certificate (for example if your docker host
is an IP address)
--project-directory PATH Specify an alternate working directory
(default: the path of the Compose file)

Commands:
build Build or rebuild services
bundle Generate a Docker bundle from the Compose file
config Validate and view the Compose file
create Create services
down Stop and remove containers, networks, images, and volumes
events Receive real time events from containers
exec Execute a command in a running container
help Get help on a command
images List images
kill Kill containers
logs View output from containers
pause Pause services
port Print the public port for a port binding
ps List containers
pull Pull service images
push Push service images
restart Restart services
rm Remove stopped containers
run Run a one-off command
scale Set number of containers for a service
start Start services
stop Stop services
top Display the running processes
unpause Unpause services
up Create and start containers
version Show the Docker-Compose version information

$ docker-compose version

docker-compose version 1.17.1, build 6d101fb
docker-py version: 2.5.1
CPython version: 2.7.13
OpenSSL version: OpenSSL 1.0.1t 3 May 2016

うまく動いてそうだ。


nginx-proxy コンテナのインストール

docker-compose が使えるようになったので、次に nginx-proxy コンテナをインストールする。

$ mkdir -p ~/docker-compose.d/nginx-proxy    # 適当なディレクトリを掘る

$ cd ~/docker-compose.d/nginx-proxy

docker-compose.yml ファイルを用意する。


docker-compose.yml

version: '2'

services:
nginx-proxy:
image: jwilder/nginx-proxy:latest
container_name: nginx-proxy
privileged: true
ports:
- 80:80
volumes:
- ./data/htpasswd:/etc/nginx/htpasswd
- ./data/conf.d:/etc/nginx/conf.d
- /etc/nginx/vhost.d
- /usr/share/nginx/html
- /var/run/docker.sock:/tmp/docker.sock:ro
network_mode: "bridge"
restart: always


ポイントは network_mode: "bridge" を付けること (これを書かないと nginx-proxy が他のコンテナを見つけられなかった)。

docker-compose で nginx-proxy コンテナを起動する。

$  docker-compose up -d

以上で docker-compose + nginx-proxy が使えるようになった。


使ってみる


コンテナの起動

docker-compose + nginx-proxy を使う準備が整ったので、適当なウェブアプリを起動してみよう。今回は Zabbix にする。

公式の Dockerfile を参考にしつつ、docker-compose.yml を書く。

https://hub.docker.com/u/zabbix/

出来上がったものがこちらです。


docker-compose.yml

version: '2'

services:
mysql:
image: mysql:5.7
command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci
volumes:
- ./data/mysql:/var/lib/mysql
expose:
- "3306"
environment:
MYSQL_ROOT_PASSWORD: docker
MYSQL_DATABASE: zabbix
MYSQL_USER: zabbix
MYSQL_PASSWORD: zabbix
network_mode: "bridge"

zabbix-server:
image: zabbix/zabbix-server-mysql:alpine-3.2-latest
volumes:
- ./data/zabbix:/var/lib/zabbix
environment:
DB_SERVER_HOST: mysql
MYSQL_USER: zabbix
MYSQL_PASSWORD: zabbix
expose:
- "10051"
depends_on:
- mysql
links:
- mysql
network_mode: "bridge"

zabbix-web:
image: zabbix/zabbix-web-nginx-mysql:alpine-3.2-latest
environment:
VIRTUAL_HOST: zabbix.example.com
VIRTUAL_PORT: 80
DB_SERVER_HOST: mysql
MYSQL_USER: zabbix
MYSQL_PASSWORD: zabbix
ZBX_SERVER_HOST: zabbix-server
TZ: Asia/Tokyo
expose:
- "80"
depends_on:
- mysql
- zabbix-server
links:
- mysql
- zabbix-server
network_mode: "bridge"

zabbix-agent:
image: zabbix/zabbix-agent:alpine-latest
environment:
ZBX_SERVER_HOST: zabbix-server
expose:
- "10050"
depends_on:
- zabbix-server
links:
- zabbix-server
privileged: true
network_mode: "bridge"


ポイントは以下の通り。


  • ウェブサーバのコンテナの環境変数 VIRTUAL_HOST に、リバースプロキシに設定したいホスト名を書く。

  • 同じく VIRTUAL_PORT には、コンテナによって EXPOSE されるウェブサーバのポート番号を書く (今回は 80)。

  • すべてのコンテナに network_mode: "bridge" を書く。

なお VIRTUAL_HOST に書くホスト名は、あらかじめ Docker のホストの IP アドレスに DNS で A レコードを設定しておく。ワイルドカードで書くと楽だと思う。

そして各コンテナを起動する。

$ docker-compose up -d

起動したか確認する。

$ docker-compose ps

Name Command State Ports
------------------------------------------------------------------------------------
zabbix_mysql_1 docker-entrypoint.sh mysql ... Up 3306/tcp
zabbix_zabbix-agent_1 /bin/bash /run_zabbix_comp ... Up 10050/tcp
zabbix_zabbix-server_1 /bin/bash /run_zabbix_comp ... Up 10051/tcp, 162/udp
zabbix_zabbix-web_1 /bin/bash /run_zabbix_comp ... Up 443/tcp, 80/tcp


アクセス

起動した zabbix-web コンテナに、nginx-proxy 経由でアクセスしてみる。

あらかじめ設定しておいたホスト名 (上記の例なら zabbix.example.com) に Web ブラウザでアクセスする。

http://zabbix.example.com/

zabbix01.png

動いてる!


おわりに

docker-compose + nginx-proxy を使って、ウェブアプリを手軽に動かすことができた。Dockerfile が用意されているアプリケーションなら、同じ要領で簡単に検証することができるだろう。

なお、CoreOS を入れたホストにグローバル IP アドレスが付いているなら、letsencrypt-nginx というコンテナを併せて使うことで、Let's Encrypt の証明書もインストールすることができる。詳細はまた今後。