├── Kong Way.png ├── Dockerfile ├── package.json ├── server.js ├── manual_instructions.txt ├── docker-compose.yml └── README.md /Kong Way.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trevorkennedy/kong_docker_demo/HEAD/Kong Way.png -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:latest 2 | WORKDIR /app 3 | COPY package*.json ./ 4 | RUN npm install 5 | COPY . . 6 | CMD node server.js 7 | EXPOSE 3000 -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kong_node", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "server.js", 6 | "author": "", 7 | "license": "ISC", 8 | "scripts": { 9 | "start": "node server.js" 10 | }, 11 | "dependencies": { 12 | "express": "^4.16.1" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const express = require('express'); 4 | 5 | // Constants 6 | const PORT = 3000; 7 | const HOST = '0.0.0.0'; 8 | 9 | // App 10 | const app = express(); 11 | app.get('/', function (req, res) { 12 | // Return current system time 13 | const time = new Date(Date.now()).toLocaleString(); 14 | res.send(`Current time: ${time}`); 15 | }); 16 | 17 | app.listen(PORT, HOST); 18 | console.log(`Running on http://${HOST}:${PORT}`); 19 | -------------------------------------------------------------------------------- /manual_instructions.txt: -------------------------------------------------------------------------------- 1 | # Use these commands to manually run the Docker containers instead of using docker-compose 2 | 3 | docker build -t kong-node-app . 4 | 5 | docker network create kong-net 6 | 7 | docker run --name kong-db --network=kong-net -e "POSTGRES_USER=kong" -e "POSTGRES_DB=kong" -e "POSTGRES_PASSWORD=kong" -d postgres:latest 8 | 9 | docker run --rm ` 10 | --network=kong-net ` 11 | -e "KONG_DATABASE=postgres" ` 12 | -e "KONG_PG_HOST=kong-db" ` 13 | -e "KONG_PG_PASSWORD=kong" ` 14 | kong:latest kong migrations bootstrap 15 | 16 | docker run -d --name kong-api --network=kong-net -e "KONG_DATABASE=postgres" -e "KONG_PG_HOST=kong-db" -e "KONG_PG_PASSWORD=kong" -e "KONG_ADMIN_LISTEN=0.0.0.0:8001" -p 8000:8000 -p 127.0.0.1:8001:8001 kong:latest 17 | 18 | docker run --name kong-app --network=kong-net -d trevor/kong-node-app 19 | 20 | docker logs kong-app -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2.1' 2 | 3 | networks: 4 | kong-net: 5 | 6 | services: 7 | 8 | ####################################### 9 | # Postgres: The database used by Kong 10 | ####################################### 11 | kong-database: 12 | image: postgres:latest 13 | container_name: kong-db 14 | environment: 15 | POSTGRES_DB: kong 16 | POSTGRES_USER: kong 17 | POSTGRES_PASSWORD: kong 18 | networks: 19 | - kong-net 20 | healthcheck: 21 | test: ["CMD", "pg_isready", "-U", "kong"] 22 | interval: 10s 23 | timeout: 5s 24 | retries: 5 25 | restart: on-failure 26 | 27 | ####################################### 28 | # Kong database migration 29 | ####################################### 30 | kong-migrations: 31 | image: kong:latest 32 | command: kong migrations bootstrap && kong migrations up && kong migrations finish 33 | depends_on: 34 | kong-database: 35 | condition: service_healthy 36 | environment: 37 | KONG_DATABASE: postgres 38 | KONG_PG_HOST: kong-db 39 | KONG_PG_USER: kong 40 | KONG_PG_PASSWORD: kong 41 | KONG_PG_DATABASE: kong 42 | networks: 43 | - kong-net 44 | restart: on-failure 45 | 46 | ####################################### 47 | # Kong: The API Gateway 48 | ####################################### 49 | kong: 50 | image: kong:latest 51 | container_name: kong-api 52 | depends_on: 53 | kong-database: 54 | condition: service_healthy 55 | environment: 56 | KONG_DATABASE: postgres 57 | KONG_PG_HOST: kong-db 58 | KONG_PG_USER: kong 59 | KONG_PG_PASSWORD: kong 60 | KONG_PG_DATABASE: kong 61 | KONG_ADMIN_LISTEN: 0.0.0.0:8001 62 | networks: 63 | - kong-net 64 | ports: 65 | - "8000:8000" 66 | - "8001:8001" 67 | healthcheck: 68 | test: ["CMD", "kong", "health"] 69 | interval: 10s 70 | timeout: 10s 71 | retries: 10 72 | restart: on-failure 73 | 74 | ####################################### 75 | # Example Microservice 76 | ####################################### 77 | app: 78 | build: . 79 | container_name: kong-app 80 | networks: 81 | - kong-net 82 | restart: on-failure -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Kong Demo Using Docker 2 | This is a demo of the [Kong API Gateway](https://konghq.com/) which exhibits how to run Kong in a Docker environment as a proxy for a public web service as well as a Node.js microservice. 3 | 4 | ## Requirements 5 | - Linux, macOS, Windows (tested on Windows 10) 6 | - [Docker](https://www.docker.com) 7 | 8 | ## Installation 9 | In a terminal window, clone this repository: 10 | 11 | ``` 12 | https://github.com/trevorkennedy/kong_docker_demo 13 | ``` 14 | 15 | ## Running 16 | 17 | Change to your local repo directory: 18 | 19 | ``` 20 | cd kong_docker_demo 21 | ``` 22 | 23 | Start the demo using [Docker Compose](https://docs.docker.com/compose/): 24 | 25 | ``` 26 | docker-compose up -d 27 | ``` 28 | 29 | Note that the ***-d*** flag will running the containers as a background process. The compose file does 4 things: 30 | 31 | 1. Creates PostgreSQL container as a backend data store (configuration info) for Kong . 32 | 2. Creates an ephemeral to initialize the Postgres database. 33 | 3. Builds a container for the system time Node.js microservice. 34 | 4. Runs the Kong API Gateway as a container. 35 | 36 | ## Verify 37 | 38 | Verify the containers (*kong-api, kong-db, kong-app*) are all running by using: 39 | 40 | ``` 41 | docker ps 42 | ``` 43 | 44 | Verify that the Kong Gateway and Admin API are responding: 45 | 46 | ``` 47 | curl http://localhost:8000 48 | curl http://localhost:8001 49 | ``` 50 | 51 | ## Create a Service Proxy 52 | 53 | Now, create a local service named ***ip-service*** that will forward requests to the [Big Cloud Data API](https://www.bigdatacloud.com/). This is a two part process as both the service and then the route must be established like so: 54 | 55 | ``` 56 | curl -i -X POST --url http://localhost:8001/services/ --data 'name=ip-service' --data 'url=https://api.bigdatacloud.net/' 57 | curl -i -X POST --url http://localhost:8001/services/ip-service/routes --data 'hosts[]=ip-service' 58 | ``` 59 | 60 | You can now test both the plubic API and the proxied service using cURL: 61 | ``` 62 | curl https://api.bigdatacloud.net/data/client-ip 63 | curl http://localhost:8000/data/client-ip --header 'Host: ip-service' 64 | ``` 65 | 66 | ## Create a Microservice Endpoint 67 | 68 | Following the recipe above, we can build an endpoint for the Node.js microservice: 69 | 70 | ``` 71 | curl -i -X POST --url http://localhost:8001/services/ --data 'name=time-service' --data 'url=http://kong-app:3000' 72 | curl -i -X POST --url http://localhost:8001/services/time-service/routes --data 'hosts[]=time-service' 73 | ``` 74 | 75 | Recall that this service is running in the *kong-app* container and is exposed to the isolated Docker network via port 3000 but callers cannot access it without going through the API gateway. We can reach the ***time-service*** using the *Host* header: 76 | 77 | ``` 78 | curl http://localhost:8000 --header 'Host: time-service' 79 | ``` 80 | 81 | Use this endpoint to see a list of all the services enabled thus far: 82 | 83 | ``` 84 | curl http://localhost:8001/services 85 | ``` 86 | 87 | ## Enable Rate Limiting 88 | 89 | Added rate limiting (a maximum of 5 requests per minute in this case) to a service is as simple as running a single command: 90 | 91 | ``` 92 | curl -X POST http://localhost:8001/services/time-service/plugins/ --data "name=rate-limiting" --data "config.minute=5" --data "config.policy=local" 93 | ``` 94 | 95 | If you hit the *time-service* endpoint again, you will see additional headers in the response indicating the rate limit and usage: 96 | 97 | ``` 98 | curl http://localhost:8000 --header 'Host: time-service' 99 | ``` 100 | 101 | ## Add Authorization 102 | 103 | Key-based authorization can be add to the *time-service* endpoint by enabling the ***key-auth*** plugin, creating a user (*QA* in this example) and then providing the access key: 104 | 105 | ``` 106 | curl -i -X POST --url http://localhost:8001/services/time-service/plugins/ --data 'name=key-auth' 107 | curl -i -X POST --url http://localhost:8001/consumers/ --data "username=QA" 108 | curl -i -X POST --url http://localhost:8001/consumers/QA/key-auth/ --data 'key=Hello_Kong!' 109 | ``` 110 | 111 | Test the *time-service* endpoint both with and without specifying an API key: 112 | 113 | ``` 114 | curl http://localhost:8000 --header 'Host: time-service' 115 | curl http://localhost:8000 --header 'Host: time-service' --header "apikey: Hello_Kong!" 116 | ``` 117 | 118 | ## Conclusion 119 | 120 | You have now added key-based authorization and rate limiting to a microservice without writing a single line of code. 121 | 122 | ![The Kong Way](Kong%20Way.png) 123 | 124 | ## Clean Up 125 | 126 | Tear everything down using: 127 | 128 | ``` 129 | docker-compose down 130 | ``` 131 | 132 | *** 133 | --------------------------------------------------------------------------------