Deploy Kong and Konga With Docker and Traefik 2

I was learning how to use Kong API Gateway recently. Although it is a great product and is easy to use, I can't find the right instructions to achieve the features that I needed. for example:
  • Use https on Kong Admin API
  • Http to https redirect
  • Automation of SSL certificate
  • Deploy Konga which is a Github project of GUI for Kong Admin API
  • We can still use Admin API locally on the server via curl or Httpie

After a lot of attempts, I settle with using Traefik as reverse proxy to achieve above goals. If you know any correct or better ways of using Kong and Konga, please let me know.

In this article, I am going to use file provider to config Traefik. If you are not sure how to use file provider, please check my previous post. I will list all files and their content on this article as my default configuration does not use file provider.

First thing first, let’s create the necessary files.

1
2
3
4
5
6
touch docker-compose.yml
mkdir data && mkdir kong && mkdir data/configurations
touch kong/docker-compose.yml && touch kong/kong.env
touch data/traefik.yml && touch data/acme.json
touch data/configurations/dynamic.yml
chmod 600 data/acme.json

Let’s start putting contents on these files.

Deployment of Traefik

~/docker-compose.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
version: '3.7'

services:
traefik:
image: traefik:latest
container_name: traefik
restart: always
security_opt:
- no-new-privileges:true
ports:
- 80:80
- 443:443
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./data/traefik.yml:/traefik.yml:ro
- ./data/acme.json:/acme.json
# Add folder with dynamic configuration yml
- ./data/configurations:/configurations
networks:
- proxy

networks:
proxy:
external: true

~/data/traefik.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
api:
dashboard: true

entryPoints:
web:
address: :80
http:
redirections:
entryPoint:
to: websecure

websecure:
address: :443
http:
middlewares:
- [email protected]
tls:
certResolver: letsencrypt

providers:
file:
filename: /configurations/dynamic.yml

certificatesResolvers:
letsencrypt:
acme:
email: [email protected]
keyType: EC384
httpChallenge:
entryPoint: web

~/data/configurations/dynamic.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# Dynamic configuration
http:
routers:
dashboard:
service: [email protected]
middlewares:
- "user-auth"
rule: "Host(`dash.yourdomain`)"
kong:
service: kong-service
middlewares:
rule: "Host(`kong.yourdomain`)"
konga:
service: konga-service
middlewares:
rule: "Host(`konga.yourdomain`)"
middlewares:
secureHeaders:
headers:
sslRedirect: true
forceSTSHeader: true
stsIncludeSubdomains: true
stsPreload: true
stsSeconds: 31536000

# UserName : admin
# Password : qwer1234
user-auth:
basicAuth:
users:
- "admin:$apr1$tm53ra6x$FntXd6jcvxYM/YH0P2hcc1"
services:
kong-service:
loadBalancer:
servers:
- url: "http://ip-address-of-kong:8000"
konga-service:
loadBalancer:
servers:
- url: "http://ip-address-of-konga:1337"
tls:
options:
default:
cipherSuites:
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
minVersion: VersionTLS12

These are all the files we need to start Traefik. Please make sure your have change all instance of yourdomain in the config to your own domain and then run docker-compose up -d. We should be able to access the Traefik dashboard at dash.yourdomain once its container is up and running.

Deployment of Kong and Konga

~/kong/docker-compose.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
version: '2.1'

services:
#######################################
# Postgres: Kong Database
#######################################
kong-database:
image: postgres:9.6-alpine
container_name: kong-db
environment:
POSTGRES_DB: kong
POSTGRES_USER: kong
POSTGRES_PASSWORD: kong
networks:
- default
healthcheck:
test: ["CMD", "pg_isready", "-U", "kong"]
interval: 10s
timeout: 5s
retries: 5
restart: on-failure

#######################################
# Kong database migration
#######################################
kong-migrations:
image: kong:latest
command: kong migrations bootstrap
depends_on:
kong-database:
condition: service_healthy
env_file:
- ./kong.env
networks:
- default
restart: on-failure

#######################################
# Kong: The API Gateway
#######################################
kong:
image: kong:latest
container_name: kong-api
depends_on:
kong-database:
condition: service_healthy
env_file:
- kong.env
networks:
- default
- proxy
ports:
- "127.0.0.1:8001:8001"
healthcheck:
test: ["CMD", "kong", "health"]
interval: 10s
timeout: 10s
retries: 10
restart: on-failure

#######################################
# Konga database migration
#######################################
konga-prepare:
image: pantsel/konga
command: "-c prepare -a postgres -u postgresql://kong:[email protected]:5432/konga_db"
networks:
- default
restart: on-failure
depends_on:
kong-database:
condition: service_healthy

#######################################
# Konga: GUI of KONG Admin API
#######################################
konga:
image: pantsel/konga
env_file:
- kong.env
networks:
- default
- proxy
restart: on-failure
depends_on:
kong-database:
condition: service_healthy

networks:
proxy:
external: true

There are some information I need to mention.

  • You have a choice to NOT use database for Konga. If you choose not to use a database, you can comment out konga-prepare but you must create a persistent volume to store Konga data.
    1
    2
    volumes:
    - konga-data:/app/kongadata
    However, you will always see below warnings in logs.
    1
    2
    3
    4
    5
    konga_1 | The default `sails-disk` adapter is not designed for use as a production database;
    konga_1 | (it stores the entire contents of your database in memory)
    konga_1 | Instead, please use another adapter; e.g. sails-postgresql or sails-mongo.
    konga_1 | For more info, see: http://sailsjs.org/documentation/concepts/deployment
    konga_1 | To hide this warning message, enable `sails.config.orm.skipProductionWarnings`.
    As I don’t want to see these warnings, I chose to add a database in existing postgresql container and use konga-prepare to prepare the database I need. This is another reason I don’t use Cassandra with Kong.
  • The use of postgres:9.6-alpine image. Konga does not support the latest postgres version, I found this information from official github issues here.
  • I put all environment variables that I need in kong.env file.

    ~/kong/kong.env

    1
    2
    3
    4
    5
    6
    7
    8
    9
    KONG_DATABASE=postgres
    KONG_PG_HOST=kong-db
    KONG_PG_USER=kong
    KONG_PG_PASSWORD=kong
    KONG_PG_DATABASE=kong
    KONG_ADMIN_LISTEN=0.0.0.0:8001

    TOKEN_SECRET=someSecret12345
    NODE_ENV=production
    Once I’ve put contents to these two files, let’s go to ~/kong/ and run docker-compose up -d. It should create postgresql, kong and konga containers automatically for you.

Adding Kong and Konga to Traefik

Once all containers are running, we will use docker inspect <container_id> to get the ip address of Kong and Konga containers. Then we can put these ip address under Services on ~/data/configurations/dynamic.yml.

1
2
3
4
5
6
7
8
9
services:
kong-service:
loadBalancer:
servers:
- url: "http://ip-address-of-kong:8000"
konga-service:
loadBalancer:
servers:
- url: "http://ip-address-of-konga:1337"

If you are not too sure how to add ip address to services, please check my post of file provider. I will create a video for this post when I have time.

If you have any questions, please feel free to leave me a comment.

Thank you and see you next time.