A story that addresses the problem that REMOTE_ADDR cannot be acquired in a cluster built with Docker Swarm + Traefik (1.7).

On the Docker Swarm cluster, I set up a Traefik container as a reverse proxy and tried to operate it with a configuration that distributes content with a node container, but I was in trouble because I could not get REMOTE_ADDR.

Make a note of what to do in that case.

Docker version: 19.03.12

The original docker-compose.yml file is:

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"
      - "[email protected]"
      - "--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

Although it is not the main subject of this time, in the above setting, "docker-socket-proxy" is used to allocate the endpoint of Traefik to another container. Generally, Traefik is executed on the manager node and docker.sock is specified as the endpoint, but if a security hole is found in Traefik, there is a risk that the entire cluster will be hijacked. .. By using docker-socket-proxy, you can execute Traefik on the worker node, and by narrowing down the authority with docker-socket-proxy, you can operate with enhanced security.

I have been operating a certain site before and have suffered from malicious access, so I definitely want to keep REMOTE_ADDR as a log, but I can not get it anyway.

Traefik should send the header information etc. to the backend as it is if you specify "traefik.frontend.passHostHeader = true" in each container. User-Agent etc. can be acquired correctly, so it seems that this setting is alive.

Cause

After a lot of research, I found information on overseas bulletin boards that the Docker Swarm overlay network does not seem to carry REMOTE_ADDR. And, in the case of Nginx, there was also a solution to mount the port in host mode.

solution

So, I rewrote the port setting of Traefik as follows.

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

After testing, I was able to get REMOTE_HOST safely.

I think that Nginx etc. can solve it with the same correspondence. If you have any problems with the same problem, please try it.

Recommended Posts

A story that addresses the problem that REMOTE_ADDR cannot be acquired in a cluster built with Docker Swarm + Traefik (1.7).
The problem that the localhost page launched by Docker cannot be confirmed in the browser when the ESET firewall is operating
The story that docker had a hard time
A story that got stuck with an error during migration in docker PHP laravel
The story that .java is also built in Unity 2018
I made a program in Java that solves the traveling salesman problem with a genetic algorithm
[Spring Dtata JPA] How to deal with the problem that DB change cannot be detected when you want to process API synchronously with a single thread in Spring Boot.
[Docker] The story that an error occurred in docker-compose up
[rails] Problems that cannot be registered / logged in with devise
Avoid the problem that session cannot be acquired when canary release when upgrading from Rails 4.2.x to 5.0.x
A story that struggled with the introduction of Web Apple Pay
The story that Tomcat suffered from a timeout error in Eclipse
A story stuck with log output in Docker + Play framework environment
The story of making it possible to build a project that was built by Maven with Ant
About the problem that the server can not be started with rails s
How to solve the problem that notification cannot be requested on iOS14
The story that the Servlet could not be loaded in the Java Web application
767 JSON :: ParserError occurs and the problem that the local server cannot be started
After verifying the Monty Hall problem with Ruby, a story that I could understand well and did not understand well