Docker サーバ管理 なるべく楽に サブドメインありhttpsあり


Overview

タイトルで検索したような人がたどり着くことを祈ります.

Description

サーバ管理って楽しめんどくさいですよね.
なるべくならここに労力をかけずにサービス運用したいものです.

上級国民は趣味レベルのサービス立ち上げるときにもAWS使ったりするのかもしれませんが, 僕のような低所得者層は毎夜枕を濡らしながら月々1000円とか2000円のVPSを使ってDBなりWebサーバを動かしています.

この記事ではnginx-proxy, letsencrypt-nginx-proxy-companion, portainer, dockerを用いた比較的簡単なサーバ管理を書いていきます.

ぶっちゃけ何ができるかというと, 最初にドメインの設定とdocker-compose.ymlを書いておけばサービスの追加も削除も再起動もシェル操作もWebブラウザからできるようになります.

Settings

大きく分けて次の2つの工程があります.

  • DNSへサブドメインの登録
  • docker-composeファイルの作成, 起動
  • portainerへのアクセス

Register SubDomains

まずはサブドメインの登録からです.

例えば, hoge.comというドメインを自分が持っているとして, minecraftサーバとブログの2つのサービスを運用したい!というときに

hoge.com/minecraft/
hoge.com/blog

とするのはかっこ悪いです.
パソコンに疎い人はそう思わないかもしれませんが, 僕らのようなPASOKON OTAKUから見ると非常にダサいのです.

そこで, 次のようなドメイン名をつけていい感じに運用しよう!というのがサブドメインのざっくりした説明です.

minecraft.hoge.com
blog.hoge.com

かっこいい!!
それにドメインというのは本来後ろから読んでいくものなので,
comドメイン内のhogeサーバのminecraftサービス のように直感的に読めるようになります.

この設定は契約している会社さんによるので, 会社名 DNS 設定とかでググると詳しく説明してくれると思います.
ここではさくらインターネットのVPSの場合を書きます.


ゾーン編集画面はこのようになっています.
伏せ文字だらけでわかりづらいかもですが, 気合で頑張りましょう.

画面右側にあるテーブルがドメインのルーティングを示しています.

どのDNSでもCNAMEタイプにAレコードと同じIPアドレスを指定することで行き先が全部同じになるのでそのように設定します.
さくらインターネットの場合は@を使ってAレコードの値を参照しているのでIPアドレス直書きしなくてもいい感じです.

普通はここでminecraft.hoge.comはサーバAに!blog.hoge.comはサーバBに!とか分けたりするんですが.
各サブドメインが全部hoge.comに来るようにしています.

なぜなら, nginx-proxyというサービスがDNSの代わりにちゃんと振り分けてくれるので正しいサービスにたどり着けるというわけです.

わかりやすく書くとこんな感じです.
難しいこというとnginx-proxyがリバースプロキシの役割をしています.

Docker

前提として, dockerとdocker-composeがインストールされていることを確認してください.
Ubuntuだったらsnap install dockerとかでいけた気がします. (sudoでdocker実行するか, 権限の設定が必要かも)

次のようなディレクトリ構成にします.
例に挙げた以上書いとかないと怒られるかもなのでminecraftのdocker-compose.ymlも書いてみました.

必要に応じて各ディレクトリ配下にコンテナ内のファイルがホストにマウントされるような感じなので管理しやすい気がします.

.
├── nginx-proxy
│   └── docker-compose.yml
├── portainer
│   └── docker-compose.yml
└── minecraft
    └── docker-compose.yml

docker-compose.ymlの内容(適宜修正すること!)

nginx-proxy, letsencrypt (必須)

version: "2"
services:
  nginx-proxy:
    image: jwilder/nginx-proxy
    container_name: nginx-proxy
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/tmp/docker.sock:ro
      - ./certs:/etc/nginx/certs:ro
      - /etc/nginx/vhost.d
      - /usr/share/nginx/html
    restart: always
    networks:
      - shared

  letsencrypt:
    image: jrcs/letsencrypt-nginx-proxy-companion
    container_name: letsencrypt
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./certs:/etc/nginx/certs:rw
    volumes_from:
      - nginx-proxy
    restart: always
    networks:
      - shared

networks:
  shared:
    external: true

portainer (必須)

version: '3.3'
services:
  portainer:
    image: portainer/portainer
    command: -H unix:///var/run/docker.sock
    ports:
      - 8000:8000
      - 9000:9000
    restart: always
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - portainer_data:/data
    environment:
      VIRTUAL_PORT: 9000
      VIRTUAL_HOST: <portainerに割り当てたいサブドメイン>
      LETSENCRYPT_HOST: <portainerに割り当てたいサブドメイン>
      LETSENCRYPT_EMAIL: <メールアドレス(ドメインのhttps化に必要です)>

networks:
  default:
    external:
      name: shared

volumes:
  portainer_data:

minecraft (任意)

version: '3.3'
services:
  mc:
    image: itzg/minecraft-server
    ports:
      - 25565:25565
    restart: always
    volumes:
      - "./mc-data:/data"
    environment:
      EULA: "true"
      VERSION: 1.14.4
      VIRTUAL_PORT: 25565
      VIRTUAL_HOST: <minecraftに割り当てたいサブドメイン>
      LETSENCRYPT_HOST: <minecraftに割り当てたいサブドメイン>
      LETSENCRYPT_EMAIL: <メールアドレス(ドメインのhttps化に必要です)>

networks:
  default:
    external:
      name: shared

実行

ファイルが設置出来たら各ディレクトリで

$ docker-compose up -d

することで各コンテナが立ち上がり, ついでに証明書も作成してくれます.
この記事からコピーして貼り付けて立ち上げるだけなので楽ですね!

指定したサブドメイン(https)にアクセスするとPortainerが立ち上がっていると思います.
GUIでDockerコンテナを管理できて非常にいい感じです.

詳しい使い方についてはこの記事で解説されています.
Nedia BLOG - DockerにおけるGUI管理(Portainer 導入編)

説明

新規サービスを立ち上げたいときには, 基本的にはminecraftのdocker-compose.ymlをコピってちょちょっと変えればOKです.

設定のキモとしては,

      VIRTUAL_PORT: <ポート番号>
      VIRTUAL_HOST: <割り当てたいサブドメイン>
      LETSENCRYPT_HOST: <割り当てたいサブドメイン>
      LETSENCRYPT_EMAIL: <メールアドレス>

networks:
  default:
    external:
      name: shared

このへんですね.
nginx-proxy, letsencryptと同じネットワークに所属させ, 証明書取得に必要な情報を環境変数として与えています.

Issues

Dockerを使う関係上, ディスク容量を食うのと直にインストールするよりは若干パフォーマンスが落ちることが問題でしょうか.
ぼくはそのデメリットよりも管理工数削減のメリットが高いと思ったためこの手法で個人のサーバを管理しています.

あ, もちろんこれはあくまで簡単な設定方法ですので, ファイアウォールなりなんなりのセキュリティ対策は他に講じる必要があります.
簡単な例ですと, 上記のdocker-compose.ymlで外部に公開するポートをアプリケーションデフォルトの値から変えるだけでも総当りしてくるバカから身を守れる確率が少し高くなります.

それでは, よいサーバ管理ライフを!

References

https://github.com/jwilder/nginx-proxy
https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion
https://github.com/portainer/portainer
https://hub.docker.com/r/itzg/minecraft-server/

letsencrypt-nginx-proxy-companionを使って複数ドメイン名に無料SSL証明書を適用する
Nedia BLOG - DockerにおけるGUI管理(Portainer 導入編)