個人開発でConoHaのVPSを使用して複数サイトを管理しているのですが、ConoHaのサービスにお金をチャージするのを忘れていて最初からサーバーを構築し直すハメになっちゃって色々忘れてしまってたので備忘録です。
対象
今回の記事は以下のような方を対象として書いています。
- バーチャルホストで複数ドメインを1つのサーバーで管理しているけどもっと楽に管理したい
- dockerを使用したことがある
個人開発していると基本的に1つのサーバーで複数サイトを管理するようになるかと思います。今回はそのやり方をdockerを使用した方法で紹介したいと思います。
また、dockerを使用したことがある方と書いてはいますが、自分もそこまでdockerに詳しくはないので細かい説明は記載してありません。
とはいえ実際に動くものを作ることでイメージが湧いてdockerについてもっと学ぶ良い機会になると思いますので分からない部分があってもまずは作ってみるというのが私のモットーです。
では早速作っていきましょう!!
開発環境
- ConoHa VPS
- Ubuntu 20.04.2
- Docker version 20.10.7
- docker-compose version 1.27.4
- Nginx
構成
リバースプロキシ用のdocker-composeとsite-a.com用のdocker-composeとsite-b.com用のdocker-composeの3つで構成されています。
ブラウザからsite-a.com or site-b.comに80番ポートでアクセスがあるとリバースプロキシ用のコンテナがアクセスを受け取ります。
次にリバースプロキシは受け取ったホスト名によって任意のコンテナ(site-a.comかsite-b.com)へアクセスするようになってます。
最終的なファイルはこちらで公開してあります。
ネットワークの構築
docker network create --driver bridge shared
コンテナ間で通信が行えるようにネットワークを作ります。今回の場合、sharedというネットワークを作成しこれを使用しているコンテナ間で通信ができるようになります。
各コンテナの説明
リバースプロキシ用コンテナ
./shared/docker-compose.yml
version: '3'
services:
proxy:
image: nginx:latest
container_name: 'proxy'
privileged: true
volumes:
- ./conf.d/:/etc/nginx/conf.d
ports:
- "80:80"
restart: always
networks:
default:
external:
name: shared
volumesの設定でconf.dディレクトリをコンテナ内の/etc/nginx/conf.dにマウントしてリバースプロキシの設定を行っています。
portsは80番ポートを開放して受け付けれるようにしてます。
こちらでsharedネットワークに接続できるようにしています。
networks:
default:
external:
name: shared
.shared/conf.d/default.conf
server {
listen 80;
server_name site-a.com;
location / {
proxy_pass http://site-a.com:80;
root /var/www/htdocs;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /var/www/htdocs;
}
}
server {
listen 80;
server_name site-b.com;
location / {
proxy_pass http://site-b.com:80;
root /var/www/htdocs;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /var/www/htdocs;
}
}
リバースプロキシの設定が記載されてるdefault.confの中身はserverブロックごとに各サイトの設定をしています。
site-a.com
./site-a.com/docker-compose.yml
version: '3'
services:
site-a.com:
image: nginx:latest
container_name: 'site-a.com'
volumes:
- ./server:/var/www
- ./docker/web/default.conf:/etc/nginx/conf.d/default.conf
environment:
VIRTUAL_HOST: 'site-a.com'
networks:
default:
external:
name: shared
environmentのVIRTUAL_HOSTにサイトのホスト名を記載します。
site-b.comに関しても同様の内容になるので割愛します。
コンテナを立ち上げる
docker-compose up -d #./shared
docker-compose up -d #./site-a.com
docker-compose up -d #./site-b.com
コンテナを立ち上げるとdocker network inspect sharedでsharedネットワークに繋がったことが確認できるるようになります。
Containersの中に立ち上げたコンテナが記載されているかと思います。
"Containers": {
"b6c922c22f92fbfab18c608f66f89f5fed224216e82443a99bfc094631ef5e54": {
"Name": "proxy",
"EndpointID": "30c590755489ac252b86b485657df475da642d5f884e7019031f9a793d0814d0",
"MacAddress": "02:42:ac:15:00:02",
"IPv4Address": "172.21.0.2/16",
"IPv6Address": ""
},
"d75bc433abb6508fdb9b7b8fa41e2f966cea25581b58bf3cd500db8180900136": {
"Name": "site-b.com",
"EndpointID": "bf77caf83b0ae0f2c648e3c3188c2a922029e6d093ec309f84264242a3124018",
"MacAddress": "02:42:ac:15:00:04",
"IPv4Address": "172.21.0.4/16",
"IPv6Address": ""
},
"fd7c9f23e3934107854d48d8024a8f37271a9ddac8573663e02caa0450881c78": {
"Name": "site-a.com",
"EndpointID": "64192615ac049cf4923ebae05c981744e10ce50cd08316ef13df01cb5713a4e5",
"MacAddress": "02:42:ac:15:00:03",
"IPv4Address": "172.21.0.3/16",
"IPv6Address": ""
}
},
これで無事「site-a.com」「site-b.com」にアクセスできるようになったかと思います。
もしローカルで立ち上げている場合、hostsファイルを書き換えることで「site-a.com」「site-b.com」でアクセスができるようになっているかと思います。
/etc/hosts
127.0.0.1 site-a.com
127.0.0.1 site-b.com
リバースプロキシ用のイメージ
実は比較的簡単にリバースプロキシの設定を行えるnginx-proxyというdockerイメージがあるんですが勉強の名目も兼ねて今回は使用しませんでした。
今回自分が行った設定ではサイトが増えるごとにdefault.confに設定を追記していかないといけないのですがnginx-proxyであればネットワークが繋がってるコンテナの起動と終了を検知して
自動で設定ファイルを書き換えてくれるので楽になります。またSSL証明書を/etc/nginx/certsに置くことでHTTPSでの通信も簡単に行うことができます。
SSL化
今回、SSL化については触れてないのですが、自分の場合はConoHaのVPS内でSSL証明証を発行して証明書があるディレクトリをリバースプロキシ用のコンテナにマウントすることで解決しています。
./shared/docker-compose.yml
version: '3'
services:
#本番用のコンテナ
proxy_prod:
image: nginx:latest
container_name: 'proxy'
volumes:
- ./conf.d/:/etc/nginx/conf.d
- /etc/letsencrypt:/etc/letsencrypt #SSL証明書をマウント
ports:
- "80:80"
- "443:443"
restart: always
#ローカル用のコンテナ
proxy_dev:
image: nginx:latest
container_name: 'proxy'
volumes:
- ./conf.d/:/etc/nginx/conf.d
ports:
- "80:80"
restart: always
networks:
default:
external:
name: shared
しかしこれだとローカル開発するときに証明書がなくて困るので、本番用とローカル用で立ち上げるコンテナを変えて開発できるようにしてるんですが、
ローカルのSSL化でスマートなやり方がないか考えてる段階でかれこれ数ヶ月が立ちます・・・(笑) そろそろやらないと!!!
nginx-proxyを使用すれば比較的簡単に実装できるんですけどね・・・
課題
今回の実装の仕方だと開発するときに毎回リバースプロキシ用のコンテナを立ち上げるという手間が発生するので結構めんどくさいです。
理想はコマンド1発で開発環境が立ち上がってローカルのPC内も汚さないというのが理想なんですがまだまだ道のりは長そうです。
また今回この記事を書いていてまだまだDockerやLinuxについて理解できていない部分が多くあることを認識できたのでしっかりと1から学び直さないといけないなと感じました。
以上!!また次の機会に!!