KONG-34 POC - Building Kong from source

KONG-34 POC - Building Kong from source

KONG-34: POC - Building Kong from source Closed

Building Kong Gateway from Source on Ubuntu 24.04

1. Prerequisites

Before you begin, ensure your system meets the following requirements:

  • Operating System: Ubuntu 24.04 (or a compatible Debian-based distribution).

  • User Privileges: A user account with sudo access.

  • Docker: Required to build a custom Docker image.

2. Clone the Kong Gateway Repository

Start by cloning the Kong Gateway source code from its official GitHub repository.

git clone https://github.com/Kong/kong.git cd kong

3. Install System Dependencies

Kong and its build tools (Bazel/Bazelisk) require several system packages, including compilers, development libraries, and utility tools. Install them using apt.

sudo apt update sudo apt install -y \ make \ build-essential \ g++ \ unzip \ zip \ curl \ default-jdk \ automake \ file \ git \ libyaml-dev \ libprotobuf-dev \ m4 \ perl \ pkg-config \ procps \ valgrind \ zlib1g-dev

4. Install Bazelisk

Bazelisk is the recommended way to manage Bazel versions. It automatically downloads the correct Bazel version required by your Kong project.

# Download the latest Bazelisk release for Linux AMD64 sudo curl -L https://github.com/bazelbuild/bazelisk/releases/latest/download/bazelisk-linux-amd64 -o /usr/local/bin/bazel # Make Bazelisk executable sudo chmod +x /usr/local/bin/bazel # Verify the installation and trigger Bazelisk to download the appropriate Bazel version bazel version

5. Install GitHub CLI (gh)

The GitHub CLI (gh) is a powerful tool for interacting with GitHub directly from your terminal. While not strictly required for building Kong, it's often useful in a development workflow.

# Install wget if not present (type -p wget >/dev/null || (sudo apt update && sudo apt install wget -y)) # Add GitHub CLI GPG key sudo mkdir -p -m 755 /etc/apt/keyrings out=$(mktemp) && wget -nv -O$out https://cli.github.com/packages/githubcli-archive-keyring.gpg cat $out | sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg # Add GitHub CLI repository to apt sources sudo mkdir -p -m 755 /etc/apt/sources.list.d echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null # Update apt cache and install gh sudo apt update sudo apt install gh -y # Authenticate with GitHub (interactive step) gh auth login

Note: The gh auth login command will prompt you to authenticate your GitHub account through your web browser or by pasting a token.

6. Build Kong Gateway

With all dependencies and tools in place, you can now proceed to build Kong. Ensure you are in the kong repository directory (cd kong).

6.1 Build Kong's Internal Dependencies

This command builds the internal dependencies required by Kong, including its Luarocks modules and C components.

bazel build //build:kong --sandbox_debug --verbose_failures

6.2 Modify .bazelrc file

Update the .bazelrc file in Kong's route folder to include the following release settings:

build:release --//:debug=true build:release --//:licensing=false build:release --action_env=BUILD_NAME=kong-eureka

6.3 Perform an Official Release Build

This command compiles the final Kong Gateway binary optimized for release. The compiled artifact will be located in the bazel-bin/build/ directory.

bazel build //build:kong --verbose_failures --config release

6.4 Build a Debian Package

This step is crucial for building the Docker image as it relies on the generated .deb package. This command builds the Debian package (.deb) which will contain the compiled Kong Gateway and its dependencies. The .deb package will be located in the bazel-bin/pkg/ directory.

bazel build --verbose_failures --config release :kong_deb

After this command, you should find a file named kong.amd64.deb (or similar, depending on your architecture) in bazel-bin/pkg/.

Note: other supported binary packages (see details in Official build section)

  • :kong_deb

  • :kong_el8

  • :kong_aws2

  • :kong_aws2023

7. Build a Custom Docker Image (kong-eureka)

