Docker containers
Containers DevOps Docker Docker Compose Microservice YAML

How to Build a Docker Container with an API Gateway

Welcome to today’s post.

In a previous post I showed how to create a Docker multi-container API service image. 

Today I will be extending this by showing how to use Docker Compose to create a container that includes an API gateway container that routes to other API service containers. Our multi-container Docker image, when complete will resemble the architecture below:

API Gateway Docker Container

The difference between the basic multi-container image and the above will be the following features:

  1. Ability to route HTTP requests into our API gateway to one of our internal API container services.
  2. Secure our internal API container services by using authentication tokens from our internal identity API service, identity-api.
  3. Decouple our client applications from the internal API services, removing dependency of the internal API references from client applications.

Below is the docker compose YAML file we can use to build the above container:

#docker-compose.yml (Base)
version: '3.4'
services:
  bookloan-gateway-api:
    image: bookloangatewayapi:${TAG:-latest}
    ports:
      - "5200:80"

  identity-api:
    image: bookloanidentityapi:${TAG:-latest}
    env_file: 
      - C:\development\environment\bookloan_identity_env.env
    ports:
      - "5100:80"

  catalog-api:
    image: bookloancatalogapi:${TAG:-latest}
    env_file: 
      - C:\development\environment\bookloan_cat_env.env
    ports:
      - "5110:80"

  loan-api:
    image: bookloanloanapi:${TAG:-latest}
    env_file: 
      - C:\development\environment\bookloan_cat_env.env
    ports:
      - "5120:80"

Our multi-container image is started with four container services, catalog-api, loan-api, identity-api and gateway-api. Each of the internal API container services has an internal TCP port 80 that allows them to be accessed from the API gateway, and to the external TCP host ports that can be used for debugging purposes in a pre-production environment. If we want to just publish the port to internal container services, then we use the expose directive to specify which ports to hide from the container host. The example below hides the external ports for the catalog-api, loan-api and identity-api internal API container services:

expose:
  - “5120”
  - “5110”
  - “5100”

Before we run the above container image, we should ensure each of the internal containers including the API gateway container is built.

After running the container using:

docker-compose up

We will see the containers created and running.

To verify the API gateway container and internal containers are started, we use the docker container ls command.

Our API gateway, defined using the Ocelot configuration is shown below:

{
  "Routes": [
    {
      "DownstreamPathTemplate": "/api/book/{everything}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "catalog-api",
          "Port": 80
        }
      ],
      "UpstreamPathTemplate": "/book/{everything}", 
      "UpstreamHttpMethod": [ "POST", "PUT", "GET" ],
      "AuthenticationOptions": {
        "AuthenticationProviderKey": "IdentityApiKey",
        "AllowedScopes": []
      }
    },
    {
      "DownstreamPathTemplate": "/api/loan/{everything}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "loan-api",
          "Port": 80
        }
      ],
      "UpstreamPathTemplate": "/loan/{everything}",
      "UpstreamHttpMethod": [ "POST", "PUT", "GET" ],
      "AuthenticationOptions": {
        "AuthenticationProviderKey": "IdentityApiKey",
        "AllowedScopes": []
      }
    }
  ],
  "GlobalConfiguration": {
    "BaseUrl": http://localhost:5200
  }
}

The above routing configuration applies the following rules:

  1. Routing of upstream catalog API service requests of the form /book/{everything} will map to downstream API service requests of in the format /api/book/{everything}.
  2. For the catalog API service, the downstream host network is specified with the name of the host, catalog-api.
  3. The API gateway network TCP port is accessible to the container host, specified in the GlobalConfiguration key with the BaseUrl.

To test our API gateway container, we run the HTTP request through our container host gateway using POSTMAN. To submit a request to http://book/list we first obtain a JWT token from our identity API service (which can either be within our container or outside of it). We then paste the token as a bearer token into the HTTP request header in the Authorization key. After submitting the HTTP request, we should see the JSON response back with data from our gateway: 

If our routing fails, then the most common error would be a 404 (not found error).

As we can see, deploying and running our container as a Docker multi-container API gateway is quite straightforward.

That is all for today’s post.

I hope you found this post useful and informative.

Social media & sharing icons powered by UltimatelySocial