Search code examples
dockerdocker-composeswaggerapi-gateway

Swagger UI accessed through docker does not work


I have two microservices (Transactions and Payments) that are gonna be accessed through an ApiGateway, and each microservice is inside a docker container. Also, I have implemented my own SwaggerResourcesProvider in order to access both Swagger from a single point: the ApiGateway Swagger, as you can see in this question: Single Swagger

In order to enable CORS in each microservice, all of them (including ApiGateway) have the following code:

@Bean
public CorsFilter corsFilter() {
    final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOrigin("*");
    config.addAllowedHeader("*");
    config.addAllowedMethod("*");
    source.registerCorsConfiguration("/**", config);
    return new CorsFilter(source);
}

If I execute each microservice using the IDE, I can access Swagger of microservices from the ApiGateway without any problem, as you can see here (ApiGateway is executed on 8070 port):

Executed locally

However, when I execute them using docker-compose, and I try to access Swagger of any microservice through ApiGateway (mapping internal port to 8070), I am receiving the following error:

executed using docker

The weird thing is that, if I enter inside the ApiGateway docker using bash, and I execute curl transactionservice/api/v2/api-docs then I am receiving the corresponding json, so docker of ApiGateway is accessing to the Swagger of the rest of the dockers, but it is not able to access from my web browser.

Question: Why Swagger is unable to access other Swaggers when being executed using docker?


Solution

  • I finally found the problem: when executing using docker-compose, each microservice communicates to others using the service name, and docker-compose is able to translate that to the corresponding IP (that is the reason that in the second image, the Transactions link shows http://transactionservice/..., because in docker-compose.yml I was using that URL as the Resource URL).

    So, when I access to swagger in ApiGateway, it returns that URL as the Resource. However, that html is being executed in my machine, not inside the docker, so when it tries to access to http://transactionservice/api/v2/api-docs, my machine does not know anything about transactionservice.

    The solution was playing a bit with redirections in ApiGateway, using this configuration:

      zuul.routes.transaction.path: /transaction/**
      zuul.routes.transaction.url: http://transactionservice/api/transaction
      zuul.routes.transaction-swagger.path: /swagger/transaction/**
      zuul.routes.transaction-swagger.url: http://transactionservice/api
      zuul.routes.payment.path: /payment/**
      zuul.routes.payment.url: http://paymentservice/api/payment
      zuul.routes.payment-swagger.path: /swagger/payment/**
      zuul.routes.payment-swagger.url: http://paymentservice/api
    
      swagger.resources[0].name: transactions
      swagger.resources[0].url: /swagger/transaction/v2/api-docs
      swagger.resources[0].version: 2.0
      swagger.resources[1].name: payments
      swagger.resources[1].url: /swagger/payment/v2/api-docs
      swagger.resources[1].version: 2.0
    

    This way, all the requests are performed using the ApiGateway, even the swagger ones.