この記事は Docker Advent Calendar 2017 の12日目です。
昨日は vankobe さんの「golangでdockerをはじめる ~ goのwebサーバーをdockerでたててみた ~」でした。
はじめに
巷には便利なオープンソースのアプリケーションが溢れている。試してみたいものが山ほどあるが、その度に仮想マシンを用意したりデータベースの設定をしたりと、何かと手間がかかる。
そこで今回は Docker + docker-compose + nginx-proxy を利用して、ウェブアプリを気軽に動かしてみよう。
docker-compose とは
複数の Docker コンテナをよしなに起動してくれるツール。
nginx-proxy とは
同じ環境下で動いている Docker コンテナ上の Web サーバを見つけて、自動的にリバースプロキシを設定してくれるコンテナ。
用意するもの
- Docker を動かすための適当なサーバ (VM で OK)
下準備
まず Docker が動く環境を用意する。既にある場合は読み飛ばしてください。
CoreOS のインストール
VMware ESXi 上に、仮想マシンとして CoreOS をインストールする。
まずは公式サイトから iso イメージを落としてくる。今回は Stable の coreos_production_iso_image.iso
を使う。
iso イメージを仮想マシンにマウントし、起動する。
この状態では、まだインストールされていない。とりあえず 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
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
を使う。
$ 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
ファイルを用意する。
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 を書く。
出来上がったものがこちらです。
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/
動いてる!
おわりに
docker-compose + nginx-proxy を使って、ウェブアプリを手軽に動かすことができた。Dockerfile が用意されているアプリケーションなら、同じ要領で簡単に検証することができるだろう。
なお、CoreOS を入れたホストにグローバル IP アドレスが付いているなら、letsencrypt-nginx
というコンテナを併せて使うことで、Let's Encrypt の証明書もインストールすることができる。詳細はまた今後。