vfarcic / docker-flow-proxy

Docker Flow Proxy
http://proxy.dockerflow.com/
599 stars 17 forks source link

One Domain multiple services #409

Closed Vad1mo closed 6 years ago

Vad1mo commented 6 years ago

I have two services on the domain app.company.com, "Website" and "API".

The API Service should receiver traffic for this path only

app.company.com/v2/*

The Website should receive traffic on this paths:

app.company.com/*
app.company.com/v2/token
app.company.com/v2/webhook

I tried to create a setup with traefik some time ago but failed, as traefik can't support such use cases. However it was fairly easy to create a setup for nginx, but its all manual and not automated in any way. So I was wondering if such an setup would be possible with DFP.

I created a small compose file, that will print out if the right service was called.


  version: '3.5'
  services:

#---#
  proxy:
    image: vfarcic/docker-flow-proxy
    ports:
      - 80:80
      - 443:443
    environment:
      - LISTENER_ADDRESS=swarm-listener
      - MODE=swarm
      - SERVICE_NAME=proxy_proxy      
    deploy:
      mode: global
      # replicas: 1
      placement:
        constraints: [node.role == worker]

  swarm-listener:
    image: vfarcic/docker-flow-swarm-listener
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - DF_NOTIFY_CREATE_SERVICE_URL=http://proxy_proxy:8080/v1/docker-flow-proxy/reconfigure
      - DF_NOTIFY_REMOVE_SERVICE_URL=http://proxy_proxy:8080/v1/docker-flow-proxy/remove
    deploy:
      placement:
        constraints: [node.role == manager]
#---#
    service_web:
      image: vad1mo/hello-world-service
      hostname: web
      deploy:      
        labels:
          - com.df.servicePath=/,/v2/token,/v2/webhooks/events
          - com.df.notify=true
          - com.df.distribute=true
          - com.df.port=5050
          - com.df.serviceDomain=docker.for.mac.localhost          
#---#
    service_api:
      image: vad1mo/hello-world-service
      hostname: api
      deploy:      
        labels:
          - com.df.servicePath=/2/
          - com.df.notify=true
          - com.df.distribute=true
          - com.df.port=5050
          - com.df.serviceDomain=docker.for.mac.localhost   

  networks:
    default:
      name: proxy    
vfarcic commented 6 years ago

Judging from your stack, it should work, assuming that both services respond on those paths. Can you confirm that vad1mo/hello-world-service responds to both / and /2/ without DFP? If that's not the case, you might need to add reqPathSearchReplace as well.

I'm at an airport and won't be able to try it out myself for a while. If you can provide more info (which service fails, DFP logs, DFP config located in /cfg/haproxy.cfg), I might be able to respond earlier. I'll be online every once in a while. WiFi in intercontinental flights allow me to check emails (and GitHub comments), but not much more.

Vad1mo commented 6 years ago

I'll try it in the next 2 days and post results here, as maybe others are also interested in such a setup as its not that uncommon.

Vad1mo commented 6 years ago

so, after 2(19) days, I was able to setup the service:

So this is my config:

Frontend app.domain.com

Backend app.domain.com

Everything in /*, /v2/token /v2/webhooks should go to the frontend. Everything to /v2/* should go to the backend except /v2/token /v2/webhooks

However with the current setup everything /v2/ related goes to backend and /v2/token /v2/webhooks are ignored

vfarcic commented 6 years ago

You're right. HAProxy evaluates ACLs from top to bottom. They are alphabetically ordered in the config using aclName or, if empty, serviceName. The exception are services that have / in the path. Since it's catch-all path, it's placed at the bottom. As a result, the backend is evaluated before the frontend and all requests with a path that starts with /v2/ are forwarded to it.

The problem is that all the ACL in a single servicePath are together. The config for the frontend looks something like:

    acl url_my-service1234_0 path_beg / path_beg /v2/token path_beg /v2/webhooks
    use_backend acl-1-be1234_0 if url_my-service1234_0

Splitting it into a separate entry will be a risky change and it'll take time to do it and it would cover a use-case that is rarely used.

Can you confirm that you:

Vad1mo commented 6 years ago

I got it now, I didn't want to change the application. However I was able to create better rules thanks to servicePathExclude.

UI:
         - com.df.servicePath=/ (default)
API:
        - com.df.servicePath=/v2/
        - com.df.servicePathExclude=/v2/token,/v2/webhooks/events

It took me days to finally find out that something simple as this won't work with traefik. thx @vfarcic for this HAP extension.

albertorm95 commented 6 years ago

@Vad1mo Did you had to modify your backend to work on /v2/? I mean it is working with /v2/ endpoint or the proxy is doing that job and your backend is only /