When deploying Spring Boot microservices in a Dockerized environment behind an API Gateway, one common issue developers face is dealing with internal Docker URLs that are not accessible from external systems. This problem becomes even more complicated when you need to integrate Swagger for API documentation, which often points to internal URLs that cannot be accessed directly.
In this article, we’ll walk through how to configure Swagger in a Spring Boot microservices environment behind an API Gateway, ensuring that Swagger documentation does not display internal Docker URLs and instead points to the public-facing API Gateway URLs.
Prerequisites
Before we dive into the steps, ensure you have the following:
- Spring Boot Microservices: A set of microservices, each running as a Spring Boot application.
- API Gateway: An API Gateway (such as Zuul or Spring Cloud Gateway) routing requests to your microservices.
- Docker: Each service running in a Docker container.
- Swagger: Swagger integrated for API documentation.
We will assume that the API Gateway and microservices are already set up and Dockerized. Let’s begin configuring Swagger correctly.
Step 1: Set Up Swagger in Spring Boot Microservices
For each microservice, you'll need to integrate Swagger to generate API documentation. If Swagger is not yet configured in your microservices, follow the steps below.
-
Add Swagger Dependencies: In the
pom.xml
file of each microservice, add the necessary Swagger dependencies.<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency>
-
Configure Swagger Docket Bean: In each microservice, configure the Swagger Docket Bean that will define the API documentation.
Create a configuration class, for example
SwaggerConfig.java
:import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; @Configuration @EnableSwagger2 public class SwaggerConfig { @Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.basePackage("com.example.microservice")) .paths(PathSelectors.any()) .build() .apiInfo(new ApiInfoBuilder().title("Microservice API").version("1.0").build()); } }
-
Access Swagger UI: After configuring Swagger, you can access the Swagger UI at
http://<service-host>:<port>/swagger-ui.html
for each microservice.
Step 2: Understanding the Problem with Dockerized Services
In a Dockerized environment, microservices often communicate with each other via internal URLs. For example, Service A may call Service B using the internal Docker network, which might look like http://service-b:8080
.
Swagger, however, will generate documentation using the internal Docker URLs like http://service-b:8080/api
instead of the public-facing URLs via the API Gateway. This becomes an issue because these internal URLs are not accessible outside the Docker network or for users accessing the API documentation.
Step 3: Integrate an API Gateway (e.g., Zuul or Spring Cloud Gateway)
To avoid exposing internal Docker URLs, you need to route all external traffic through an API Gateway. Here’s how you can configure an API Gateway using Spring Cloud Gateway:
-
Add Dependencies: Add the following dependencies in the
pom.xml
of your API Gateway project.<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency>
-
Configure API Gateway Routes: In the
application.yml
orapplication.properties
file, define the routes for your microservices. Ensure that all requests go through the API Gateway.For example, in
application.yml
:spring: cloud: gateway: routes: - id: service-a uri: lb://SERVICE-A # Service name registered in Eureka or direct URL predicates: - Path=/service-a/** - id: service-b uri: lb://SERVICE-B # Service name registered in Eureka or direct URL predicates: - Path=/service-b/**
This ensures that any request to
http://<api-gateway>/service-a/
will be routed toservice-a
and similarly forservice-b
. -
Start the API Gateway: After configuring the routes, start your API Gateway, which will route requests to the appropriate microservice.
Step 4: Configuring Swagger to Use Public API Gateway URLs
To ensure that Swagger generates documentation using the API Gateway URLs instead of internal Docker URLs, you need to configure Swagger to use the external URLs.
-
Set External API URL: Modify your Swagger configuration to set the external host for Swagger. You can achieve this by using the
externalDocs
property in theDocket
configuration.Update the
SwaggerConfig.java
class in each microservice to include a reference to the API Gateway URL:@Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.basePackage("com.example.microservice")) .paths(PathSelectors.any()) .build() .apiInfo(new ApiInfoBuilder().title("Microservice API").version("1.0").build()) .host("api-gateway-url.com"); // Set the public URL of your API Gateway }
In this example, replace
"api-gateway-url.com"
with the actual external URL of your API Gateway. -
Externalizing Base Path for Swagger UI: In some cases, you may need to set the base path for Swagger UI to use the API Gateway’s external URL. This can be done by configuring the
springfox.documentation.swagger.v2.path
property inapplication.yml
.springfox: documentation: swagger: v2: path: /swagger/v2
This ensures that Swagger’s generated paths point to the correct external routes.
Step 5: Test and Verify the Swagger Documentation
Now that you’ve configured Swagger to use the public API Gateway URLs, you need to test the Swagger UI and ensure it points to the correct routes.
-
Access Swagger UI: Open the Swagger UI by visiting
http://<api-gateway-url>/swagger-ui.html
.The documentation should now show the public API Gateway URLs (e.g.,
http://api-gateway-url.com/service-a/
) instead of the internal Docker service URLs (e.g.,http://service-a:8080/
). -
Test API Endpoints: Use the Swagger UI to test the API endpoints. When you invoke an endpoint through the Swagger UI, the request should route through the API Gateway and reach the correct microservice.
Step 6: Docker Networking Considerations
When deploying microservices in Docker containers, ensure the API Gateway can communicate with all microservices. You may need to configure Docker Compose or Docker Swarm networks for seamless communication.
For example, in docker-compose.yml
, define a shared network:
version: '3'
services:
api-gateway:
image: api-gateway-image
networks:
- microservice-network
service-a:
image: service-a-image
networks:
- microservice-network
service-b:
image: service-b-image
networks:
- microservice-network
networks:
microservice-network:
driver: bridge
This ensures that all services, including the API Gateway, can communicate within the same Docker network.
Conclusion
Configuring Swagger in Spring Boot microservices behind an API Gateway to avoid internal Docker URLs is an essential step for maintaining a clean, production-ready API documentation setup. By routing all traffic through the API Gateway and configuring Swagger to use the public-facing URLs, you ensure that Swagger documentation is accessible and accurate for external users.
By following these steps, you will successfully integrate Swagger with Spring Boot microservices behind an API Gateway, ensuring that your API documentation points to the correct external endpoints while keeping internal Docker URLs hidden.