Installing a Custom Plugin in Docker: Kong Plugin Development
Tags: kong, kongplugi, docker, apigateway
Published: 2024-06-04 07:37:47

By Venkata Reddy Bhavanam
Author LinkedIn:https://www.linkedin.com/in/venkatareddybhavanam/

This is the second post on installing a custom plugin in Kong API Gateway. Please check out the 1st post if you need a quick introduction to Kong and how to install a custom plugin in a VM.
In this post, we’ll learn how to install a custom plugin in Docker.

We’ll use the same custom plugin code as we used in the previous post.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/twgwmpuvycimy3fxudsi.png)Kong Plugin Development

**Copying the code over here for completeness. The folder structure:**

`api-version/
├── handler.lua
└── schema.lua`

The plugin name `api-version` and the contents of `schema.lua`

```
local typedefs = require "kong.db.schema.typedefs"

local PLUGIN_NAME = "api-version"

local schema = {
  name = "api-version",
  fields = {
    { consumer = typedefs.no_consumer },  -- this plugin cannot be configured on a consumer (typical for auth plugins)
    { protocols = typedefs.protocols_http },
    { config = {
        type = "record",
        fields = {
          { request_header = typedefs.header_name {
              required = true,
              default = "Hello-World" } },
          { response_header = typedefs.header_name {
              required = true,
              default = "Bye-World" } },
        },
        entity_checks = {
          { at_least_one_of = { "request_header", "response_header" }, },
          { distinct = { "request_header", "response_header"} },
        },
      },
    },
  },
}

return schema
```

**Contents of `handler.lua`:**

```
local typedefs = require "kong.db.schema.typedefs"

local PLUGIN_NAME = "api-version"

local schema = {
  name = "api-version",
  fields = {
    { consumer = typedefs.no_consumer },  -- this plugin cannot be configured on a consumer (typical for auth plugins)
    { protocols = typedefs.protocols_http },
    { config = {
        type = "record",
        fields = {
          { request_header = typedefs.header_name {
              required = true,
              default = "Hello-World" } },
          { response_header = typedefs.header_name {
              required = true,
              default = "Bye-World" } },
        },
        entity_checks = {
          { at_least_one_of = { "request_header", "response_header" }, },
          { distinct = { "request_header", "response_header"} },
        },
      },
    },
  },
}

return schema

```
**Building the docker image:**
We’ll take a base Kong image, add the plugin(and dependencies, if any), and use the final image. The `Dockerfile`

`FROM kong/kong-gateway:3.2.2.1`

```
**USER root**

# luarocks install dependency-name # to install any dependencies for cusotm plugin
RUN mkdir /usr/local/share/lua/5.1/kong/plugins/api-versionCOPY ./api-version /usr/local/share/lua/5.1/kong/plugins/api-version
```

Here, we are taking Kong base image kong/kong-gateway:3.2.2.1 and adding our plugin code.

**We can now build it and run it with the following:**

```
docker build -t kong-demo .
docker run -d --name kong-demo \
  -p "8000-8001:8000-8001" \
  -e "KONG_ADMIN_LISTEN=0.0.0.0:8001" \
  -e "KONG_PROXY_LISTEN=0.0.0.0:8000" \
  -e "KONG_DATABASE=off" \
  -e "KONG_LOG_LEVEL=debug" \
  -e "KONG_PLUGINS=bundled,api-version" \
  kong-demo
```

As you can see, we specify the custom plugin name along with the bundled plugins using `KONG_PLUGINS `environment variable.

Kong can be run either in DB mode using Postgres (and Cassandra, but it will be deprecated) or DB Less mode. We’ll use db-less mode and the following declarative config to create a service, route, and apply the plugin for this demo.

```
config.yaml
_format_version: "3.0"
_transform: trueservices:
  - name: demo
    url: https://mockbin.org
    plugins:
      - name: api-version
    routes:
      - name: demo-route
        paths:
          - /echo
```
**Create the config with an API call to the admin API.**

`curl -X POST http://localhost:8001/config -F config=@config.yam`l

Verify the custom plugin works by visiting the proxy URL. We’ll use HTTPie

```
http :8000/echo --headers
HTTP/1.1 200 OK
Bye-World: 0.1
...
```
That’s it. In the next post, we’ll see how to install the custom plugin in Kubernetes. 

**For more information:** https://zelarsoft.com/