LoginSignup
0
0

More than 3 years have passed since last update.

Docker Swarm + Traefik(1.7) で構築したクラスタで、REMOTE_ADDRが取得できない問題に対処した話

Last updated at Posted at 2020-09-06

Docker Swarmクラスタ上で、リバースプロキシとしてTraefikコンテナを立て、nodeコンテナでコンテンツを配信する構成で運用しようとしたところ、どうにもREMOTE_ADDRが取得できなくて困りました。

そのときの対処方法をメモしておきます。

Dockerのバージョン:19.03.12

当初のdocker-compose.ymlファイルは以下のとおりです。

version: '3.4'

services:

  socket-proxy:
    image: tecnativa/docker-socket-proxy
    networks:
      - internal
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - SERVICES=1
      - TASKS=1
      - NETWORKS=1
      - LOGSPOUT=ignore
    deploy:
      placement:
        constraints:
          - node.hostname == manager

  traefik:
    image: traefik:1.7-alpine
    command:
      - "--logLevel=error"
      - "--entryPoints=Name:http Address::80 Redirect.EntryPoint:https"
      - "--entryPoints=Name:https Address::443 TLS"
      - "--defaultentrypoints=http,https"
      - "--web"
      - "--web.address=:8080"
      - "--acme"
      - "--acme.storage=certs.json"
      - "--acme.entrypoint=https"
      - "--acme.httpchallenge.entrypoint=http"
      - "--acme.onHostRule=true"
      - "--acme.email=hashimoto@bagooon.com"
      - "--docker"
      - "--docker.endpoint=tcp://socket-proxy:2375"
      - "--docker.swarmMode"
      - "--docker.watch"
    ports:
      - 80:80
      - 443:443
    networks:
      - internal
      - overlay
    volumes:
      - ./certs/certs.json:/certs.json
    deploy:
      placement:
        constraints:
          - node.hostname == web
      restart_policy:
        condition: on-failure

  web:
    image: hoge/fuga:dev
    networks:
      - overlay
    deploy:
      replicas: 1
      placement:
        constraints:
          - node.hostname == web
      labels:
        - "traefik.enable=true"
        - "traefik.backend=web"
        - "traefik.frontend.rule=Host:sample.com"
        - "traefik.frontend.entryPoints=https"
        - "traefik.frontend.passHostHeader=true"
        - "traefik.docker.network=overlay"
        - "traefik.protocol=http"
        - "traefik.port=3000"

networks:
  overlay:
    external: true
  internal:
    internal: true

今回の本題ではありませんが、上記の設定では「docker-socket-proxy」を使って、Traefikのendpointを別のコンテナに割り振っています。一般的にTraefikはマネージャノードで実行し、endpointにdocker.sockを指定して使用するのですが、もしTraefikにセキュリティホールが見つかったりすると、クラスタ全体を乗っ取られてしまう危険性が指摘されています。docker-socket-proxyを使用することで、ワーカーノード上でTraefikを実行でき、さらにdocker-socket-proxyで権限を絞ることでセキュリティを高めた運用が可能になります。

以前あるサイトを運用していて、悪質なアクセスに悩まされた経験がありますので、是非ともREMOTE_ADDRはログとして残しておきたいのですが、どうにも取得できません。

Traefikは、各コンテナで「traefik.frontend.passHostHeader=true」を指定すれば、バックエンドにヘッダー情報等をそのまま送り届けてくれるはずです。User-Agent等は正しく取得できますので、どうやらこの設定は生きているようです。

原因

いろいろ調べていたところ、海外の掲示板で、Docker SwarmのオーバーレイネットワークがREMOTE_ADDRを運ばないらしいという情報を見つけました。そして、Nginxの事例ではありましたが、ポートをhostモードでマウントするといいよ、という解決策も示されていました。

解決策

そこで、Traefikのポートの設定を以下のように書き換えてみました。

    ports:
      - mode: host
        protocol: tcp
        published: 80
        target: 80
      - mode: host
        protocol: tcp
        published: 443
        target: 443

テストしたところ、無事にREMOTE_HOSTを取得できるようになりました。

Nginx等でも同じ対応で解決できるものと思います。
同じ問題でお困りの方がいらっしゃいましたら、是非お試しください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0