さくらVPSで1つのサーバで2つのrailsサービスを動かしたい。(そのうちのひとつはマストドン)
この場合、ドメインを2つ使う必要があると思い、ドメインを2つ取得したのだが、 今サブドメインというしくみを知った。これをつかえばやりたいことが実現できそうだ。 railsプロジェクトはdocker-composeで管理している。 railsアプリケーションをhttps化するために、let’s encryptのdockerもつかうと便利なことがわかった。
まとめると、次のようなことをやりたい。
- Dockerがインストールされているサーバに複数のdocker-composeで管理されたWebアプリケーションを動かす。
- Webアプリケーションには、それぞれのドメインを設定して、一意にアクセスできるようにする。
- 各ドメインには、Let’s Encryptで取得したSSL証明書が適用される。
結末
調べて実施した結果、やりたいことはできた。
しかし、致命的な問題 が発生して、解決方法が分からず、結局挫折した。
その問題点とは、railsアプリケーション間でのコンテナ間通信ができない、というもの。 たとえば、pingは届くのだけれども、wgetやcurlが届かない。 これが解決できなくて、挫折してしまった。
解決方法が分かる方、教えてください!
手順
挫折はしたものの、rails間で通信しない場合の運用並ば問題ないため、手順をわすれないように残しておく。
前提となる環境
- さくらVPS(Ubuntu)
- Dockerとdocker-composeがインストールされている
コンテナ間通信をするための経路を作成
Dockerのコンテナどうしが通信するための経路を作成する。
# ネットワークを作成する
$ docker network create --driver bridge front
$ docker network create --driver bridge back-mstdn
$ docker network create --driver bridge back-wtdn
リバースプロキシサーバ & Let’s Encryptサーバ
リバースプロキシサーバとして、nginxを利用する。
こいつの役割がいまいちわかっていないのだが、複数ドメインを共存させることができる。 さらには、ドメインについてSSL証明書を発行してくれる。
nginxとletsencryptサーバのdockerイメージを利用する。
~/nginx-proxy
ディレクトリを作成して、その中に docker-compose.yml
を作成する。
certディレクトリに証明書が保存される。
version: '2'
services:
proxy:
image: jwilder/nginx-proxy:alpine
container_name: proxy-nginx
ports:
- 80:80
- 443:443
restart: always
tty: false
privileged: true
volumes:
- ./certs:/etc/nginx/certs:ro
- /var/run/docker.sock:/tmp/docker.sock:ro
- /etc/nginx/vhost.d
- /usr/share/nginx/html
networks:
- front
letsencrypt:
image: jrcs/letsencrypt-nginx-proxy-companion
container_name: proxy-letsencrypt
restart: always
tty: false
privileged: true
volumes:
- ./certs:/etc/nginx/certs:rw
- /var/run/docker.sock:/var/run/docker.sock:ro
volumes_from:
- proxy
networks:
- front
networks:
front:
external: true
railsアプリケーション1(Mastodon)の docker-compose.ymlを作成
1つ目のWebアプリケーション、マストドンを立ちあげる。
Mastodonのリポジトリをcloseすると、docker-compose.ymlがあるので、それを編集する。
- nginxコンテナを新規追加
- ポートは9090(かぶらなければなんでもよい)
- 各コンテナを
back-mstdn
ネットワークでつなぐ db
,redis
のvolumesのコメントアウトを外して、データの永続化。
version: '2'
services:
nginx:
image: nginx:1.11.10-alpine
container_name: mstdn-nginx
ports:
- 9090:9090
restart: always
tty: false
env_file: .env.production
links:
- web
- streaming
volumes:
- ./setting/nginx/conf.d:/etc/nginx/conf.d:ro
- ./setting/nginx/conf:/etc/nginx/conf/:ro
volumes_from:
- container:proxy-nginx
networks:
- front
- back-mstdn
db:
restart: always
image: postgres:9.6-alpine
container_name: mstdn-db
volumes:
- ./postgres:/var/lib/postgresql/data
networks:
- back-mstdn
redis:
restart: always
image: redis:4.0-alpine
container_name: mstdn-redis
volumes:
- ./redis:/data
networks:
- back-mstdn
web:
build: .
image: tootsuite/mastodon
restart: always
container_name: mstdn-web
env_file: .env.production
command: bash -c "rm -f /mastodon/tmp/pids/server.pid; bundle exec rails s -p 3000 -b '0.0.0.0'"
networks:
- back-mstdn
ports:
- "127.0.0.1:3000:3000"
depends_on:
- db
- redis
volumes:
- ./public/assets:/mastodon/public/assets
- ./public/packs:/mastodon/public/packs
- ./public/system:/mastodon/public/system
streaming:
build: .
image: tootsuite/mastodon
restart: always
container_name: mstdn-streaming
env_file: .env.production
command: yarn start
networks:
- back-mstdn
ports:
- "127.0.0.1:4000:4000"
depends_on:
- db
- redis
sidekiq:
build: .
image: tootsuite/mastodon
restart: always
container_name: mstdn-sidekick
env_file: .env.production
command: bundle exec sidekiq -q default -q mailers -q pull -q push
depends_on:
- db
- redis
networks:
- back-mstdn
volumes:
- ./public/packs:/mastodon/public/packs
- ./public/system:/mastodon/public/system
networks:
front:
external: true
back-mstdn:
external: true
.env.productionを読み込んでいるが、これはマストドンを動かすための環境変数がいろいろ書いてある。 編集するところだけ抜き出そう。メールサーバには、ここではsparkpostを利用している。
VIRTUAL_HOST=weightodon.site
VIRTUAL_PORT=9090
VIRTUAL_PROTO=https
LETSENCRYPT_HOST=weightodon.site
LETSENCRYPT_EMAIL=xxx@gmail.com
LETSENCRYPT_TEST=false
LOCAL_DOMAIN=weightodon.site
SECRET_KEY_BASE=<rails secretで表示される値>
OTP_SECRET=<rails secretで表示される値>
SMTP_SERVER=smtp.sparkpostmail.com
SMTP_PORT=587
SMTP_LOGIN=SMTP_Injection
SMTP_PASSWORD=<Web APIで表示される値>
SMTP_FROM_ADDRESS=notifications@weightodon.site
最後にnginxの設定。mastodon/setting/nginx/conf.d/default.conf
を作成して、そこに以下を記述。
編集する箇所は次のとおり。
- listen 9090
- server_nameを設定
- ssl_certificate, ssl_sertificate_keyのパスのサイトを自分のドメインにする
- rootのところをコンテナの中からみた、公開ディレクトリに設定
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 9090 ssl;
server_name weightodon.site;
ssl_protocols TLSv1.2;
ssl_ciphers EECDH+AESGCM:EECDH+AES;
ssl_ecdh_curve prime256v1;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_certificate /etc/nginx/certs/weightodon.site/fullchain.pem;
ssl_certificate_key /etc/nginx/certs/weightodon.site/key.pem;
keepalive_timeout 70;
sendfile on;
client_max_body_size 8m;
root /mastodon/public;
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
add_header Strict-Transport-Security "max-age=31536000";
location / {
try_files $uri @proxy;
}
location ~ ^/(emoji|packs|system/accounts/avatars|system/media_attachments/files) {
add_header Cache-Control "public, max-age=31536000, immutable";
try_files $uri @proxy;
}
location /sw.js {
add_header Cache-Control "public, max-age=0";
try_files $uri @proxy;
}
location @proxy {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Proxy "";
proxy_pass_header Server;
proxy_pass https://web:3000;
proxy_buffering off;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
tcp_nodelay on;
}
location /api/v1/streaming {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Proxy "";
proxy_pass https://web:4000;
proxy_buffering off;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
tcp_nodelay on;
}
error_page 500 501 502 503 504 /500.html;
}
これで、すべて完了。docker-compse up -d
で自動で証明書がダウンロードされてhttps化されるはずだ。
2つめのrailsアプリケーションを立ちあげる
2つめは自作railsアプリケーション。基本的には、Mastodonと同じ。ですので、一気に紹介。
- docker-compose.yml
version: '2'
services:
nginx:
image: nginx:1.11.10-alpine
container_name: wtdn-nginx
ports:
- 9091:9091
restart: always
tty: true
environment:
VIRTUAL_HOST: weightodon.club
VIRTUAL_PORT: 9091
VIRTUAL_PROTO: https
LETSENCRYPT_HOST: weightodon.club
LETSENCRYPT_EMAIL: xxx@gmail.com
LETSENCRYPT_TEST: "false"
links:
- web
volumes:
- ./setting/nginx/conf.d:/etc/nginx/conf.d:ro
- ./setting/nginx/conf:/etc/nginx/conf/:ro
volumes_from:
- container:proxy-nginx
networks:
- front
- back-wtdn
web:
restart: always
build: .
command: bundle exec unicorn_rails -p 3001 -c /app/config/unicorn.rb
# command: bash -c "rm -f /app/tmp/pids/server.pid; bundle exec rails s -p 3001 -b '0.0.0.0'"
container_name: wtdn-web
volumes:
- .:/app
- bundle:/bundle
environment:
TZ: "Asia/Tokyo"
RAILS_ENV: production
RAILS_ROOT: /app
SECRET_KEY_BASE: 7066cf88b55e4b76d4bc9196a96acc1ebc2d809dd6f6f3e854ddd6dba75a2616eee5de216a221b2b13da4932f2c6d6025e0d604b83a2c24c88701c2c2641214d
depends_on:
- db
tty: true
stdin_open: true
ports:
- "127.0.0.1:3001:3001"
dns:
- 133.242.0.3
- 133.242.0.4
- 8.8.8.8
networks:
- back-wtdn
db:
restart: always
image: postgres:alpine
container_name: wtdn-db
volumes:
- ./postgres:/var/lib/postgresql/data
networks:
- back-wtdn
volumes:
db-volume:
bundle:
driver: local
networks:
front:
external: true
back-wtdn:
external: true
setting/nginx/conf.d/default.yml
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 9091 ssl;
server_name weightodon.club;
ssl_protocols TLSv1.2;
ssl_ciphers EECDH+AESGCM:EECDH+AES;
ssl_ecdh_curve prime256v1;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_certificate /etc/nginx/certs/weightodon.club/fullchain.pem;
ssl_certificate_key /etc/nginx/certs/weightodon.club/key.pem;
keepalive_timeout 70;
sendfile on;
client_max_body_size 8m;
root /app/public;
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
add_header Strict-Transport-Security "max-age=31536000";
location / {
try_files $uri @proxy;
}
location ~ ^/(emoji|packs|system/accounts/avatars|system/media_attachments/files) {
add_header Cache-Control "public, max-age=31536000, immutable";
try_files $uri @proxy;
}
location /sw.js {
add_header Cache-Control "public, max-age=0";
try_files $uri @proxy;
}
location @proxy {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Proxy "";
proxy_pass_header Server;
proxy_pass https://web:3001;
proxy_buffering off;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
tcp_nodelay on;
}
error_page 500 501 502 503 504 /500.html;
}
基本的な考え方は、以下をすれば新しいドメインを追加できるはずだ。
- Dockerのネットワークを追加
- nginxのポートを決める
- docker-compose.ymlを作成
- setting/nginx/conf.d/default.ymlを作成
では。