Search code examples
nginxdocker-composereverse-proxy

Is it possible to add locations dinamically on ngninx reverse proxy docker?


Infrastructure

I want to create a docker with the following structure: Structure I intend to have a docker-compose that inside has 3 main images (a database, an api on port 8080 and a frontend on port 443). Besides that I have a couple of extra docker-compose that represent other services.

Functionality

The feature i'm looking for is being able to create container instances of the secundary docker-compose files from inside the nginx reverse proxy(main docker-compose) and map that port to an unique subdirectory (it's important to be able of creating multiple instances of the same docker-compose).

What I found

To acomplish the rest of the features already found some resources:


Solution

  • Solved the problem using traefik, it allows me to add routes by the subdirectory to containers without modifying the build configuration.

    The docker-compose.yml would be something like this:

    version: '3.7'
    services:
      traefik:
        image: traefik:v2.2.0
        ports:
          - "${FRONT_HTTP_PORT:-80}:80"
          - "${TRAEFIK_PORT:-8080}:8080"
        environment: 
          - TRAEFIK_LOG_LEVEL=DEBUG
          - TRAEFIK_PROVIDERS_DOCKER_EXPOSEDBYDEFAULT=false
          - TRAEFIK_PROVIDERS_DOCKER=true
          - TRAEFIK_PROVIDERS_DOCKER_NETWORK=traefik01
          - TRAEFIK_API_INSECURE=true
          - TRAEFIK_ENTRYPOINTS_FRONT=true
          - TRAEFIK_ENTRYPOINTS_FRONT_ADDRESS=:${FRONT_HTTP_PORT:-80}
        volumes:
          - /var/run/docker.sock:/var/run/docker.sock:ro
        security_opt:
          - label:type:docker_t
    
      frontend:
        build: ./frontend
        expose:
          - 80
        labels:
          - "traefik.enable=true"
          - "traefik.http.routers.frontend.entrypoints=front"
          - "traefik.http.routers.frontend.rule=PathPrefix(`/frontend{regex:$$|/.*}`)"
          - "traefik.http.routers.frontend.middlewares=frontend-stripprefix"
          - "traefik.http.middlewares.frontend-stripprefix.stripprefix.prefixes=/frontend"
          - "traefik.http.routers.frontend.priority=2"
          # - "traefik.http.routers.frontend.priority=1"
          # - "traefik.frontend.rule=Host:ctf.itasahobby.com"
        stdin_open: true
    
      api:
        build: ./api
        expose: 
          - 80
        links:
          - database
        labels:
          - "traefik.enable=true"
          - "traefik.http.routers.api.entrypoints=front"
          - "traefik.http.routers.api.rule=PathPrefix(`/api{regex:$$|/.*}`)"
          - "traefik.http.routers.api.middlewares=api-stripprefix"
          - "traefik.http.middlewares.api-stripprefix.stripprefix.prefixes=/api"
          - "traefik.http.routers.api.priority=2"
    
      database:
        build: ./database
        restart: always
    networks:
      default:
        external:
          name: testnetwork
    

    Then to add a new container it has to contain the same network interface and the labels in order to set the routes, for instance:

    version: '3.7'
    services:
      app2:
        image: httpd:2.4.41-alpine
        expose:
          - 80
        labels:
          - "traefik.enable=true"
          - "traefik.http.routers.app2.entrypoints=front"
          - "traefik.http.routers.app2.rule=PathPrefix(`/app2{regex:$$|/.*}`)"
          - "traefik.http.routers.app2.middlewares=app2-stripprefix"
          - "traefik.http.middlewares.app2-stripprefix.stripprefix.prefixes=/app2"
    networks:
      default:
        external:
          name: testnetwork