今年の春くらいにWEB+DBの「サーバ/インフラ徹底攻略 (WEB+DB PRESS plus)」を読み、イミュータブルインフラストラクチャというものに興味が湧いた。そこで、これまではBitnami StacksでOSXに直接インストールしていたWebアプリケーションを、VagrantとDockerで不変なものに置き換えてみることにした。
※スライド版資料もあります →Dockerで楽しむ自宅サーバ
2016-02-15追記
紹介しているサーバ構成の簡易版をgithubにアップロードしました。自宅と全く同じ構成ではありませんが(非SSL・内部ネットワーク化など)、VagrantとOSXさえあれば動作するようになっています。 →デモ用Vagrantfile + docker-compose.yml
最終的に出来上がったシステムの俯瞰図
設定ファイルの一覧
├── Vagrantfile
├── config.rb
├── docker-compose.yml
├── user-data
├── /proxy
│ ├── Dockerfile
│ ├── /conf
│ │ └── nginx.conf
│ ├── /html
│ │ └── index.html
│ └── /ssl
│ ├── server.crt
│ └── server.csr
├── /lychee
│ ├── Dockerfile
│ └── /conf
└── /resourcespace
├── Dockerfile
└── /conf
筆者スペック
インフラについてはほぼ素人。Vagrantはちょっと使ったことある。普段の制作でCLIを使うことには慣れているものの、LinuxやDockerに関する事前知識はほとんどない。
- 本業はフロントエンドやデザイン
- OSXのコマンドラインは少し使えるが、Linuxは触ったことない
- ITパスポートなら持ってる
やりたかったこと
- 複数のWebアプリケーションを自宅サーバ内に構築し、どこからでも使いたい
- 1つのIPアドレスに複数のWebアプリケーションを集約したい
- 必要なデータは1つのファイルに隔離し、バックアップを簡単にしたい
- すべての設定を1つのGitリポジトリに集約させ、データ以外はそこから全て復旧できるようにしたい
- 以下のアプリケーションをインストールしたい
| アプリケーション | 機能 |
|:--|:--|:--|
| Redmine | Issueトラッキング・システム |
| ResourceSpace | DAMシステム |
| Gitbucket | GitHubクローン |
| Libreboard | Trelloクローン |
| manet | Webサイトのスクリーンショット作成|
| Lychee | 写真管理アプリケーション |
| Etherpad | リアルタイム同期テキストエディタ |
| EtherCalc | リアルタイム同期スプレッドシート |
※Redmine, Gitbucket, Libreboard, manet, EtherCalcについては「Dockerで即実行できる、社内・自宅向けオープンソースWebアプリ」でも詳しく紹介
※ResourceSpaceについては「オープンソースのDAMシステム、ResourceSpaceのまとめ」でも詳しく紹介
どうやって実現するか
自宅サーバは直接公開せず、VPN経由でアクセスする
セキュリティのことを考えると話が複雑になるので、今回はパス。サーバにはMacOSX ServerのVPN機能を使ってアクセスする。
VirtualBox + Vagrantで仮想化する
仮想マシンの設定はVagrantfile内で完結させる。
CoreOSを使う
UbuntuやCentOSのような普通のLinuxよりも今回の目的に向いていそうに思ったので、これを使うことにした。
- 公式でVagrantfileが配布されていてインストールが簡単
- OS自体が仮想環境上で短時間に生成→破棄のサイクルを繰り返すこと前提に作られており、システムの設定が1ファイルに集約されている
- Dockerがデフォルトでインストールされている
- 余計なツールが一切インストールできないので、問題の切り分けが楽そう
Dockerコンテナのオーケストレーションにdocker-compseを使用する
docker-composeを使うと複数コンテナの管理が便利に
リバースプロキシを構成し、1つのURLへ複数のWebサービスをまとめる
リバースプロキシというものを使うことで、複数のWebサービスを束ねて1つのURL化に構成することができる。nginx(エンジンエックス)というWebサーバがリバースプロキシとしての機能を持っているため、これを使う
「ホスト」が指す対象の定義
今後の文章では、OSX環境、仮想マシン内、仮想マシン内のDockerコンテナのことを次のように呼び分ける。
OSXから見たLinuxのゲストマシンが、コンテナ側からはDockerホストになることに注意。
VirtualBoxが動作するMacOSX環境 | VirtualBox内のCoreOS環境 | CoreOS内のDockerコンテナ内の環境 |
---|---|---|
ホスト | ゲスト 又は Dockerホスト | Dockerコンテナ |
感想
記事が長いので先に感想を記載する。
調べるべきことがすごく多かった
Dockerだけやれば済むくらいのつもりだったが、思った以上に調べないといけないことが多かった。インフラエンジニアってすごい!
- docker, docker-composeの使い方の理解
- VirtualBox特有の機能・概念の理解
- Vagrantfileの書き方・簡単なrubyの構文の意味の理解
- シェルスクリプトの書き方
- systemdの設定ファイル(user-data)の書き方
- nginxの設定ファイル(nginx.conf)の書き方
- DockerHub上にある各イメージの使い方
- 各Webアプリケーションの設定の書き方
永続化データをいかに分離するかが鍵かも
Vagrantfile・docker-compose・user-dataにすべての設定が集約されている為、このgitリポジトリさえあればサーバ環境を簡単に作り直すことができる。ミドルウェアのバージョンアップをしたくなったら、dockerfileでpullしてくるバージョン番号を上げるだけで完了してしまう。
問題は消えてしまっては困る永続化データの部分で、これをちゃんと分離しないと気軽に環境の破棄ができず、vagrantやdockerの魅力が半減してしまう。
はじめは、dockerコンテナからVMの共有フォルダを通して直接OSXのディレクトリにファイルを書き込む運用を考えたが、パーミッションが弱く使えなかった。ほとんどのコンテナでは初期化時にchownを必要とする。
しかし、普通にdocker run -v
オプションを使うと、仮想マシン内へ直接データが蓄積されてしまう。
これは嫌なので、データ保存先を専用のVirtualBoxのディスクイメージに変更。ディスクイメージはvagrant up
時に自動で作成・初期化、又は、既に存在する場合は自動で仮想マシンにアタッチするようにVagrantfileを記述した。
リバースプロキシの設定がはまりどころ
最後の方の段階での、リバースプロキシ(nginx)でWebアプリケーションをサブディレクトリにマップする設定ははまりどころが多かった。次のようなことが起こり泣きそうになった。
- Webアプリケーション自体にはアクセスできているのに、フロントエンドのパスが通っておらずCSSが適用されない
- 一見問題なく動作しているが、ログインやログアウトのリダイレクト時に、サブディレクトリを無視したアドレスへ飛ばされる
Webアプリケーション側の設定が必要な場合もあれば、リバースプロキシ側で正しくヘッダ情報を飛ばしていないことが原因の場合もあった。
OSX側での事前準備
1.VirtualBoxとVagrantをインストール
Vagrant, Oracle VM VirtualBox
これがないと始まらない。
2. visudo
でvagrantにsudo権限を与える (オプション)
メモ:Vagrant の NFS synced folder でいちいちパスワード聞いてこなくするやつ
仮想マシンとホストマシンのファイル共有にNFSを使用すると、Vagrantで仮想マシンを立ち上げる度に管理者パスワードを求められる。Virtualboxにsudoの権限を与えておくと、シェルスクリプトでの自動起動ができるので使いやすい。visudoコマンドによってsudo可能なユーザーを編集することができる。
3. 仮想マシンの保存場所を差分バックアップに対応させる(オプション)
仮想マシンをTimeMachineで効率的にバックアップする方法
ディスクイメージは巨大なバイナリデータなので、そのままだとTimemMachineのバックアップ容量を無駄に消費してしまう。
スパース・バンドル形式で適当な可変サイズのディスクイメージを作成し、VirtualBoxの仮想マシン作成先をその中へ変更。このディスクイメージはスタートアップ時に自動でマウントする様にOSXの起動項目へ追加しておく。後のバックアップはTimeMachineにまかせる。
4. CoreOS公式のVagrantfileリポジトリをダウンロードする
coreos-vagrant/Vagrantfile at master · coreos/coreos-vagrant
この後、リポジトリ内のvagrantfile
とuser-config
を編集していく。
Vagrantfileのカスタマイズ
CoreOSの公式Vagrantfileは、Vagrantfile
本体とconfig.rb
に分離している。config.rb
にカスタマイズ部分を書き、Vagrantfile自体にはあまり手を加えなくとも使えるというのがその意図だろう。なるべくその意図を尊重してカスタマイズを行なったが、結局両方のファイルに変更を加えているため、1つにまとめてしまっても良いかもしれない。
以下、変更・追記箇所をポイントごとに解説。ファイル全体はgist記事を参照。
https://gist.github.com/hokkey/f29492503b485ea8d414
1. ホスト・ゲスト間のファイル共有を設定
# Share additional folders to the CoreOS VMs
# For example,
# $shared_folders = {'/path/on/host' => '/path/on/guest', '/home/foo/app' => '/app'}
# or, to map host folders to guest folders of the same name,
# $shared_folders = Hash[*['/home/foo/app1', '/home/foo/app2'].map{|d| [d, d]}.flatten]
$shared_folders = {'.' => '/home/core/dockerfiles'}
config.rbが含まれるディレクトリへ、CoreOSの内部からアクセスできるようにする。これでdockerの設定ファイルをゲストマシンから直接参照できるようになる。
このファイル共有にはMacOSXのNFSファイル共有機能が使われる為、マウントされた共有フォルダはNFS特有の制約を受ける。
結論から先に言うと、NFS経由ではrootはすごく弱くなる。
NFSの設定と動作 - HHeLiBeXの日記 正道編
NFSはアクセスする側の制約がかなり大きいので、この場所に直接Dockerコンテナからファイルを書き込んだりする運用は難しいのではないかと思う。やろうと思ったけど上手くいかなかった顛末をStackoverflowにまとめてある。
mysql - 仮想マシン上のCoreOSで、dockerの永続化データをホストとの共有フォルダに作成できず、権限エラーとなってしまう - スタック・オーバーフロー
2. ディスクイメージの自動作成とアタッチ
通常は1つの仮想ディスク内に全てのデータが格納される。しかし、データ管理の都合からDockerイメージと永続化データは通常のディスクイメージから分離することにした。
Dockerイメージを専用のディスクイメージに隔離する
DockerがDockerHubからイメージをpullしてくる時の保存場所を、外部ディスクとして分離する。これにより、仮想マシンを破棄しても再度大容量のイメージをダウンロードしてくる必要がなくなり、仮想マシンの再構築が手軽に行えるようになる。
このイメージ自体はなくなっても困るものではないので、バックアップしなくても構わない。
永続化データを専用のディスクイメージへ隔離する
永続化データを単独のディスクイメージに隔離することで、仮想マシンの破棄を手軽に行うことができるようになる。究極的にはこのディクイメージだけバックアップしておけば、他の部分はいつでも再構築ができる。
# 外部ストレージ
$attached_storages = [
{:file => './internal_data.vdi', :size => 100*1024, :port => 1, :device => 0, :dev => 'sdb', :dest => '/mnt/data'},
{:file => './internal_image.vdi', :size => 100*1024, :port => 1, :device => 1, :dev => 'sdc', :dest => '/var/lib/docker'}
]
# ストレージをフォーマットしてマウント
def format_storage(dev, dest)
fdisk = <<-EOF
(echo n; echo p; echo 1; echo ; echo ; echo w) | fdisk /dev/#{dev}
mkfs -t ext4 /dev/#{dev}1
mount -t ext4 /dev/#{dev}1 #{dest}
EOF
return fdisk
end
(1..$num_instances).each do |i|
# 途中省略
# 外部ストレージの作成と追加
if not File.exist?($attached_storages[0][:file]) then
init_storage = format_storage($attached_storages[0][:dev])
config.vm.provision :shell, :inline => init_storage, :privileged => true
end
if not File.exist?($attached_storages[1][:file]) then
init_storage = format_storage($attached_storages[1][:dev])
config.vm.provision :shell, :inline => init_storage, :privileged => true
end
config.vm.provider :virtualbox do |vb|
for data in $attached_storages
# 新規ストレージ作成
if not File.exist?(data[:file]) then
vb.customize ['createhd', '--filename', data[:file], '--size', data[:size]]
end
# ストレージをアタッチ
vb.customize ['storageattach', :id, '--storagectl', 'IDE Controller', '--port', data[:port], '--device', data[:device], '--type', 'hdd', '--medium', data[:file], '--setuuid', '']
end
end
Vagrantfileをカスタマイズして、ディスクイメージが在しない場合は自動的に作成されるようにした。
- イメージが存在しない場合は自動的にVDI形式の可変ディスクイメージを作成して仮想マシンに接続
- 初回起動時にフォーマットして初期化
- イメージが存在する場合は何もしない(アタッチされたまま)
ただし、マウントを設定しないとCoreOS側からはまだアクセスできない。CoreOS側の設定は後述のuser-data内に記述する。
vagrant destroy
するときの注意
ディスクイメージの分離はとても便利だが、一つだけ重要な問題がある。それは、vagrant destoryした時に、その仮想マシンに紐付く外部ディスクのイメージも同時に消されてしまうことだ。
仮想マシンをdestroyする時には、かならずディスクイメージの紐付けを解除してから行うようにしないと大変なことになってしまう。このあたりを上手くやれるようにする方法は現在も模索中。
3. 仮想マシンのメモリ・CPU数・チャンネルを設定
チャンネルとはcoreOSの更新状況を通知するもので、alpha版、beta版、stable版が選べる。alpha,betaはかなり頻繁に更新されている。筆者はリブートストラテジをoffにしているため、stable版を使うことにしている。リブートストラテジについてはuser-dataの項を参照。
# Customize VMs
$vm_gui = false
$vm_memory = 3072
$vm_cpus = 2
# Official CoreOS channel from which updates should be downloaded
$update_channel='stable'
- メモリが少なすぎるとMySQLが落ちたりする。中で動かすコンテナが多い場合はそれなりに確保する
4.ネットワーク設定
今回は公開ネットワークへブリッジし、仮想マシン自体のMACアドレスを使って外部のDHCPサーバからIPを固定する運用にした。
# 公開ネットワーク設定
$bridge = 'en0: Ethernet'
$mac_address = '000000000000'
(1..$num_instances).each do |i|
# 途中省略
# ネットワーク設定
config.vm.network :public_network, bridge: $bridge, mac: $mac_address
5.プロビジョニング
初回のプロビジョニング時にはdocker-compose
を自動でインストールするようにした。
# docker_composeをインストール
$install_docker_compose = <<-EOF
curl -L https://github.com/docker/compose/releases/download/1.2.0/docker-compose-`uname -s`-`uname -m` > ~/docker-compose
sudo mkdir /opt
sudo mkdir /opt/bin
sudo mv ~/docker-compose /opt/bin/docker-compose
sudo chown root:root /opt/bin/docker-compose
sudo chmod +x /opt/bin/docker-compose
EOF
(1..$num_instances).each do |i|
# 途中省略
# docker-composeをインストール
config.vm.provision :shell, :inline => $install_docker_compose, :privileged => true
OS起動後、常にdocker-compose-up -d
が走るスクリプトも記載した。
# docker_composeを起動する
$docker_compose_up = <<-EOF
cd /home/core/dockerfiles
docker-compose up -d
EOF
(1..$num_instances).each do |i|
# 途中省略
# docker-composeを実行(常に)
config.vm.provision :shell, :inline => $docker_compose_up, :run => 'always'
user-dataの構成
CoreOSのシステム環境設定はcloud-configというYAMLファイルへ記述するルールになっている。(Vagrant版ではuser-dataという名前になっているが、役割は同じ)
CoreOSではsystemdというサービスが動いていて、それがこのYAMLファイルの設定に沿ってシステムの設定をしてくれる仕組みらしい。
Systemd入門(1) - Unitの概念を理解する - めもめも
systemd超入門 | Developers.IO
自宅サーバとして使うにあたり、次のような設定を記述した。
#cloud-config
hostname: coreos
coreos:
update:
reboot-strategy: off
etcd:
addr: $public_ipv4:4001
peer-addr: $public_ipv4:7001
fleet:
public-ip: $public_ipv4
# flannel:
# interface: $public_ipv4
units:
- name: etcd.service
command: start
- name: fleet.service
command: start
# タイムゾーン
- name: timezone.service
command: start
content: |
[Unit]
Description=timezone
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/ln -sf ../usr/share/zoneinfo/Japan /etc/localtime
# マウント
- name: mnt-data.mount
command: start
content: |
[Mount]
What=/dev/sdb1
Where=/mnt/data
Type=ext4
- name: var-lib-docker.mount
command: start
content: |
[Unit]
Before=docker.service
[Mount]
What=/dev/sdc1
Where=/var/lib/docker
Type=ext4
# - name: docker-tcp.socket
# command: start
# enable: true
# content: |
# [Unit]
# Description=Docker Socket for the API
#
# [Socket]
# ListenStream=2375
# Service=docker.service
# BindIPv6Only=both
#
# [Install]
# WantedBy=sockets.target
write_files:
- path: /etc/resolv.conf
permissions: 0644
owner: root
content: |
nameserver 192.168.1.1
-
リブートストラテジをoffに
本当は自動アップデートしたいのだが、Vagrant側の操作で再起動させないと、ホストとのファイル共有が失われてしまう。アップデートが必要なことに気付いたらvagrant reload
することにした。
仮想マシンの内部から再起動コマンドを叩いて、Vagrantのファイル共有を維持する方法があったら是非知りたい……。
reboot-strategy: off
-
マウントの追加
先程説明した外部ディスクイメージをマウントするための設定を記述する。
nameとマウント先の名前が整合していないとルールが適用されない。
例として/mnt/data
へマウントしたい場合、設定の名前はname: mnt-data.mount
となる。なぜそんなルールなのかは分からなかったけど……
# マウント
- name: mnt-data.mount
command: start
content: |
[Mount]
What=/dev/sdb1
Where=/mnt/data
Type=ext4
- name: var-lib-docker.mount
command: start
content: |
[Unit]
Before=docker.service
[Mount]
What=/dev/sdc1
Where=/var/lib/docker
Type=ext4
-
DNSの追加
LAN内のDNSサーバを参照するようにした
write_files:
- path: /etc/resolv.conf
permissions: 0644
owner: root
content: |
nameserver 192.168.1.1
Dockerコンテナの構成
次のような内容のdocker-composeを作成した。
#
# data volume containers
#
data00mongo:
image: busybox:buildroot-2014.02
volumes:
- /data/mongo:/data/db
data00manet:
image: busybox:buildroot-2014.02
volumes:
- /tmp/manet
data00redis:
image: busybox:buildroot-2014.02
volumes:
- /mnt/data/redis:/data
data00gitbucket:
image: busybox:buildroot-2014.02
volumes:
- /mnt/data/gitbucket:/gitbucket
data00lychee:
image: busybox:buildroot-2014.02
volumes:
- /mnt/data/lychee/data:/data
- /mnt/data/lychee/uploads:/uploads
- /mnt/host/:/uploads/import
data00mysql:
image: busybox:buildroot-2014.02
volumes:
- /mnt/data/mysql:/var/lib/mysql
data00redmine:
image: busybox:buildroot-2014.02
volumes:
- /mnt/data/redmine/files:/home/redmine/data/files
- /mnt/data/redmine/plugins:/home/redmine/data/plugins
- /mnt/data/redmine/themes:/home/redmine/data/themes
data00resourcespace:
image: busybox:buildroot-2014.02
volumes:
- /mnt/data/resourcespace/filestore:/var/www/html/resourcespace/filestore
- /mnt/data/resourcespace/homeanim:/var/www/html/resourcespace/gfx/homeanim
#
# reverse proxy container
#
proxy:
build: proxy
links:
- manet:manet
- gitbucket:gitbucket
- etherpad:etherpad
- redmine:redmine
- resourcespace:resourcespace
- lychee:lychee
- ethercalc:ethercalc
- libreboard:libreboard
ports:
- "80:80"
- "443:443"
#
# db containers
#
mysql:
image: mysql:5.6.24
environment:
MYSQL_ROOT_PASSWORD: yourSecurePasswordHere
volumes_from:
- data00mysql
ports:
- "3306:3306"
redis:
image: redis:3.0.3
volumes_from:
- data00redis
command: redis-server --appendonly yes
mongo:
image: mongo:3.1.5
volumes_from:
- data00mongo
command: mongod --smallfiles
#
# application containers
#
etherpad:
image: tvelocity/etherpad-lite
links:
- mysql:mysql
environment:
ETHERPAD_ADMIN_PASSWORD: yourSecurePasswordHere
gitbucket:
image: f99aq8ove/gitbucket
ports:
- "29418:29418"
volumes_from:
- data00gitbucket
command: java -jar /opt/gitbucket.war --prefix=/gitbucket
lychee:
build: lychee
links:
- mysql:mysql
volumes_from:
- data00lychee
manet:
image: earlyclaim/docker-manet
volumes_from:
- data00manet
command: manet --storage /tmp/manet
redmine:
image: sameersbn/redmine:2.6.6-1
volumes_from:
- data00redmine
- data00gitbucket
links:
- mysql:mysql
environment:
REDMINE_HTTPS: true
REDMINE_RELATIVE_URL_ROOT: /redmine
DB_USER: root
DB_NAME: redmine
DB_PASS: yourSecurePasswordHere
#SMTP_USER: hoge@hoge
#SMTP_PASS: hoge
resourcespace:
build: resourcespace
links:
- mysql:mysql
volumes_from:
- data00resourcespace
ethercalc:
image: audreyt/ethercalc:latest
links:
- redis:redis
command: ["sh", "-c", "REDIS_HOST=$REDIS_PORT_6379_TCP_ADDR REDIS_PORT=$REDIS_PORT_6379_TCP_PORT pm2 start -x `which ethercalc` -- --cors --basepath /ethercalc/ && pm2 logs"]
libreboard:
image: miurahr/libreboard:20150503
environment:
MONGO_URL: mongodb://mongo:27017/libreboard
ROOT_URL: https://service.home.private/
links:
- mongo:mongo
ports:
- 8080:5555
データボリュームコンテナの作成
ファイル冒頭部で作成している「data00〜」がデータボリュームコンテナ。Dockerホスト側のマッピング先を永続化データ用のマウントポイントに設定することで、永続化データをディスクイメージファイルに隔離している。
自分でDockerfileを作成したコンテナ
これら以外のアプリケーションはDockerHubのイメージをそのまま使っている。
ResourceSpace
Michael Harrisさんが公開しているdockerfile一式をダウンロードし、少しカスタマイズして使用した。
https://github.com/michael-harris/resourcespace-docker/blob/master/Dockerfile
カスタマイズの内容はResourceSpaceに関係することなので割愛する。
Lychee
neosarさんが公開しているdockerfile一式をダウンロードし、少しカスタマイズして使用した。
https://hub.docker.com/r/neosar/lychee-docker/~/dockerfile/
カスタマイズの内容はLycheeに関係することなので割愛する。
nginx
複数のWebアプリケーションを同時に動作させたい場合、1つの仮想マシン内に複数のポート番号でサーバを立ち上げることになる。そのままでも良いのだが、デフォルトのポート番号でアクセスし、各アプリケーションへサブディレクトリでアクセスできる構成の方がそれらしい。そのような仕組みにする為にリバースプロキシを導入することにした。リバースプロキシ自体もdockerコンテナとして動作している。
dockerfile
# https://registry.hub.docker.com/_/nginx/
FROM nginx:1.9
# SSL証明書をコピー
COPY ssl/server.crt /usr/local/nginx/conf/server.crt
COPY ssl/server.key /usr/local/nginx/conf/server.key
# 設定ファイルをコピー
COPY conf/nginx.conf /etc/nginx/nginx.conf
# HTMLファイルをコピー
COPY html /usr/share/nginx/html
設定ファイル
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name www.home.private;
charset koi8-r;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name service.home.private;
charset koi8-r;
ssl on;
ssl_certificate /usr/local/nginx/conf/server.crt;
ssl_certificate_key /usr/local/nginx/conf/server.key;
client_max_body_size 1024M;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
# static-html
location / {
index index.html;
root /usr/share/nginx/html;
}
# manet
location /manet {
rewrite ^/manet/?(.*) /$1 break;
proxy_pass http://manet:8891;
proxy_redirect off;
}
# gitbucket
location /gitbucket {
proxy_pass http://gitbucket:8080/gitbucket;
proxy_redirect http:// https://;
}
# redmine
location /redmine {
proxy_pass http://redmine/redmine;
proxy_redirect http:// https://;
}
# lychee
location /lychee {
proxy_pass http://lychee;
proxy_redirect http:// https://;
rewrite ^/lychee/(.*) /$1 break;
}
# resourcespace
location /resourcespace {
proxy_pass http://resourcespace/resourcespace;
proxy_redirect http:// https://;
}
# ethercalc
location /ethercalc {
rewrite ^/ethercalc/?(.*) /$1 break;
proxy_pass http://ethercalc:8000;
proxy_redirect default;
}
# libreboard
location /libreboard {
rewrite ^/libreboard/?(.*) http://$host:8080/$1 break;
}
# etherpad settings
location ~ ^/(locales/|locales.json|admin/|static/|pluginfw/|javascripts/|socket.io/|ep/|minified/|api/|ro/|error/|jserror/|favicon.ico|robots.txt) {
proxy_buffering off;
proxy_pass http://etherpad:9001;
}
location /p {
rewrite ^/p/(.*) /etherpad/p/$1 redirect;
}
location /etherpad {
proxy_pass http://etherpad:9001/;
rewrite ^/etherpad/?(.*) /$1 break;
rewrite ^/etherpad$ /etherpad/ permanent;
proxy_pass_header Server;
proxy_buffering off;
proxy_redirect / /etherpad/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /static {
rewrite /static/(.*) /static/$1 break;
proxy_pass http://etherpad:9001/;
}
}
}
-
proxy_pass http://(サービス名)/ の意味
dockerでコンテナ間のlinkを設定すると、コンテナの中からリンク先のコンテナ名でIPアドレスの名前解決ができる。最初は意味が分からなかった… -
SSLの導入
特に深い意味はないが、せっかくリバースプロキシを導入したのでSSLも使ってみることにした。80番ポートでのアクセスは全てhttpsにリダイレクトされる -
Etherpadはちょっと特殊
https://github.com/ether/etherpad-lite/wiki/How-to-put-Etherpad-Lite-behind-a-reverse-Proxy -
静的HTMLの追加
Webアプリケーションをサブディレクトリにマップしたので、ルートでアクセスした時に表示するものが何もなくなってしまった。ちょっと寂しいので、各アプリケーションへアクセスするためのホームページをnginxのコンテナに追加した。デザインはこんな感じ: