3
votes

I have few microservices, let's call it food-ms, receipt-ms, ingredients-ms and frontend with React App consumes those microservices. Each of them exposes API at /api/[methods].

I would like to create environment for production and development using Docker and docker-compose with next properties:

  • Application should be available at single host. In production host should be for example http://food-app.test, for development it should be (ideally) localhost

  • Each microservice and frontend should be at single host, but at different paths. For example, food-ms API should be at localhost/food/api, receipt-ms API should be at localhost/receipt/api etc. Frontend should be at localhost root / path.

  • Ideally, I would like to be able to run some services outside container for easy debugging, but still be reverse proxied and available by localhost/{service}/api.

I found a traefik reverse proxy, and experimented with it a bit, but stuck in issues:

  1. How to make app available at some predictable domain, like localhost. Currently I'm able to proxy requests to specific backend by specifying a strange host in Host header like <container-name>.<network-name>.docker.localhost Seems frontends described in traefik.toml don't have an effect.
  2. How to route requests from one frontend to different backends depending on path?
  3. How to route request to an external IP and port (I would like to use this to run services outside container for debugging)? Should I use host network in docker for this?

Thanks in advance.

Here is my traefik.toml

defaultEntryPoints = ["http"]

[entryPoints]
    [entryPoints.http]
    address = ":80"

[file]

[frontends]
    [frontends.food]
    entrypoints = ["http"]
    backend="food"

    [frontends.receipts]
    entrypoints = ["http"]
    backend="receipts"

Those frontends seems doesn't get applied, because dashboards doesn't get changed if I commend them out.

3
Sorry, I am not aware of traefik, but suggestion, you can use nginx reverse proxy which is widely use as reverse proxy server.Rohan J Mohite

3 Answers

1
votes

After some time spent, I got a bit of success with my problem.

First of all, it is much easier to experiment with traefik running as local application rather than docker container.

So I installed traefik locally (brew install traefik) and run it with next command line:

traefik --web --configfile=./docker/traefik-local.toml --logLevel=INFO

There is a deprecated but working argument --web which meanwhile could be omitted.

Then I created a TOML file with configuration

defaultEntryPoints = ["http"]
[entryPoints]
    [entryPoints.http]
    address = ":80"

[file]

[frontends]
    [frontends.fin]
        entrypoints = ["http"]
        backend="fin"
        [frontends.fin.routes.matchUrl]
            rule="PathPrefixStrip:/api/fin"
        [frontends.fin.routes.rewriteUrl]
            rule = "AddPrefix: /api"

    [frontends.proj]
    entrypoints = ["http"]
    backend="proj"
        [frontends.proj.routes.matchUrl]
            rule="PathPrefixStrip: /api/proj"
        [frontends.proj.routes.rewriteUrl]
            rule = "AddPrefix: /api"


[backends]
    [backends.fin]
        #
        [backends.fin.servers.main]
        url = "http://localhost:81"
    [backends.proj]
        #
        [backends.proj.servers.main]
        url = "http://localhost:82"

Service names are different from initial answer, but idea should be clear.

First of all, there is mandatory [file] directive before describing frontends and backends. It doesn't work without it, arghh :(

Services are running in docker containers and exposes ports 81 for fin and 82 for proj. Since now traefik works outside docker isolated network, it supports either natively running application and application in container.

Then two frontends are described. Initially I also had an issue with rules: PathPrefixStrip is Matcher but it also modifies the path by removing path prefix.

So now it works as I want with local running, and it should be much easier to get it working in the Docker.

0
votes

Well, a bit more info about running all that stuff in Docker.

First of all, the traefik has a concept of configuration provides, where it could get all that info about backends, frontends, rules, mappings etc.

For Docker there are at least two ways: use labels on services in docker-compose.yml or use file configuration provider.

Here I would consider using file configuration provider. To use it you need to add [file] section and configuration below to traefik config or use separated file.

I used separated file, enabled and point it by adding --file --file.filename=/etc/traefik/traefik.file.toml command-line arguments.

Remember if you use Windows and docker-toolbox you need to add shared folder in Virtual Box and add mapping relative to that folder, that's a pain, yes.

After that another things are easy.

To address services in [backends] section of traefik config use service names from docker-compose.yml. To expose proxy use port mappings.

Here is my docker-compose.yaml:

version: "3"
services:     

  financial-service:
    build:
      context: .
      dockerfile: ./docker/financial.Dockerfile

  project-service:
    build:
      context: .
      dockerfile: ./docker/project.Dockerfile

  traefik:
    image: traefik
    command: --web --docker --file --file.filename=/etc/traefik/traefik.file.toml --docker.domain=docker.localhost --logLevel=INFO --configFile=/etc/traefik/traefik.toml
    ports:
      - "80:80"
      - "8088:8080"
      # - "44:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      # On Windows with docker-toolbox:
      #    this should be mounted as a shared folder in VirtualBox.
      # Mount via VB UI, don't forget to restart docker machine.

      # - /rd-erp/docker:/etc/traefik/
      # On normal OS
      - ./docker:/etc/traefik/
    depends_on:
      - project-service
      - financial-service

Here is traefik.file.toml for Docker:

[frontends]
    [frontends.fin]
        entrypoints = ["http"]
        backend="fin"
        [frontends.fin.routes.matchUrl]
            rule="PathPrefixStrip:/api/fin"
        [frontends.fin.routes.rewriteUrl]
            rule = "AddPrefix: /api"

    [frontends.proj]
    entrypoints = ["http"]
    backend="proj"
        [frontends.proj.routes.matchUrl]
            rule="PathPrefixStrip: /api/proj"
        [frontends.proj.routes.rewriteUrl]
            rule = "AddPrefix: /api"


[backends]
    [backends.fin]
        #
        [backends.fin.servers.main]
        url = "http://financial-service"
    [backends.proj]
        #
        [backends.proj.servers.main]
        url = "http://project-service"

Next step would be to run some services outside container and still be able to reverse-proxy it from localhost.

0
votes

And probably the last part: connecting to the services running on the host machine from the Docker, and in our case, from the traefik container.

  1. Run service on the host machine
  2. In Docker 18.3+ use special domain host.docker.internal and don't forget to specify protocol and port.

    In earlier Docker probably would need to use host network mode. This would involve extra configuration of services to don't overlap with busy ports, but probably wouldn't require changing configuration for running services outside container.

  3. Run docker-compose without service you would like to debug:

    docker-compose up --no-deps traefik financial-service

  4. Enjoy

Don't forget to remove [file] section from traefik.toml if you use configuration in separated file provided by --file.filename, seems [file] section takes precedences.