Traefikでアプリをサブドメイン・URLで振り分ける

# 目的
Dockerを用いているとポートが被る事がある。サービス別にポートを設定しているといつの間にか開放ポートの量が増えてしまって管理が大変となってしまう。

## サブドメインを用いる方法
### traefik.yml
```traefik.yml
# https://docs.traefik.io/

# Docker configuration backend
providers:
  docker:
    exposedByDefault: false
    defaultRule: "Host(`{{ index .Labels \"traefik.host\" }}.172.24.20.16.nip.io`)"

entryPoints:
  http:
    address: ":80"

  # smtp:
  #   address: ":25"
  # pop3:
  #   address: ":110"
  # imap:
  #   address: ":143"
  # mysql:
  #   address: ":3306"
  # psql:
  #   address: ":5432"
  # mongo:
  #   address: ":27017"

# API and dashboard configuration
api:
  insecure: true
```

### docker-compose.yml
``` docker-compose.yml
root@ubuntu-16:/home/tmcit/docker-reveal.js# cat docker-compose.yml
version: '3'

services:
  traefik:
    image: "traefik:v2.10"
    container_name: "traefik"
    command:
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
    ports:
      - "80:80"
      - "8080:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./traefik.yml:/etc/traefik/traefik.yml"



  reveal-docker:
    build: .
    container_name: "reveal-docker"
    volumes:
      - ./md:/etc/reveal/md/
    tty: true
    labels:
      - "traefik.enable=true"
      - "traefik.host=reveal-docker"
      - "traefik.http.routers.reveal-docker.entrypoints=http"
      - "traefik.http.services.reveal-docker.loadbalancer.server.port=8000"
```

### アクセス
```
http://reveal-docker.172.24.20.16.nip.io
```

### 解説
#### traefik.yml
- この設定を行う事によって、traefikの設定を行っていないコンテナについては無視するようになる。
```
exposedByDefault: false
```

- nip.ioを用いる事で、サブドメインを用いる事が出来るようになる。
```
defaultRule: "Host(`{{ index .Labels \"traefik.host\" }}.172.24.20.16.nip.io`)"
```

#### docker-compose.yml
- traefikの公開対象にする設定
```
- "traefik.enable=true"
```

- ホスト名の設定
```
- "traefik.host=reveal-docker"
```

- routerの作成。httpは上記のtraefik.ymlで別に設定する必要がある
```
- "traefik.http.routers.reveal-docker.entrypoints=http"
```

- 公開ポートを指定する
```
- "traefik.http.services.reveal-docker.loadbalancer.server.port=8000"
```


### サブドメイン使用時の問題
ここでとある問題にぶち当たってしまった。この構成の場合、ngrok等で公開してもngrokのURL自体はサブドメインを用いる事が出来ない。そこで、URLPathを用いる。


## URLPathを用いる方法
```traefik.yml
## traefik.yml

# https://docs.traefik.io/

# Docker configuration backend
providers:
  docker:
    exposedByDefault: false
#    defaultRule: "Host(`{{ index .Labels \"traefik.host\" }}.172.24.20.16.nip.io`)"

entryPoints:
  http:
    address: ":80"
  https:
    address: ":443"

  # smtp:
  #   address: ":25"
  # pop3:
  #   address: ":110"
  # imap:
  #   address: ":143"
  # mysql:
  #   address: ":3306"
  # psql:
  #   address: ":5432"
  # mongo:
  #   address: ":27017"

# API and dashboard configuration
api:
  insecure: true
```

```docker-compose.yml
version: '3'

services:
  traefik:
    image: "traefik:v2.10"
    container_name: "traefik"
    command:
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
    ports:
      - "80:80"
      - "8080:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./traefik.yml:/etc/traefik/traefik.yml"



  reveal-docker:
    build: .
    container_name: "reveal-docker"
    volumes:
      - ./md:/etc/reveal/md/
    tty: true
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.reveal-docker.entrypoints=http"
      - "traefik.http.routers.reveal-docker.rule=PathPrefix(`/reveal-docker{regex:$$|/.*}`)"

      - "traefik.http.routers.reveal-docker.middlewares=reveal-docker-middlewares"
      - "traefik.http.middlewares.reveal-docker-middlewares.stripprefix.prefixes=/reveal-docker"

      - "traefik.http.routers.reveal-docker.service=reveal-docker-service"
      - "traefik.http.services.reveal-docker-service.loadbalancer.server.port=8000"
```

### アクセス
```
http://172.24.20.16/reveal-docker/
```

この設定を行う事で、ngrok等で公開した場合にも対応する事が出来る。
```
https://dXXXXXXXXXX.ngrok-free.app/reveal-docker/
```


### 解説

正規表現を用いて、/reveal-docker/にマッチするものをルーティングする
```
- "traefik.http.routers.reveal-docker.rule=PathPrefix(`/reveal-docker{regex:$$|/.*}`)"
```

- ミドルウェアの作成
```
- "traefik.http.routers.reveal-docker.middlewares=reveal-docker-middlewares"
```

- ミドルウェアとURLPathの紐づけ
```
- "traefik.http.middlewares.reveal-docker-middlewares.stripprefix.prefixes=/reveal-docker"
```
- サービスの作成
```
- "traefik.http.routers.reveal-docker.service=reveal-docker-service"
```

- 公開ポートの指定
```
- "traefik.http.services.reveal-docker-service.loadbalancer.server.port=8000"
```