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

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

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

趣味レベルのサービスにいちいちAWSとか使うと破産するので, 僕のようなおさいふが軽い層は**毎夜枕を濡らしながら月々1000円とか2000円のVPSでDBなりWebサーバを動かしています**. :cry:

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

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

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

1. DNSへサブドメインの登録
2. docker-composeファイルの作成, 起動

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

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

```
hoge.com/minecraft/
hoge.com/blog
```

とするのはかっこ悪いです. 
<font color=lightgray>パソコンに疎い人はそう思わないかもしれませんが, 僕らのようなぱそこんのおたくから見ると**非常にダサい**のです.</font>

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

```
minecraft.hoge.com
blog.hoge.com
```

**かっこいい！！**

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

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

![5e66c11f0a94347aaee54fe1f5fd314f.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250257/dbfc56de-de4f-437a-8da2-9c4b9517e200.png)

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

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

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

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

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

![a06992fb8e92e3268be6c6382eeb3cdd.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250257/78a590fa-c8be-0355-11c6-6982d6973b2a.png)

わかりやすく書くとこんな感じです. 
難しいこというと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の内容

:::note warn
記事執筆当初の設定です. 最新バージョン等は気合で確認・修正してください. 
:::

#### nginx-proxy, letsencrypt (必須)
```yaml:docker-compose.yml
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 (必須)
```yaml:docker-compose.yml
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 (任意)
```yaml:docker-compose.yml
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
```

### コンテナの実行
ファイルが設置出来たら各ディレクトリで

```shell
$ docker-compose up -d
```

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

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

詳しい使い方についてはこの記事で解説されています.
[Nedia BLOG - DockerにおけるGUI管理(Portainer 導入編)](https://www.nedia.ne.jp/blog/2019/07/02/14868)

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

設定のキモとしては, 

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

networks:
  default:
    external:
      name: shared
```

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

# 注意点
Dockerを使う関係上, **ディスク容量を結構食います**.
また, 直にインストールするよりは**若干パフォーマンスが落ちる**ので, 格安サーバだと多少気になることもあるかもしれません. :thinking:

また, これはあくまで簡単な設定方法なので, ファイアウォールなりなんなりのセキュリティ対策を他に講じる必要があります.

外部にサービスを公開する関係上攻撃を受けることは避けられないので, 上記のdocker-compose.ymlで外部に公開するポートをデフォルトの値から変えるだけでも**総当りしてくるバカ**から身を守れる確率が少し高くなります.

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

# 参考

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/

https://qiita.com/fukuyama012/items/5d4390ae4a34ba477cef

https://www.nedia.ne.jp/blog/2019/07/02/14868