To containerize your custom-compiled Kong Gateway using the .deb package, follow these steps.

  1. Navigate to the Kong repository root:

    cd kong
  2. Fetch the docker-entrypoint.sh script:
    This script is commonly used in official Kong Docker images to handle startup and configuration.

    curl -O https://raw.githubusercontent.com/Kong/docker-kong/master/docker-entrypoint.sh chmod +x docker-entrypoint.sh
  3. Move the generated Debian package to the Docker build context:

    mv bazel-bin/pkg/kong.amd64.deb .
  4. Create a Dockerfile:
    Create a file named Dockerfile in the current directory (kong repository root) with the following content. This Dockerfile is based on the official Kong Docker builds.

    FROM ubuntu:24.04 COPY kong.amd64.deb /tmp/kong.deb RUN set -ex; \ apt-get update \ && apt-get install --yes /tmp/kong.deb \ && rm -rf /var/lib/apt/lists/* \ && rm -rf /tmp/kong.deb \ && chown kong:0 /usr/local/bin/kong \ && chown -R kong:0 /usr/local/kong \ && ln -s /usr/local/openresty/luajit/bin/luajit /usr/local/bin/luajit \ && ln -s /usr/local/openresty/luajit/bin/luajit /usr/local/bin/lua \ && ln -s /usr/local/openresty/nginx/sbin/nginx /usr/local/bin/nginx \ && kong version COPY docker-entrypoint.sh /docker-entrypoint.sh USER kong ENTRYPOINT ["/docker-entrypoint.sh"] EXPOSE 8000 8443 8001 8444 8002 8445 8003 8446 8004 8447 STOPSIGNAL SIGQUIT HEALTHCHECK --interval=10s --timeout=10s --retries=10 CMD kong health CMD ["kong", "docker-start"]
  5. Build the Docker image:
    Run the following command in the kong repository root (where your Dockerfile, docker-entrypoint.sh, and kong.amd64.deb are located).

    docker build --platform linux/amd64 --no-cache -t kong-eureka .
  6. Run and verify the custom Docker image:

    docker run -it --rm kong-eureka kong version

    This command will run your custom kong-eureka image and execute kong version inside it, performing a sanity check of the successful build and packaging. The output will look like:

3.10.0

Running and testing Kong Gateway docker image

1. Run Kong with docker-compose

1.1 Create a docker-compose.yml file:
Place the following content into a file named docker-compose.yml in your chosen directory.

volumes: kong_db_data: {} # Named volume to persist Postgres data across container restarts networks: kong-net: # Custom bridge network for isolated Kong and Postgres communication driver: bridge # Common environment variables used by Kong services (bootstrap and CP) x-kong-config: &kong-env KONG_DATABASE: postgres # Use Postgres as the backing database KONG_PG_HOST: kong-database # Hostname of the Postgres service KONG_PG_DATABASE: kong # Name of the database to connect to KONG_PG_USER: kong # Database username KONG_PG_PASSWORD: kong # Database password services: kong-database: container_name: kong-database image: postgres:latest # Official Postgres image restart: on-failure # Restart if the container fails volumes: - kong_db_data:/var/lib/postgresql/data # Mount the volume for persistent data networks: - kong-net # Connect to the shared Kong network environment: POSTGRES_USER: kong # Set DB user inside the container POSTGRES_DB: kong # Create this database on first run POSTGRES_PASSWORD: kong # Set the password for the DB user healthcheck: # Ensure the DB is ready before starting dependent services test: ["CMD", "pg_isready", "-U", "kong"] interval: 5s timeout: 10s retries: 10 ports: - '5432:5432' # Optional: expose Postgres on localhost for debugging kong-bootstrap: image: '${GW_IMAGE:-kong-eureka:latest}' # Kong Gateway image (default to latest version) container_name: kong-bootstrap networks: - kong-net depends_on: kong-database: condition: service_healthy # Wait until Postgres is up and healthy restart: on-failure environment: <<: *kong-env # Reuse environment config from x-kong-config KONG_PASSWORD: handyshake # Admin GUI password (required for RBAC) command: kong migrations bootstrap # Run DB migrations to initialize Kong schema kong-cp: image: '${GW_IMAGE:-kong-eureka:latest}' # Main Kong Gateway Control Plane (default to latest version) container_name: kong-cp restart: on-failure networks: - kong-net environment: <<: *kong-env KONG_ADMIN_LISTEN: 0.0.0.0:8001, 0.0.0.0:8444 ssl # Admin API on HTTP + HTTPS KONG_ADMIN_GUI_LISTEN: 0.0.0.0:8002, 0.0.0.0:8445 ssl # Kong Manager on HTTP + HTTPS KONG_ADMIN_GUI_URL: http://${GW_HOST:-localhost}:8002 # URL for GUI links KONG_PASSWORD: handyshake # Required for logging in to Kong Manager (RBAC) KONG_PROXY_ACCESS_LOG: /dev/stdout KONG_ADMIN_ACCESS_LOG: /dev/stdout KONG_PROXY_ERROR_LOG: /dev/stderr KONG_ADMIN_ERROR_LOG: /dev/stderr KONG_PLUGINS: bundled depends_on: kong-bootstrap: condition: service_completed_successfully # Start only after bootstrap has succeeded ports: - "8000:8000" # Proxy HTTP - "8443:8443" # Proxy HTTPS - "8001:8001" # Admin API HTTP - "8444:8444" # Admin API HTTPS - "8002:8002" # Kong Manager HTTP - "8445:8445" # Kong Manager HTTPS wiremock: image: wiremock/wiremock:latest # or a specific version like 2.35.0 container_name: wiremock-server networks: - kong-net ports: - "8080:8080" # WireMock HTTP server volumes: - ./wiremock-data:/home/wiremock # Mount a volume for mappings and files command: --verbose # Optional: add WireMock startup parameters

This docker-compose.yml file defines a multi-service application and based on docker-compose file from Install Kong Gateway using Docker Compose section of official Kong documentation:

  • kong-database: A PostgreSQL database container that Kong uses to store its configuration. It uses a named volume (kong_db_data) for data persistence.

  • kong-bootstrap: A temporary service that runs Kong database migrations to set up the schema in PostgreSQL.

  • kong-cp: The main Kong Control Plane service, which runs the Kong Gateway. It exposes various ports for the proxy (8000/8443), Admin API (8001/8444), and Kong Manager GUI (8002/8445). It waits for the kong-bootstrap to complete successfully. It defaults to using the kong-eureka:latest image.

  • wiremock: A WireMock server, useful for API mocking during development or testing. It's connected to the same network as Kong and exposes port 8080. It also mounts a volume for persisting mappings.

  • kong-net: A custom bridge network for internal communication between services.

  • kong_db_data: A named volume for persistent PostgreSQL data.

1.2 Prepare for WireMock
Create a directory for its persistent data and mappings:

mkdir wiremock-data

and two sub-directories

  • __files – place in this directory

  • mappings – place in this directory

1.3 Start the services with Docker Compose:
Ensure you are in the directory containing docker-compose.yml.

# To use your custom 'kong-eureka' image (which is the default in the provided docker-compose.yml) docker compose up -d # If you want to explicitly specify the image (e.g., if you renamed it or want to use a specific tag) # GW_IMAGE=kong-eureka:latest docker compose up -d

2. Verify the installation

Verify Kong Gateway Admin API

curl -X GET "http://localhost:8001/"

You should receive a JSON response from Kong's Admin API:

{ "edition": "community", "version": "3.10.0", "plugins": { "enabled_in_cluster": [], "available_on_server": { "request-size-limiting": { "version": "3.10.0", "priority": 951 }, "rate-limiting": { "version": "3.10.0", "priority": 910 }, "response-ratelimiting": { "version": "3.10.0", "priority": 900 }, "syslog": { "version": "3.10.0", "priority": 4 }, "loggly": { "version": "3.10.0", "priority": 6 }, "datadog": { "version": "3.10.0", "priority": 10 }, "ldap-auth": { "version": "3.10.0", "priority": 1200 }, "statsd": { "version": "3.10.0", "priority": 11 }, "bot-detection": { "version": "3.10.0", "priority": 2500 }, "aws-lambda": { "version": "3.10.0", "priority": 750 }, "request-termination": { "version": "3.10.0", "priority": 2 }, "prometheus": { "version": "3.10.0", "priority": 13 }, "proxy-cache": { "version": "3.10.0", "priority": 100 }, "session": { "version": "3.10.0", "priority": 1900 }, "acme": { "version": "3.10.0", "priority": 1705 }, "grpc-gateway": { "version": "3.10.0", "priority": 998 }, "grpc-web": { "version": "3.10.0", "priority": 3 }, "pre-function": { "version": "3.10.0", "priority": 1000000 }, "post-function": { "version": "3.10.0", "priority": -1000 }, "azure-functions": { "version": "3.10.0", "priority": 749 }, "zipkin": { "version": "3.10.0", "priority": 100000 }, "opentelemetry": { "version": "3.10.0", "priority": 14 }, "ai-proxy": { "version": "3.10.0", "priority": 770 }, "ai-prompt-decorator": { "version": "3.10.0", "priority": 772 }, "ai-prompt-template": { "version": "3.10.0", "priority": 773 }, "ai-prompt-guard": { "version": "3.10.0", "priority": 771 }, "ai-request-transformer": { "version": "3.10.0", "priority": 777 }, "ai-response-transformer": { "version": "3.10.0", "priority": 768 }, "standard-webhooks": { "version": "3.10.0", "priority": 760 }, "redirect": { "version": "3.10.0", "priority": 779 }, "jwt": { "version": "3.10.0", "priority": 1450 }, "acl": { "version": "3.10.0", "priority": 950 }, "correlation-id": { "version": "3.10.0", "priority": 100001 }, "cors": { "version": "3.10.0", "priority": 2000 }, "oauth2": { "version": "3.10.0", "priority": 1400 }, "tcp-log": { "version": "3.10.0", "priority": 7 }, "udp-log": { "version": "3.10.0", "priority": 8 }, "file-log": { "version": "3.10.0", "priority": 9 }, "http-log": { "version": "3.10.0", "priority": 12 }, "key-auth": { "version": "3.10.0", "priority": 1250 }, "hmac-auth": { "version": "3.10.0", "priority": 1030 }, "basic-auth": { "version": "3.10.0", "priority": 1100 }, "ip-restriction": { "version": "3.10.0", "priority": 990 }, "request-transformer": { "version": "3.10.0", "priority": 801 }, "response-transformer": { "version": "3.10.0", "priority": 800 } } }, "hostname": "62e7ff966f96", "lua_version": "LuaJIT 2.1.0-20250117", "node_id": "337446c6-857d-4d8c-8642-1452d1d134ea", "configuration": { "lmdb_validation_tag": "3.10", "nginx_supstream_directives": {}, "db_cache_warmup_entities": [ "services" ], "plugins": [ "bundled" ], "wasm_filters": [ "bundled", "user" ], "lua_max_resp_headers": 100, "headers": [ "server_tokens", "latency_tokens", "x-kong-request-id" ], "nginx_wasm_wasmer_directives": {}, "ssl_cipher_suite": "intermediate", "lua_max_uri_args": 100, "nginx_wasm_main_directives": {}, "ssl_ciphers": "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305", "nginx_err_logs": "/usr/local/kong/logs/error.log", "lua_max_post_args": 100, "nginx_acc_logs": "/usr/local/kong/logs/access.log", "admin_acc_logs": "/usr/local/kong/logs/admin_access.log", "nginx_conf": "/usr/local/kong/nginx.conf", "nginx_kong_gui_include_conf": "/usr/local/kong/nginx-kong-gui-include.conf", "nginx_kong_conf": "/usr/local/kong/nginx-kong.conf", "kong_process_secrets": "/usr/local/kong/.kong_process_secrets", "nginx_kong_stream_conf": "/usr/local/kong/nginx-kong-stream.conf", "nginx_inject_conf": "/usr/local/kong/nginx-inject.conf", "nginx_kong_inject_conf": "/usr/local/kong/nginx-kong-inject.conf", "nginx_kong_stream_inject_conf": "/usr/local/kong/nginx-kong-stream-inject.conf", "lua_package_cpath": "", "ssl_cert_csr_default": "/usr/local/kong/ssl/kong-default.csr", "nginx_http_ssl_protocols": "TLSv1.2 TLSv1.3", "nginx_stream_ssl_protocols": "TLSv1.2 TLSv1.3", "ssl_prefer_server_ciphers": "on", "nginx_http_ssl_prefer_server_ciphers": "off", "nginx_stream_ssl_prefer_server_ciphers": "off", "nginx_events_worker_connections": "auto", "nginx_stream_ssl_dhparam": "ffdhe2048", "ssl_session_tickets": "on", "nginx_http_ssl_session_tickets": "on", "nginx_http_charset": "UTF-8", "ssl_session_timeout": "1d", "nginx_http_client_max_body_size": "0", "nginx_stream_ssl_session_timeout": "1d", "ssl_session_cache_size": "10m", "proxy_access_log": "/dev/stdout", "proxy_error_log": "/dev/stderr", "dns_resolver": {}, "proxy_stream_error_log": "logs/error.log", "admin_access_log": "/dev/stdout", "admin_error_log": "/dev/stderr", "dns_hostsfile": "/etc/hosts", "admin_gui_error_log": "logs/admin_gui_error.log", "status_access_log": "off", "status_error_log": "logs/status_error.log", "upstream_keepalive_max_requests": 10000, "nginx_stream_lua_ssl_protocols": "TLSv1.2 TLSv1.3", "lua_socket_pool_size": 256, "cluster_control_plane": "127.0.0.1:8005", "dns_error_ttl": 1, "status_ssl_cert_key_default": "/usr/local/kong/ssl/status-kong-default.key", "dns_not_found_ttl": 30, "nginx_http_keepalive_requests": "10000", "dns_stale_ttl": 3600, "cluster_data_plane_purge_delay": 1209600, "dns_cache_size": 10000, "port_maps": {}, "dns_order": [ "LAST", "SRV", "A", "CNAME" ], "admin_ssl_cert_key": "******", "dns_no_sync": false, "ssl_cert": [ "/usr/local/kong/ssl/kong-default.crt", "/usr/local/kong/ssl/kong-default-ecdsa.crt" ], "untrusted_lua_sandbox_requires": {}, "resolver_address": {}, "worker_events_max_payload": 65535, "cluster_rpc": false, "resolver_family": [ "A", "SRV" ], "opentelemetry_tracing_sampling_rate": 0.01, "nginx_admin_client_body_buffer_size": "10m", "trusted_ips": {}, "real_ip_header": "X-Real-IP", "resolver_stale_ttl": 3600, "admin_gui_csp_header": false, "resolver_lru_cache_size": 10000, "pg_host": "kong-database", "pg_port": 5432, "pg_password": "******", "pg_ssl": false, "pg_database": "kong", "pg_max_concurrent_queries": 0, "pg_semaphore_timeout": 60000, "tracing_instrumentations": [ "off" ], "tracing_sampling_rate": 0.01, "_debug_pg_ttl_cleanup_interval": 300, "db_resurrect_ttl": 30, "pg_ro_ssl": false, "pg_ro_ssl_verify": false, "pluginservers": {}, "cluster_mtls": "shared", "enabled_headers_upstream": { "X-Kong-Request-Id": true }, "enabled_headers": { "server_tokens": true, "X-Kong-Proxy-Latency": true, "X-Kong-Request-Id": true, "X-Kong-Response-Latency": true, "Via": true, "Server": true, "X-Kong-Upstream-Latency": true, "X-Kong-Upstream-Status": false, "latency_tokens": true, "X-Kong-Admin-Latency": true }, "nginx_http_directives": [ { "name": "charset", "value": "UTF-8" }, { "name": "client_body_buffer_size", "value": "8k" }, { "name": "client_max_body_size", "value": "0" }, { "name": "keepalive_requests", "value": "10000" }, { "name": "lua_regex_cache_max_entries", "value": "8192" }, { "name": "lua_regex_match_limit", "value": "100000" }, { "name": "lua_shared_dict", "value": "prometheus_metrics 5m" }, { "name": "ssl_dhparam", "value": "/usr/local/kong/ssl/ffdhe2048.pem" }, { "name": "ssl_prefer_server_ciphers", "value": "off" }, { "name": "ssl_protocols", "value": "TLSv1.2 TLSv1.3" }, { "name": "ssl_session_tickets", "value": "on" }, { "name": "ssl_session_timeout", "value": "1d" } ], "upstream_keepalive_pool_size": 512, "stream_listeners": {}, "vaults": [ "bundled" ], "ssl_protocols": "TLSv1.2 TLSv1.3", "admin_listeners": [ { "ipv6only=off": false, "so_keepalive=on": false, "bind": false, "so_keepalive=%w*:%w*:%d*": false, "listener": "0.0.0.0:8001", "port": 8001, "ip": "0.0.0.0", "so_keepalive=off": false, "ssl": false, "http2": false, "proxy_protocol": false, "deferred": false, "reuseport": false, "backlog=%d+": false, "ipv6only=on": false }, { "ipv6only=off": false, "so_keepalive=on": false, "bind": false, "so_keepalive=%w*:%w*:%d*": false, "listener": "0.0.0.0:8444 ssl", "port": 8444, "ip": "0.0.0.0", "so_keepalive=off": false, "ssl": true, "http2": false, "proxy_protocol": false, "deferred": false, "reuseport": false, "backlog=%d+": false, "ipv6only=on": false } ], "lua_package_path": "./?.lua;./?/init.lua;", "proxy_listen": [ "0.0.0.0:8000 reuseport backlog=16384", "0.0.0.0:8443 http2 ssl reuseport backlog=16384" ], "admin_gui_listeners": [ { "ipv6only=off": false, "so_keepalive=on": false, "bind": false, "so_keepalive=%w*:%w*:%d*": false, "listener": "0.0.0.0:8002", "port": 8002, "ip": "0.0.0.0", "so_keepalive=off": false, "ssl": false, "http2": false, "proxy_protocol": false, "deferred": false, "reuseport": false, "backlog=%d+": false, "ipv6only=on": false }, { "ipv6only=off": false, "so_keepalive=on": false, "bind": false, "so_keepalive=%w*:%w*:%d*": false, "listener": "0.0.0.0:8445 ssl", "port": 8445, "ip": "0.0.0.0", "so_keepalive=off": false, "ssl": true, "http2": false, "proxy_protocol": false, "deferred": false, "reuseport": false, "backlog=%d+": false, "ipv6only=on": false } ], "stream_listen": [ "off" ], "stream_proxy_ssl_enabled": false, "admin_listen": [ "0.0.0.0:8001", "0.0.0.0:8444 ssl" ], "admin_ssl_enabled": true, "admin_gui_listen": [ "0.0.0.0:8002", "0.0.0.0:8445 ssl" ], "admin_gui_ssl_enabled": true, "prefix": "/usr/local/kong", "status_ssl_enabled": false, "cluster_listen": [ "0.0.0.0:8005" ], "proxy_ssl_enabled": true, "proxy_listeners": [ { "ipv6only=off": false, "so_keepalive=on": false, "bind": false, "so_keepalive=%w*:%w*:%d*": false, "listener": "0.0.0.0:8000 reuseport backlog=16384", "backlog=16384": true, "port": 8000, "ip": "0.0.0.0", "so_keepalive=off": false, "http2": false, "proxy_protocol": false, "deferred": false, "reuseport": true, "ssl": false, "ipv6only=on": false }, { "ipv6only=off": false, "so_keepalive=on": false, "bind": false, "so_keepalive=%w*:%w*:%d*": false, "listener": "0.0.0.0:8443 ssl reuseport backlog=16384", "backlog=16384": true, "port": 8443, "ip": "0.0.0.0", "so_keepalive=off": false, "http2": true, "proxy_protocol": false, "deferred": false, "reuseport": true, "ssl": true, "ipv6only=on": false } ], "loaded_plugins": { "request-size-limiting": true, "rate-limiting": true, "response-ratelimiting": true, "syslog": true, "loggly": true, "datadog": true, "ldap-auth": true, "statsd": true, "bot-detection": true, "aws-lambda": true, "request-termination": true, "prometheus": true, "proxy-cache": true, "session": true, "acme": true, "grpc-gateway": true, "grpc-web": true, "pre-function": true, "post-function": true, "azure-functions": true, "zipkin": true, "opentelemetry": true, "ai-proxy": true, "ai-prompt-decorator": true, "ai-prompt-template": true, "ai-prompt-guard": true, "ai-request-transformer": true, "ai-response-transformer": true, "standard-webhooks": true, "redirect": true, "jwt": true, "acl": true, "correlation-id": true, "cors": true, "oauth2": true, "tcp-log": true, "udp-log": true, "file-log": true, "http-log": true, "key-auth": true, "hmac-auth": true, "basic-auth": true, "ip-restriction": true, "request-transformer": true, "response-transformer": true }, "anonymous_reports": true, "mem_cache_size": "128m", "nginx_wasm_main_shm_kv_directives": {}, "headers_upstream": [ "x-kong-request-id" ], "nginx_wasm_v8_directives": {}, "nginx_wasm_wasmtime_directives": {}, "nginx_sproxy_directives": {}, "nginx_stream_directives": [ { "name": "lua_shared_dict", "value": "stream_prometheus_metrics 5m" }, { "name": "ssl_dhparam", "value": "/usr/local/kong/ssl/ffdhe2048.pem" }, { "name": "ssl_prefer_server_ciphers", "value": "off" }, { "name": "ssl_protocols", "value": "TLSv1.2 TLSv1.3" }, { "name": "ssl_session_tickets", "value": "on" }, { "name": "ssl_session_timeout", "value": "1d" } ], "nginx_admin_directives": [ { "name": "client_body_buffer_size", "value": "10m" }, { "name": "client_max_body_size", "value": "10m" } ], "lua_ssl_verify_depth": 1, "nginx_location_directives": {}, "ssl_dhparam": "ffdhe2048", "nginx_http_lua_regex_cache_max_entries": "8192", "admin_gui_url": [ "http://localhost:8002" ], "admin_gui_origin": [ "http://localhost:8002" ], "cluster_use_proxy": false, "nginx_events_directives": [ { "name": "multi_accept", "value": "on" }, { "name": "worker_connections", "value": "auto" } ], "nginx_main_directives": [ { "name": "daemon", "value": "off" }, { "name": "user", "value": "kong kong" }, { "name": "worker_processes", "value": "auto" }, { "name": "worker_rlimit_nofile", "value": "auto" } ], "admin_gui_ssl_cert_default_ecdsa": "/usr/local/kong/ssl/admin-gui-kong-default-ecdsa.crt", "admin_gui_ssl_cert_default": "/usr/local/kong/ssl/admin-gui-kong-default.crt", "admin_ssl_cert_key_default_ecdsa": "/usr/local/kong/ssl/admin-kong-default-ecdsa.key", "pluginserver_names": {}, "admin_ssl_cert_default_ecdsa": "/usr/local/kong/ssl/admin-kong-default-ecdsa.crt", "admin_ssl_cert_key_default": "/usr/local/kong/ssl/admin-kong-default.key", "worker_consistency": "eventual", "admin_ssl_cert_default": "/usr/local/kong/ssl/admin-kong-default.crt", "client_ssl_cert_key_default": "/usr/local/kong/ssl/kong-default.key", "client_ssl_cert_default": "/usr/local/kong/ssl/kong-default.crt", "nginx_pid": "/usr/local/kong/pids/nginx.pid", "ssl_cert_key_default_ecdsa": "/usr/local/kong/ssl/kong-default-ecdsa.key", "ssl_cert_default_ecdsa": "/usr/local/kong/ssl/kong-default-ecdsa.crt", "admin_gui_ssl_cert_key_default": "/usr/local/kong/ssl/admin-gui-kong-default.key", "ssl_cert_key_default": "/usr/local/kong/ssl/kong-default.key", "kong_env": "/usr/local/kong/.kong_env", "ssl_cert_default": "/usr/local/kong/ssl/kong-default.crt", "status_ssl_cert_default_ecdsa": "/usr/local/kong/ssl/status-kong-default-ecdsa.crt", "status_ssl_cert_key_default_ecdsa": "/usr/local/kong/ssl/status-kong-default-ecdsa.key", "ssl_cert_key": "******", "status_ssl_cert_default": "/usr/local/kong/ssl/status-kong-default.crt", "admin_gui_ssl_cert_key_default_ecdsa": "/usr/local/kong/ssl/admin-gui-kong-default-ecdsa.key", "admin_gui_ssl_cert": [ "/usr/local/kong/ssl/admin-gui-kong-default.crt", "/usr/local/kong/ssl/admin-gui-kong-default-ecdsa.crt" ], "status_ssl_cert_key": "******", "nginx_daemon": "off", "opentelemetry_tracing": [ "off" ], "stream_config_sock": "sc", "role": "traditional", "stream_rpc_sock": "rp", "stream_worker_events_sock": "sw", "database": "postgres", "worker_events_sock": "we", "socket_path": "/usr/local/kong/sockets", "loaded_vaults": { "env": true }, "new_dns_client": false, "nginx_main_worker_rlimit_nofile": "auto", "nginx_events_multi_accept": "on", "nginx_stream_ssl_session_tickets": "on", "log_level": "notice", "nginx_http_lua_ssl_protocols": "TLSv1.2 TLSv1.3", "wasm": false, "router_flavor": "traditional_compatible", "nginx_admin_client_max_body_size": "10m", "nginx_worker_processes": "auto", "cluster_ocsp": "off", "cluster_dp_labels": {}, "nginx_proxy_real_ip_header": "X-Real-IP", "status_ssl_cert": {}, "pg_user": "kong", "proxy_server_ssl_verify": true, "untrusted_lua_sandbox_environment": {}, "client_body_buffer_size": "8k", "nginx_proxy_real_ip_recursive": "off", "admin_gui_ssl_cert_key": "******", "admin_ssl_cert": [ "/usr/local/kong/ssl/admin-kong-default.crt", "/usr/local/kong/ssl/admin-kong-default-ecdsa.crt" ], "client_ssl": false, "error_default_type": "text/plain", "admin_gui_access_log": "logs/admin_gui_access.log", "status_listen": [ "127.0.0.1:8007 reuseport backlog=16384" ], "cluster_rpc_sync": false, "cluster_max_payload": 16777216, "nginx_http_client_body_buffer_size": "8k", "lmdb_map_size": "2048m", "admin_gui_path": "/", "resolver_hosts_file": "/etc/hosts", "db_update_frequency": 5, "db_update_propagation": 0, "db_cache_ttl": 0, "proxy_stream_access_log": "logs/access.log basic", "nginx_http_ssl_dhparam": "ffdhe2048", "real_ip_recursive": "off", "nginx_main_worker_processes": "auto", "nginx_http_ssl_session_timeout": "1d", "status_listeners": [ { "ipv6only=off": false, "so_keepalive=on": false, "bind": false, "so_keepalive=%w*:%w*:%d*": false, "listener": "127.0.0.1:8007 reuseport backlog=16384", "backlog=16384": true, "port": 8007, "ip": "127.0.0.1", "so_keepalive=off": false, "http2": false, "proxy_protocol": false, "deferred": false, "reuseport": true, "ssl": false, "ipv6only=on": false } ], "nginx_main_daemon": "off", "nginx_http_lua_regex_match_limit": "100000", "upstream_keepalive_idle_timeout": 60, "cluster_listeners": [ { "ipv6only=off": false, "so_keepalive=on": false, "bind": false, "so_keepalive=%w*:%w*:%d*": false, "listener": "0.0.0.0:8005", "port": 8005, "ip": "0.0.0.0", "so_keepalive=off": false, "ssl": false, "http2": false, "proxy_protocol": false, "deferred": false, "reuseport": false, "backlog=%d+": false, "ipv6only=on": false } ], "host_ports": {}, "resolver_mem_cache_size": "5m", "cluster_cjson": false, "kic": false, "pg_ssl_verify": false, "dedicated_config_processing": true, "pg_timeout": 5000, "request_debug": true, "worker_state_update_frequency": 5, "stream_tls_passthrough_sock": "sp", "stream_tls_terminate_sock": "st", "cluster_proxy_ssl_terminator_sock": "cp", "lua_ssl_trusted_certificate": [ "/etc/ssl/certs/ca-certificates.crt" ], "lua_ssl_trusted_certificate_combined": "/usr/local/kong/.ca_combined", "allow_debug_header": false, "lua_ssl_protocols": "TLSv1.2 TLSv1.3", "nginx_upstream_directives": {}, "untrusted_lua": "sandbox", "nginx_proxy_directives": [ { "name": "real_ip_header", "value": "X-Real-IP" }, { "name": "real_ip_recursive", "value": "off" } ], "lua_max_req_headers": 100, "nginx_main_user": "kong kong", "lmdb_environment_path": "dbless.lmdb", "nginx_status_directives": {}, "resolver_error_ttl": 1, "nginx_user": "kong kong" }, "pids": { "master": 1, "workers": [ 1413, 1414, 1415, 1416, 1417, 1418, 1419, 1420 ] }, "timers": { "pending": 1, "running": 257 }, "tagline": "Welcome to kong" }

Configure test Service and Route in Access Kong Manager (GUI):

Open web browser and go to http://localhost:8002. You should see the Kong Manager main page:

image-20250829-162716.png

Go to Gateway Service and create a test Service:

image-20250829-162852.png

Configure a new Route associated with test-api Service:

image-20250829-163111.png

Verify Kong routes calls to Wiremock:

curl -X GET "http://localhost:8000/test/api/data" | jq .

The output should be:

{ "message": "Hello from WireMock!" }

References

  1. Kong build README.md

  2. "Build and Install from source" section from DEVELOPER.md

  3. Build a custom Docker image

  4. Install Kong Gateway using Docker Compose