├── kong.deb ├── kong.rpm ├── kong.apk.tar.gz ├── ubuntu ├── kong.deb ├── docker-entrypoint.sh └── Dockerfile ├── customize ├── empty_file ├── example.sh ├── list_plugins.sh ├── Dockerfile ├── readme.md └── packer.lua ├── compose ├── POSTGRES_PASSWORD ├── config │ └── kong.yaml ├── Makefile ├── README.md ├── docker-compose.yml └── docker-compose.yml-e ├── tests ├── bad_file.conf ├── rockserver │ └── kong-plugin-myplugin-0.1.0-1.all.rock ├── README.md ├── 04-executables.test.sh ├── 03-cis-sec.test.sh ├── 01-image.test.sh └── test.sh ├── kong-build-tools ├── .dockerignore ├── test │ ├── kong_license.json │ ├── nginx.conf │ ├── run_tests.sh │ ├── docker-entrypoint.sh │ ├── Dockerfile.test │ ├── build_container.sh │ ├── util.sh │ └── kong-tests-compose.yaml ├── .rpmmacros ├── output │ └── .gitignore ├── .gitignore ├── .github │ ├── dependabot.yml │ └── workflows │ │ └── release.yaml ├── .gitmodules ├── .releaserc └── .ci │ └── setup_ci.sh ├── .gitattributes ├── hadolint.yaml ├── .gitignore ├── .github ├── dependabot.yml └── workflows │ ├── auto-assignee.yml │ └── version2_test.yml ├── .editorconfig ├── Dockerfile.deb ├── docker-entrypoint.sh ├── README.md ├── Makefile ├── Dockerfile.rpm ├── update.sh ├── submit.sh └── LICENSE /kong.deb: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kong.rpm: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kong.apk.tar.gz: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ubuntu/kong.deb: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /customize/empty_file: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /compose/POSTGRES_PASSWORD: -------------------------------------------------------------------------------- 1 | kong -------------------------------------------------------------------------------- /tests/bad_file.conf: -------------------------------------------------------------------------------- 1 | this is a bad conf file 2 | -------------------------------------------------------------------------------- /kong-build-tools/.dockerignore: -------------------------------------------------------------------------------- 1 | kong/servroot* 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | Dockerfile.* linguist-language=Dockerfile 2 | -------------------------------------------------------------------------------- /kong-build-tools/test/kong_license.json: -------------------------------------------------------------------------------- 1 | kong_license.private -------------------------------------------------------------------------------- /hadolint.yaml: -------------------------------------------------------------------------------- 1 | ignored: 2 | - DL3008 3 | - DL3027 4 | - SC2046 5 | - DL4006 6 | -------------------------------------------------------------------------------- /kong-build-tools/.rpmmacros: -------------------------------------------------------------------------------- 1 | %_signature gpg 2 | %_gpg_name Kong Inc -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .che 3 | kong 4 | *.bak 5 | submit 6 | **/*.deb 7 | **/*.rpm 8 | **/*.apk 9 | -------------------------------------------------------------------------------- /compose/config/kong.yaml: -------------------------------------------------------------------------------- 1 | # a very minimal declarative config file 2 | _format_version: "2.1" 3 | _transform: true 4 | -------------------------------------------------------------------------------- /kong-build-tools/output/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | * 3 | # Except this file 4 | !.gitignore 5 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: docker 4 | directory: / 5 | schedule: 6 | interval: daily 7 | -------------------------------------------------------------------------------- /tests/rockserver/kong-plugin-myplugin-0.1.0-1.all.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kong/docker-kong/HEAD/tests/rockserver/kong-plugin-myplugin-0.1.0-1.all.rock -------------------------------------------------------------------------------- /kong-build-tools/.gitignore: -------------------------------------------------------------------------------- 1 | kong 2 | docker-kong 3 | id_rsa.private 4 | kong_license.private 5 | *.deb 6 | *.rpm 7 | openresty-build-tools/build 8 | github-token 9 | -------------------------------------------------------------------------------- /tests/README.md: -------------------------------------------------------------------------------- 1 | To create a new testfile run: 2 | 3 | ```shell 4 | ./test.sh --create mytestfile "Docker-Kong test suite" 5 | ``` 6 | 7 | instructions will be in the generated file. 8 | -------------------------------------------------------------------------------- /compose/Makefile: -------------------------------------------------------------------------------- 1 | kong-postgres: 2 | COMPOSE_PROFILES=database KONG_DATABASE=postgres docker compose up -d 3 | 4 | kong-dbless: 5 | docker compose up -d 6 | 7 | clean: 8 | docker compose kill 9 | docker compose rm -f 10 | -------------------------------------------------------------------------------- /kong-build-tools/.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "docker" # See documentation for possible values 4 | directory: "/dockerfiles" # Location of package manifests 5 | schedule: 6 | interval: "daily" 7 | -------------------------------------------------------------------------------- /kong-build-tools/.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lua-kong-nginx-module"] 2 | path = lua-kong-nginx-module 3 | url = git@github.com:Kong/lua-kong-nginx-module.git 4 | [submodule "lua-resty-lmdb"] 5 | path = lua-resty-lmdb 6 | url = git@github.com:Kong/lua-resty-lmdb.git 7 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | trim_trailing_whitespace = true 7 | charset = utf-8 8 | 9 | [*.sh] 10 | indent_style = space 11 | indent_size = 2 12 | 13 | [Dockerfile] 14 | indent_style = space 15 | indent_size = 2 16 | 17 | [Makefile] 18 | indent_style = tab 19 | -------------------------------------------------------------------------------- /.github/workflows/auto-assignee.yml: -------------------------------------------------------------------------------- 1 | name: Add assignee to PRs 2 | on: 3 | pull_request: 4 | types: [ opened, reopened ] 5 | permissions: 6 | pull-requests: write 7 | jobs: 8 | assign-author: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: toshimaru/auto-author-assign@2daaeb2988aef24bf37e636fe733f365c046aba0 12 | 13 | -------------------------------------------------------------------------------- /kong-build-tools/.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Release 3 | 4 | on: # yamllint disable-line rule:truthy 5 | pull_request: 6 | push: 7 | branches: 8 | - master 9 | 10 | jobs: 11 | release: 12 | name: Create Release 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v3 17 | - name: Release 18 | id: release 19 | uses: ahmadnassri/action-semantic-release@v2.0.1 20 | env: 21 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 22 | -------------------------------------------------------------------------------- /.github/workflows/version2_test.yml: -------------------------------------------------------------------------------- 1 | name: Build & Test Version 2 2 | on: [push, pull_request] 3 | 4 | jobs: 5 | test: 6 | name: Build & Test Version 2 7 | runs-on: ubuntu-latest 8 | timeout-minutes: 30 9 | 10 | strategy: 11 | matrix: 12 | package: [deb, rpm] 13 | 14 | env: 15 | BASE: ${{ matrix.package }} 16 | PACKAGE: ${{ matrix.package }} 17 | KONG_DOCKER_TAG: kong-${{ matrix.package }} 18 | 19 | steps: 20 | - name: Checkout 21 | uses: actions/checkout@v2 22 | - name: Build 23 | run: | 24 | make build_v2 25 | - name: Test 26 | shell: 'script -q -e -c "bash {0}"' 27 | run: | 28 | make test 29 | -------------------------------------------------------------------------------- /kong-build-tools/test/nginx.conf: -------------------------------------------------------------------------------- 1 | 2 | #user nobody; 3 | worker_processes 1; 4 | 5 | #error_log logs/error.log; 6 | #error_log logs/error.log notice; 7 | #error_log logs/error.log info; 8 | 9 | #pid logs/nginx.pid; 10 | 11 | 12 | events { 13 | worker_connections 1024; 14 | } 15 | 16 | 17 | http { 18 | include mime.types; 19 | default_type application/octet-stream; 20 | 21 | #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 22 | # '$status $body_bytes_sent "$http_referer" ' 23 | # '"$http_user_agent" "$http_x_forwarded_for"'; 24 | 25 | #access_log logs/access.log main; 26 | 27 | sendfile on; 28 | #tcp_nopush on; 29 | 30 | #keepalive_timeout 0; 31 | keepalive_timeout 65; 32 | 33 | #gzip on; 34 | 35 | include /etc/nginx/conf.d/*.conf; 36 | } -------------------------------------------------------------------------------- /kong-build-tools/test/run_tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source test/util.sh 4 | 5 | if $VERBOSE; then 6 | set -x 7 | fi 8 | 9 | if [[ "$RESTY_IMAGE_BASE" == "src" ]]; then 10 | exit 0 11 | fi 12 | 13 | if [[ "$SKIP_TESTS" == "true" ]]; then 14 | exit 0 15 | fi 16 | 17 | # used to skip systemd-based tests that require a /sys/fs/cgroup mount in 18 | # 01-package/run.sh which doesn't exists on Mac OS 19 | if uname -a | grep -qs -i darwin; then 20 | DARWIN=1 21 | fi 22 | 23 | USE_TTY="-t" 24 | test -t 1 && USE_TTY="-it" 25 | 26 | for dir in test/tests/*; do 27 | msg_test "Running '$dir' tests..." 28 | msg_test "======================================================================" 29 | 30 | pushd $dir 31 | test -f up.sh && source ./up.sh 32 | 33 | set -e 34 | test -f run.sh && source ./run.sh 35 | set +e 36 | 37 | test -f down.sh && source ./down.sh 38 | popd 39 | 40 | msg_green "=================================OK==================================" 41 | done 42 | -------------------------------------------------------------------------------- /kong-build-tools/test/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | export KONG_NGINX_DAEMON=off 5 | 6 | has_transparent() { 7 | echo "$1" | grep -E "[^\s,]+\s+transparent\b" >/dev/null 8 | } 9 | 10 | if [[ "$1" == "kong" ]]; then 11 | PREFIX=${KONG_PREFIX:=/usr/local/kong} 12 | 13 | if [[ "$2" == "docker-start" ]]; then 14 | shift 2 15 | kong prepare -p "$PREFIX" "$@" 16 | 17 | chmod o+w /proc/self/fd/1 18 | chmod o+w /proc/self/fd/2 19 | 20 | if [ "$(id -u)" != "0" ]; then 21 | exec /usr/local/openresty/nginx/sbin/nginx \ 22 | -p "$PREFIX" \ 23 | -c nginx.conf 24 | else 25 | if [ ! -z ${SET_CAP_NET_RAW} ] \ 26 | || has_transparent "$KONG_STREAM_LISTEN" \ 27 | || has_transparent "$KONG_PROXY_LISTEN" \ 28 | || has_transparent "$KONG_ADMIN_LISTEN"; 29 | then 30 | setcap cap_net_raw=+ep /usr/local/openresty/nginx/sbin/nginx 31 | fi 32 | chown -R kong:0 /usr/local/kong 33 | exec su-exec kong /usr/local/openresty/nginx/sbin/nginx \ 34 | -p "$PREFIX" \ 35 | -c nginx.conf 36 | fi 37 | fi 38 | fi 39 | 40 | exec "$@" 41 | -------------------------------------------------------------------------------- /customize/example.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # pick a plugin repo, and pack the rock, and its dependencies (clear first) 4 | # because we use a local LuaRocks repo, we also need the dependencies in there 5 | # since the public one will not be available 6 | pushd ~/code/kong-plugin-enterprise-request-validator 7 | luarocks remove kong-plugin-request-validator --force 8 | luarocks remove net-url --force 9 | luarocks remove lua-resty-ljsonschema --force 10 | luarocks make 11 | luarocks pack kong-plugin-request-validator 12 | luarocks pack net-url 13 | luarocks pack lua-resty-ljsonschema 14 | popd 15 | 16 | # create a LuaRocks repo, and copy the rocks in there. This directory will be 17 | # used as the base LuaRocks server we're installing from. These, and only these, 18 | # rocks can be installed. 19 | rm -rf ./rocksdir 20 | mkdir ./rocksdir 21 | mv ~/code/kong-plugin-enterprise-request-validator/*.rock ./rocksdir/ 22 | 23 | #build the custom image 24 | docker build \ 25 | --build-arg "KONG_LICENSE_DATA=$KONG_LICENSE_DATA" \ 26 | --build-arg KONG_BASE="kong-ee" \ 27 | --build-arg PLUGINS="kong-plugin-request-validator" \ 28 | --build-arg ROCKS_DIR="./rocksdir" \ 29 | --tag "your_new_image" . 30 | 31 | 32 | -------------------------------------------------------------------------------- /customize/list_plugins.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | KONG_IMAGE=$1 4 | if [ "$1" == "" ]; then 5 | KONG_IMAGE="kong:latest" 6 | >&2 echo "No image passed on command-line, defaulting to \"$KONG_IMAGE\"" 7 | fi 8 | >&2 echo "Listing plugins for Kong image \"$KONG_IMAGE\"" 9 | 10 | # start a local Kong 11 | CID=$(docker run -it --rm -d \ 12 | -e KONG_DATABASE=off \ 13 | -e KONG_LICENSE_DATA \ 14 | -e KONG_ADMIN_LISTEN=0.0.0.0:8001 \ 15 | -p 8001:8001 \ 16 | $KONG_IMAGE kong start) 17 | >&2 echo "Started introspection container id \"$CID\"" 18 | 19 | # wait for instance to be available and responding 20 | x=1 21 | PLUGIN_DATA=$(curl -s http://localhost:8001/) 22 | while [ ! $? -eq 0 ]; do 23 | sleep 0.1 24 | x=$(( x + 1 )) 25 | 26 | if [ $x -gt 50 ]; then 27 | >&2 echo "ERROR timeout while waiting for Kong instance to become available" 28 | docker kill "$CID" > /dev/null 29 | >&2 echo "Destroyed introspection container id \"$CID\"" 30 | exit 1 31 | fi 32 | 33 | PLUGIN_DATA=$(curl -s http://localhost:8001/) 34 | done 35 | 36 | # kill the local Kong instance 37 | docker kill "$CID" > /dev/null 38 | >&2 echo "Destroyed introspection container id \"$CID\"" 39 | 40 | # send plugin data to stdout 41 | echo "$PLUGIN_DATA" | jq .plugins.available_on_server 42 | -------------------------------------------------------------------------------- /customize/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG KONG_BASE=kong:latest 2 | 3 | FROM ${KONG_BASE} AS build 4 | 5 | ARG PLUGINS 6 | ENV INJECTED_PLUGINS=${PLUGINS} 7 | 8 | ARG TEMPLATE=empty_file 9 | ENV TEMPLATE=${TEMPLATE} 10 | 11 | ARG ROCKS_DIR=empty_file 12 | ENV ROCKS_DIR=${ROCKS_DIR} 13 | 14 | ARG KONG_LICENSE_DATA 15 | ENV KONG_LICENSE_DATA=${KONG_LICENSE_DATA} 16 | 17 | COPY $TEMPLATE /custom_nginx.conf 18 | COPY $ROCKS_DIR /rocks-server 19 | COPY packer.lua /packer.lua 20 | 21 | USER root 22 | 23 | RUN /usr/local/openresty/luajit/bin/luajit /packer.lua -- "$INJECTED_PLUGINS" 24 | 25 | FROM ${KONG_BASE} 26 | 27 | USER root 28 | 29 | # Workarounds used: 30 | # 1 - the "custom_nginx.conf*" wildcard ensures it doesn't fail if it doesn't exist 31 | # 2 - "RUN true", see https://stackoverflow.com/questions/51115856/docker-failed-to-export-image-failed-to-create-image-failed-to-get-layer/62409523#62409523 32 | 33 | # replace the entrypoint, add the custom template if it exists 34 | COPY --from=build /docker-entrypoint.sh /old-entrypoint.sh /custom_nginx.conf* / 35 | RUN true 36 | 37 | # add the Lua files (.lua) 38 | COPY --from=build /usr/local/share/lua/5.1 /usr/local/share/lua/5.1 39 | RUN true 40 | 41 | # add the compiled libraries (.so) 42 | COPY --from=build /usr/local/lib/lua/5.1 /usr/local/lib/lua/5.1 43 | RUN true 44 | 45 | # add the Luarocks manifest 46 | COPY --from=build /usr/local/lib/luarocks/rocks-5.1 /usr/local/lib/luarocks/rocks-5.1 47 | RUN true 48 | 49 | # add any Lua commandline scripts 50 | # TODO: should commandline scripts be copied at all? 51 | #COPY --from=build /usr/local/bin /usr/local/bin 52 | 53 | 54 | HEALTHCHECK --interval=60s --timeout=10s --retries=10 CMD kong-health 55 | 56 | USER kong 57 | -------------------------------------------------------------------------------- /kong-build-tools/.releaserc: -------------------------------------------------------------------------------- 1 | { 2 | "branches": ["+([0-9])?(.{+([0-9]),x}).x", "master", "next"], 3 | "tagFormat": "${version}", 4 | "repositoryUrl": "https://github.com/Kong/kong-build-tools.git", 5 | "plugins": [ 6 | [ 7 | "@semantic-release/commit-analyzer", 8 | { 9 | "preset": "conventionalcommits", 10 | "releaseRules": [ 11 | { "breaking": true, "release": "major" }, 12 | { "revert": true, "release": "patch" }, 13 | { "type": "build", "release": "patch" }, 14 | { "type": "docs", "release": "patch" }, 15 | { "type": "feat", "release": "minor" }, 16 | { "type": "fix", "release": "patch" }, 17 | { "type": "perf", "release": "patch" }, 18 | { "type": "refactor", "release": "patch" }, 19 | { "type": "chore", "release": "patch" } 20 | ] 21 | } 22 | ], 23 | [ 24 | "@semantic-release/release-notes-generator", 25 | { 26 | "preset": "conventionalcommits", 27 | "presetConfig": { 28 | "types": [ 29 | { "type": "build", "section": "Build", "hidden": false }, 30 | { "type": "chore", "section": "Chores", "hidden": false }, 31 | { "type": "ci", "section": "CI/CD", "hidden": false }, 32 | { "type": "docs", "section": "Docs", "hidden": false }, 33 | { "type": "feat", "section": "Features", "hidden": false }, 34 | { "type": "fix", "section": "Bug Fixes", "hidden": false }, 35 | { "type": "perf", "section": "Performance", "hidden": false }, 36 | { "type": "refactor", "section": "Refactor", "hidden": false }, 37 | { "type": "style", "section": "Code Style", "hidden": false }, 38 | { "type": "test", "section": "Tests", "hidden": false } 39 | ] 40 | } 41 | } 42 | ], 43 | "@semantic-release/github" 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /tests/04-executables.test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | function run_test { 4 | # the suite name below will only be used when rtunning this file directly, when 5 | # running through "test.sh" it must be provided using the "--suite" option. 6 | tinitialize "Docker-Kong test suite" "${BASH_SOURCE[0]}" 7 | 8 | tchapter "makes executables available" 9 | 10 | ttest "resty is in the system path" 11 | docker run -ti --rm "kong-$BASE" resty -V 12 | if [ $? -eq 0 ]; then 13 | tsuccess 14 | else 15 | tmessage "resty wasn't found in the system path" 16 | tfailure 17 | fi 18 | 19 | ttest "luajit is in the system path" 20 | docker run -ti --rm "kong-$BASE" luajit -v 21 | if [ $? -eq 0 ]; then 22 | tsuccess 23 | else 24 | tmessage "luajit wasn't found in the system path" 25 | tfailure 26 | fi 27 | 28 | ttest "lua is in the system path" 29 | docker run -ti --rm "kong-$BASE" lua -v 30 | if [ $? -eq 0 ]; then 31 | tsuccess 32 | else 33 | tmessage "lua wasn't found in the system path" 34 | tfailure 35 | fi 36 | 37 | ttest "nginx is in the system path" 38 | docker run -ti --rm "kong-$BASE" nginx -v 39 | if [ $? -eq 0 ]; then 40 | tsuccess 41 | else 42 | tmessage "nginx wasn't found in the system path" 43 | tfailure 44 | fi 45 | 46 | ttest "luarocks is in the system path" 47 | docker run -ti --rm "kong-$BASE" luarocks --version 48 | if [ $? -eq 0 ]; then 49 | tsuccess 50 | else 51 | tmessage "luarocks wasn't found in the system path" 52 | tfailure 53 | fi 54 | 55 | tfinish 56 | } 57 | 58 | # No need to modify anything below this comment 59 | 60 | # shellcheck disable=SC1090 # do not follow source 61 | [[ "$T_PROJECT_NAME" == "" ]] && set -e && if [[ -f "${1:-$(dirname "$(realpath "$0")")/test.sh}" ]]; then source "${1:-$(dirname "$(realpath "$0")")/test.sh}"; else source "${1:-$(dirname "$(realpath "$0")")/run.sh}"; fi && set +e 62 | run_test 63 | -------------------------------------------------------------------------------- /Dockerfile.deb: -------------------------------------------------------------------------------- 1 | # When you update this file substantially, please update build_your_own_images.md as well. 2 | FROM debian:bookworm-20250520-slim 3 | 4 | LABEL maintainer="Kong Docker Maintainers (@team-gateway-bot)" 5 | ARG KONG_VERSION=3.9.1 6 | ENV KONG_VERSION $KONG_VERSION 7 | 8 | ARG KONG_SHA256="34857a1b61e3c4b64b1e0529d8582a49ec19bc36f5b787bb63b41874e53c156a" 9 | 10 | ARG KONG_PREFIX=/usr/local/kong 11 | ENV KONG_PREFIX $KONG_PREFIX 12 | 13 | ARG ASSET=remote 14 | ARG EE_PORTS 15 | 16 | COPY kong.deb /tmp/kong.deb 17 | 18 | RUN set -ex; \ 19 | apt-get update; \ 20 | apt-get install -y curl; \ 21 | if [ "$ASSET" = "remote" ] ; then \ 22 | CODENAME=$(cat /etc/os-release | grep VERSION_CODENAME | cut -d = -f 2) \ 23 | && KONG_REPO=$(echo ${KONG_VERSION%.*} | sed 's/\.//') \ 24 | && DOWNLOAD_URL="https://packages.konghq.com/public/gateway-$KONG_REPO/deb/debian/pool/$CODENAME/main/k/ko/kong_$KONG_VERSION/kong_${KONG_VERSION}_amd64.deb" \ 25 | && curl -fL $DOWNLOAD_URL -o /tmp/kong.deb \ 26 | && echo "$KONG_SHA256 /tmp/kong.deb" | sha256sum -c -; \ 27 | fi \ 28 | && apt-get update \ 29 | && apt-get install --yes /tmp/kong.deb \ 30 | && rm -rf /var/lib/apt/lists/* \ 31 | && rm -rf /tmp/kong.deb \ 32 | && chown kong:0 /usr/local/bin/kong \ 33 | && chown -R kong:0 ${KONG_PREFIX} \ 34 | && ln -sf /usr/local/openresty/bin/resty /usr/local/bin/resty \ 35 | && ln -sf /usr/local/openresty/luajit/bin/luajit /usr/local/bin/luajit \ 36 | && ln -sf /usr/local/openresty/luajit/bin/luajit /usr/local/bin/lua \ 37 | && ln -sf /usr/local/openresty/nginx/sbin/nginx /usr/local/bin/nginx \ 38 | && kong version \ 39 | && apt-get purge curl -y 40 | 41 | COPY docker-entrypoint.sh /docker-entrypoint.sh 42 | 43 | USER kong 44 | 45 | ENTRYPOINT ["/docker-entrypoint.sh"] 46 | 47 | EXPOSE 8000 8443 8001 8444 $EE_PORTS 48 | 49 | STOPSIGNAL SIGQUIT 50 | 51 | HEALTHCHECK --interval=60s --timeout=10s --retries=10 CMD kong-health 52 | 53 | CMD ["kong", "docker-start"] 54 | -------------------------------------------------------------------------------- /kong-build-tools/.ci/setup_ci.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This script configures CI systems such that they're capable of building our ARM64 assets 4 | 5 | set -x 6 | 7 | if [ "$RESTY_IMAGE_TAG" != "bionic" ] && [ "$RESTY_IMAGE_TAG" != "18.04" ] && [ "$RESTY_IMAGE_BASE" != "alpine" ]; then 8 | exit 0 9 | fi 10 | 11 | if uname -a | grep -qs -i darwin; then 12 | exit 0 13 | fi 14 | 15 | sudo apt-get install -y \ 16 | qemu \ 17 | binfmt-support \ 18 | qemu-user-static 19 | 20 | docker version 21 | RESULT=$? 22 | if [ "$RESULT" != "0" ]; then 23 | curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - 24 | sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) test" 25 | sudo apt-get update 26 | sudo apt-get -y -o Dpkg::Options::="--force-confnew" install containerd.io docker-ce 27 | fi 28 | 29 | if test -d /etc/docker; then 30 | echo '{"experimental":true}' | sudo tee /etc/docker/daemon.json 31 | fi 32 | 33 | docker buildx version 34 | RESULT=$? 35 | if [ "$RESULT" != "0" ]; then 36 | curl -fsSLo buildx https://github.com/docker/buildx/releases/download/v0.8.2/buildx-v0.8.2.linux-amd64 37 | mkdir -p ~/.docker/cli-plugins/ 38 | chmod +x buildx 39 | mv buildx ~/.docker/cli-plugins/docker-buildx 40 | sudo service docker restart 41 | fi 42 | 43 | if ! [ -x "$(command -v docker-machine)" ]; then 44 | curl -L https://github.com/docker/machine/releases/download/v0.16.2/docker-machine-$(uname -s)-$(uname -m) >docker-machine 45 | sudo install docker-machine /usr/local/bin/docker-machine 46 | fi 47 | 48 | set -e 49 | echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin || true 50 | echo "$REDHAT_PASSWORD" | docker login -u "$REDHAT_USERNAME" registry.access.redhat.com --password-stdin || true 51 | docker-machine version 52 | docker version 53 | docker buildx version 54 | 55 | export BUILDX=true 56 | 57 | command -v ssh-agent >/dev/null || ( sudo apt-get update -y && sudo apt-get install openssh-client -y ) 58 | eval $(ssh-agent -s) 59 | -------------------------------------------------------------------------------- /kong-build-tools/test/Dockerfile.test: -------------------------------------------------------------------------------- 1 | ARG RESTY_IMAGE_BASE="ubuntu" 2 | ARG RESTY_IMAGE_TAG="bionic" 3 | ARG DOCKER_KONG_SUFFIX 4 | ARG DOCKER_OPENRESTY_SUFFIX 5 | ARG DOCKER_REPOSITORY 6 | 7 | FROM ${DOCKER_REPOSITORY}:test-${DOCKER_OPENRESTY_SUFFIX} 8 | 9 | ENV PATH=$PATH:/kong/bin:/usr/local/openresty/bin/:/usr/local/kong/bin/:/usr/local/openresty/nginx/sbin/ 10 | ENV LUA_PATH=/kong/?.lua;/kong/?/init.lua;/root/.luarocks/share/lua/5.1/?.lua;/root/.luarocks/share/lua/5.1/?/init.lua;/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua;./?.lua;/usr/local/openresty/luajit/share/luajit-2.1.0-beta3/?.lua;/usr/local/openresty/luajit/share/lua/5.1/?.lua;/usr/local/openresty/luajit/share/lua/5.1/?/init.lua 11 | ENV LUA_CPATH=/root/.luarocks/lib/lua/5.1/?.so;/usr/local/lib/lua/5.1/?.so;./?.so;/usr/local/openresty/luajit/lib/lua/5.1/?.so;/usr/local/lib/lua/5.1/loadall.so 12 | 13 | RUN cp -R /tmp/build/* / || true 14 | RUN rm -rf /usr/local/bin/kong 15 | RUN ln -fs /usr/share/zoneinfo/America/New_York /etc/localtime && \ 16 | apt-get update && \ 17 | apt-get upgrade -y && \ 18 | apt-get install -y \ 19 | ca-certificates \ 20 | tzdata \ 21 | vim \ 22 | jq \ 23 | httpie \ 24 | iputils-ping \ 25 | net-tools \ 26 | valgrind \ 27 | net-tools && \ 28 | dpkg-reconfigure --frontend noninteractive tzdata && \ 29 | apt-get install -y postgresql 30 | 31 | RUN rm -rf /kong/* || true 32 | COPY kong /kong 33 | RUN rm -rf /kong/bin/grpcurl 34 | RUN mkdir -p /kong/servroot/logs 35 | RUN chmod -R 777 /kong 36 | WORKDIR /kong 37 | RUN luarocks purge --tree=/usr/local || true 38 | RUN /usr/local/bin/luarocks make kong-*.rockspec \ 39 | CRYPTO_DIR=/usr/local/kong \ 40 | OPENSSL_DIR=/usr/local/kong \ 41 | YAML_LIBDIR=/usr/local/kong/lib \ 42 | EXPAT_DIR=/usr/local/kong \ 43 | LIBXML2_DIR=/usr/local/kong \ 44 | CFLAGS="-L/usr/local/kong/lib -Wl,-rpath,/usr/local/kong/lib -O2 -fPIC" 45 | RUN make dev 46 | 47 | RUN curl -L https://cpanmin.us | perl - App::cpanminus \ 48 | && cpanm --notest Test::Nginx \ 49 | && cpanm --notest local::lib 50 | 51 | RUN rm -rf /tmp/build 52 | 53 | CMD ["sh", "-c", "cat /kong/spec/fixtures/hosts >> /etc/hosts; tail -f /dev/null"] 54 | -------------------------------------------------------------------------------- /docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeo pipefail 3 | 4 | # usage: file_env VAR [DEFAULT] 5 | # ie: file_env 'XYZ_DB_PASSWORD' 'example' 6 | # (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of 7 | # "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature) 8 | file_env() { 9 | local var="$1" 10 | local fileVar="${var}_FILE" 11 | local def="${2:-}" 12 | # Do not continue if _FILE env is not set 13 | if ! [ "${!fileVar:-}" ]; then 14 | return 15 | elif [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then 16 | echo >&2 "error: both $var and $fileVar are set (but are exclusive)" 17 | exit 1 18 | fi 19 | local val="$def" 20 | if [ "${!var:-}" ]; then 21 | val="${!var}" 22 | elif [ "${!fileVar:-}" ]; then 23 | val="$(< "${!fileVar}")" 24 | fi 25 | export "$var"="$val" 26 | unset "$fileVar" 27 | } 28 | 29 | export KONG_NGINX_DAEMON=${KONG_NGINX_DAEMON:=off} 30 | 31 | if [[ "$1" == "kong" ]]; then 32 | 33 | all_kong_options="/usr/local/share/lua/5.1/kong/templates/kong_defaults.lua" 34 | set +Eeo pipefail 35 | while IFS='' read -r LINE || [ -n "${LINE}" ]; do 36 | opt=$(echo "$LINE" | grep "=" | sed "s/=.*$//" | sed "s/ //" | tr '[:lower:]' '[:upper:]') 37 | file_env "KONG_$opt" 38 | done < $all_kong_options 39 | set -Eeo pipefail 40 | 41 | file_env KONG_PASSWORD 42 | PREFIX=${KONG_PREFIX:=/usr/local/kong} 43 | 44 | if [[ "$2" == "docker-start" ]]; then 45 | kong prepare -p "$PREFIX" "$@" 46 | 47 | # remove all dangling sockets in $PREFIX dir before starting Kong 48 | LOGGED_SOCKET_WARNING=0 49 | for localfile in "$PREFIX"/* "$PREFIX"/sockets/*; do 50 | if [ -S "$localfile" ]; then 51 | if (( LOGGED_SOCKET_WARNING == 0 )); then 52 | printf >&2 'WARN: found dangling unix sockets in the prefix directory ' 53 | printf >&2 '(%q) ' "$PREFIX" 54 | printf >&2 'while preparing to start Kong. This may be a sign that Kong ' 55 | printf >&2 'was previously shut down uncleanly or is in an unknown state ' 56 | printf >&2 'and could require further investigation.\n' 57 | LOGGED_SOCKET_WARNING=1 58 | fi 59 | rm -f "$localfile" 60 | fi 61 | done 62 | 63 | ln -sfn /dev/stdout $PREFIX/logs/access.log 64 | ln -sfn /dev/stdout $PREFIX/logs/admin_access.log 65 | ln -sfn /dev/stderr $PREFIX/logs/error.log 66 | 67 | exec /usr/local/openresty/nginx/sbin/nginx \ 68 | -p "$PREFIX" \ 69 | -c nginx.conf 70 | fi 71 | fi 72 | 73 | exec "$@" 74 | -------------------------------------------------------------------------------- /ubuntu/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeo pipefail 3 | 4 | # usage: file_env VAR [DEFAULT] 5 | # ie: file_env 'XYZ_DB_PASSWORD' 'example' 6 | # (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of 7 | # "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature) 8 | file_env() { 9 | local var="$1" 10 | local fileVar="${var}_FILE" 11 | local def="${2:-}" 12 | # Do not continue if _FILE env is not set 13 | if ! [ "${!fileVar:-}" ]; then 14 | return 15 | elif [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then 16 | echo >&2 "error: both $var and $fileVar are set (but are exclusive)" 17 | exit 1 18 | fi 19 | local val="$def" 20 | if [ "${!var:-}" ]; then 21 | val="${!var}" 22 | elif [ "${!fileVar:-}" ]; then 23 | val="$(< "${!fileVar}")" 24 | fi 25 | export "$var"="$val" 26 | unset "$fileVar" 27 | } 28 | 29 | export KONG_NGINX_DAEMON=${KONG_NGINX_DAEMON:=off} 30 | 31 | if [[ "$1" == "kong" ]]; then 32 | 33 | all_kong_options="/usr/local/share/lua/5.1/kong/templates/kong_defaults.lua" 34 | set +Eeo pipefail 35 | while IFS='' read -r LINE || [ -n "${LINE}" ]; do 36 | opt=$(echo "$LINE" | grep "=" | sed "s/=.*$//" | sed "s/ //" | tr '[:lower:]' '[:upper:]') 37 | file_env "KONG_$opt" 38 | done < $all_kong_options 39 | set -Eeo pipefail 40 | 41 | file_env KONG_PASSWORD 42 | PREFIX=${KONG_PREFIX:=/usr/local/kong} 43 | 44 | if [[ "$2" == "docker-start" ]]; then 45 | kong prepare -p "$PREFIX" "$@" 46 | 47 | # remove all dangling sockets in $PREFIX dir before starting Kong 48 | LOGGED_SOCKET_WARNING=0 49 | for localfile in "$PREFIX"/* "$PREFIX"/sockets/*; do 50 | if [ -S "$localfile" ]; then 51 | if (( LOGGED_SOCKET_WARNING == 0 )); then 52 | printf >&2 'WARN: found dangling unix sockets in the prefix directory ' 53 | printf >&2 '(%q) ' "$PREFIX" 54 | printf >&2 'while preparing to start Kong. This may be a sign that Kong ' 55 | printf >&2 'was previously shut down uncleanly or is in an unknown state ' 56 | printf >&2 'and could require further investigation.\n' 57 | LOGGED_SOCKET_WARNING=1 58 | fi 59 | rm -f "$localfile" 60 | fi 61 | done 62 | 63 | ln -sfn /dev/stdout $PREFIX/logs/access.log 64 | ln -sfn /dev/stdout $PREFIX/logs/admin_access.log 65 | ln -sfn /dev/stderr $PREFIX/logs/error.log 66 | 67 | exec /usr/local/openresty/nginx/sbin/nginx \ 68 | -p "$PREFIX" \ 69 | -c nginx.conf 70 | fi 71 | fi 72 | 73 | exec "$@" 74 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Build Status](https://github.com/kong/docker-kong/actions/workflows/test.yml/badge.svg) 2 | 3 | # About this Repo 4 | 5 | This is the Git repo of the Docker 6 | [official image](https://docs.docker.com/docker-hub/official_repos/) for 7 | [kong](https://registry.hub.docker.com/_/kong/). 8 | See [the Docker Hub page](https://registry.hub.docker.com/_/kong/) 9 | for the full readme on how to use this Docker image and for information 10 | regarding contributing and issues. 11 | 12 | The full readme is generated over in [docker-library/docs](https://github.com/docker-library/docs), 13 | specifically in [docker-library/docs/kong](https://github.com/docker-library/docs/tree/master/kong). 14 | 15 | See a change merged here that doesn't show up on the Docker Hub yet? 16 | Check [the "library/kong" manifest file in the docker-library/official-images 17 | repo](https://github.com/docker-library/official-images/blob/master/library/kong), 18 | especially [PRs with the "library/kong" label on that 19 | repo](https://github.com/docker-library/official-images/labels/library%2Fkong). For more information about the official images process, see the [docker-library/official-images readme](https://github.com/docker-library/official-images/blob/master/README.md). 20 | 21 | # For Kong developers 22 | 23 | ## Pushing a Kong patch release (x.y.Z) update 24 | 25 | If the update does not require changes to the Dockerfiles other than 26 | pointing to the latest Kong code, the process can be semi-automated as follows: 27 | 28 | 1. Check out this repository. 29 | 30 | 2. Run `./update.sh x.y.z` 31 | 32 | This will create a release branch, modify the relevant files automatically, 33 | give you a chance to review the changes and press "y", then 34 | it will push the branch and open a browser with the PR 35 | to this repository. 36 | 37 | 3. Peer review, run CI and merge the submitted PR. 38 | 39 | 4. Run `./submit.sh -p x.y.z` 40 | 41 | Once the internal PR is merged, this script will do the same 42 | for the [official-images](https://github.com/docker-library/official-images) 43 | repository. It will clone [Kong's fork](https://github.com/kong/official-images), 44 | create a branch, modify the relevant files automatically, 45 | give you a chance to review the changes and press "y", then 46 | it will push the branch and open a browser with the PR 47 | to the docker-library repository. 48 | 49 | ## Pushing a Kong minor release (x.Y.0) update 50 | 51 | Not semi-automated yet. Note that minor releases are more likely to require more 52 | extensive changes to the Dockerfiles. 53 | 54 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # DO NOT update KONG_BUILD_TOOLS manually - it's set by update.sh 2 | # to ensure same version is used here and in the respective kong version 3 | KONG_BUILD_TOOLS?=4.33.19 4 | 5 | PACKAGE?=deb 6 | BASE?=ubuntu 7 | 8 | DOCKER_TAG_PREFIX?=kong 9 | 10 | KONG_VERSION?= 11 | KONG_SHA256?= 12 | 13 | # these two flags cannot be specified in this makefile if the default 14 | # values from the Dockerfiles are desired 15 | # 16 | # this way, the build-arg flag variables are empty (preventing a flag from 17 | # being passed to docker at all) if the parent VARs are unset 18 | ifeq ($(strip $(KONG_VERSION)),) 19 | KONG_VERSION_FLAG:= 20 | else 21 | KONG_VERSION_FLAG:=--build-arg KONG_VERSION=$(KONG_VERSION) 22 | endif 23 | 24 | ifeq ($(strip $(KONG_SHA256)),) 25 | KONG_SHA256_FLAG:= 26 | else 27 | KONG_SHA256_FLAG:=--build-arg KONG_SHA256=$(KONG_SHA256) 28 | endif 29 | 30 | RHEL_REGISTRY_KEY?= 31 | RHEL_REGISTRY?=scan.connect.redhat.com 32 | RHEL_PID?= 33 | RHEL_REGISTRY_REPO?=$(RHEL_REGISTRY)/$(RHEL_PID)/kong 34 | 35 | # search for "build_v2" in the invocation make goals and set tags accordingly 36 | ifneq ($(findstring build_v2,$(MAKECMDGOALS)),) 37 | DOCKER_TAG?=$(DOCKER_TAG_PREFIX)-$(PACKAGE) 38 | else 39 | DOCKER_TAG?=$(DOCKER_TAG_PREFIX)-$(BASE) 40 | endif 41 | 42 | build: ASSET_LOCATION?=ce 43 | build: 44 | docker build \ 45 | --no-cache \ 46 | --build-arg ASSET=$(ASSET_LOCATION) \ 47 | $(KONG_VERSION_FLAG) \ 48 | $(KONG_SHA256_FLAG) \ 49 | -t $(DOCKER_TAG) \ 50 | $(BASE)/ 51 | 52 | # (yzl, 14 June 2022) Should you change this substantially, please update build_your_own_images.md. 53 | build_v2: ASSET_LOCATION?=remote 54 | build_v2: 55 | docker image inspect -f='{{.Id}}' $(DOCKER_TAG) || \ 56 | docker build \ 57 | --no-cache \ 58 | --build-arg ASSET=$(ASSET_LOCATION) \ 59 | $(KONG_VERSION_FLAG) \ 60 | $(KONG_SHA256_FLAG) \ 61 | -t $(DOCKER_TAG) \ 62 | -f Dockerfile.$(PACKAGE) \ 63 | . 64 | 65 | .PHONY: test 66 | 67 | test: KONG_DOCKER_TAG?=$(DOCKER_TAG) 68 | test: 69 | BASE=$(BASE) ./tests/test.sh --suite "Docker-Kong test suite" 70 | 71 | release-rhel: build_v2 72 | $(MAKE) PACKAGE=rpm build_v2 73 | @if \ 74 | test -z '$(KONG_VERSION)' || \ 75 | test -z '$(RHEL_PID)' || \ 76 | test -z '$(RHEL_REGISTRY_KEY)' \ 77 | ; then \ 78 | echo 'one of $$KONG_VERSION, $$RHEL_PID, $$RHEL_REGISTRY_KEY unset'; \ 79 | exit 2; \ 80 | fi 81 | @echo '$(RHEL_REGISTRY_KEY)' \ 82 | | docker login -u unused $(RHEL_REGISTRY) --password-stdin 83 | docker tag $(DOCKER_TAG) $(RHEL_REGISTRY_REPO):$(KONG_VERSION) 84 | docker push $(RHEL_REGISTRY_REPO):$(KONG_VERSION) 85 | 86 | -------------------------------------------------------------------------------- /kong-build-tools/test/build_container.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source test/util.sh 4 | set -e 5 | 6 | SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) 7 | source $SCRIPT_DIR/../openresty-build-tools/common.sh 8 | 9 | DOCKER_BUILD_ARGS=() 10 | 11 | KONG_TEST_IMAGE_NAME=$DOCKER_RELEASE_REPOSITORY:$ARCHITECTURE-$KONG_TEST_CONTAINER_TAG 12 | 13 | image_id=$(docker image inspect -f '{{.ID}}' "$KONG_TEST_IMAGE_NAME" || true) 14 | if [ -n "$image_id" ]; then 15 | msg_test "Tests image Name: $KONG_TEST_IMAGE_NAME" 16 | msg_test "Tests image ID: $image_id" 17 | exit 0; 18 | fi 19 | 20 | rm -rf docker-kong || true 21 | git clone --single-branch --branch $DOCKER_KONG_VERSION https://github.com/Kong/docker-kong.git docker-kong 22 | chmod -R 755 docker-kong/*.sh 23 | 24 | if [ "$RESTY_IMAGE_BASE" == "src" ]; then 25 | exit 0 26 | elif [ "$RESTY_IMAGE_BASE" == "alpine" ]; then 27 | cp output/${KONG_PACKAGE_NAME}-${KONG_RELEASE_LABEL}.${ARCHITECTURE}.apk.tar.gz docker-kong/kong.apk.tar.gz 28 | elif [ "$PACKAGE_TYPE" == "deb" ]; then 29 | cp output/*${ARCHITECTURE}*.deb docker-kong/kong.deb 30 | else 31 | cp output/*.${PACKAGE_TYPE} docker-kong/kong.${PACKAGE_TYPE} 32 | fi 33 | 34 | pushd ./docker-kong 35 | if \ 36 | [ "$RESTY_IMAGE_BASE" == 'rhel' ] || \ 37 | [[ "$RESTY_IMAGE_BASE" == *'/ubi'* ]] || \ 38 | [[ "$RESTY_IMAGE_BASE" == *'redhat'* ]] 39 | then 40 | major="${RESTY_IMAGE_TAG%%.*}" 41 | 42 | sed -i.bak "s|^FROM .*|FROM registry.access.redhat.com/ubi${major}|" Dockerfile.$PACKAGE_TYPE 43 | elif [ "$RESTY_IMAGE_BASE" == "debian" ]; then 44 | sed -i.bak 's/^FROM .*/FROM '${RESTY_IMAGE_BASE}:${RESTY_IMAGE_TAG}-slim'/' Dockerfile.$PACKAGE_TYPE 45 | else 46 | sed -i.bak 's/^FROM .*/FROM '${RESTY_IMAGE_BASE}:${RESTY_IMAGE_TAG}'/' Dockerfile.$PACKAGE_TYPE 47 | fi 48 | 49 | if [ -n "$DOCKER_LABEL_REVISION" ]; then 50 | DOCKER_BUILD_ARGS+=(--label "org.opencontainers.image.revision=$DOCKER_LABEL_REVISION") 51 | fi 52 | 53 | DOCKER_BUILD_ARGS+=(--platform linux/${ARCHITECTURE}) 54 | DOCKER_BUILD_ARGS+=(--no-cache) 55 | DOCKER_BUILD_ARGS+=(--pull) 56 | DOCKER_BUILD_ARGS+=(--build-arg ASSET=local .) 57 | 58 | if [[ "$EDITION" == 'enterprise' ]]; then 59 | DOCKER_BUILD_ARGS+=(--build-arg EE_PORTS="8002 8445 8003 8446 8004 8447") 60 | fi 61 | 62 | with_backoff docker build \ 63 | --progress=${DOCKER_BUILD_PROGRESS:-auto} \ 64 | -t $KONG_TEST_IMAGE_NAME \ 65 | -f Dockerfile.$PACKAGE_TYPE \ 66 | ${DOCKER_LABELS} \ 67 | "${DOCKER_BUILD_ARGS[@]}" 68 | 69 | msg_test "Tests image Name: $KONG_TEST_IMAGE_NAME" 70 | popd 71 | 72 | rm -rf docker-kong || true 73 | -------------------------------------------------------------------------------- /ubuntu/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:noble 2 | 3 | LABEL maintainer="Kong Docker Maintainers (@team-gateway-bot)" 4 | 5 | ARG ASSET=ce 6 | ENV ASSET $ASSET 7 | 8 | ARG EE_PORTS 9 | 10 | COPY kong.deb /tmp/kong.deb 11 | 12 | ARG KONG_VERSION=3.9.1 13 | ENV KONG_VERSION $KONG_VERSION 14 | 15 | ARG KONG_AMD64_SHA="8f493149bfc321d3108e5031f5008dd1511aed166fb0d4673916577d04c63eac" 16 | ARG KONG_ARM64_SHA="87f9c971d232c71fcd21808c65082cdd9ded3441950c00d2718206b6438c7cd8" 17 | 18 | # hadolint ignore=DL3015 19 | RUN set -ex; \ 20 | arch=$(dpkg --print-architecture); \ 21 | case "${arch}" in \ 22 | amd64) KONG_SHA256=$KONG_AMD64_SHA ;; \ 23 | arm64) KONG_SHA256=$KONG_ARM64_SHA ;; \ 24 | esac; \ 25 | apt-get update \ 26 | && if [ "$ASSET" = "ce" ] ; then \ 27 | apt-get install -y --no-install-recommends curl ca-certificates \ 28 | && UBUNTU_CODENAME=$(cat /etc/os-release | grep UBUNTU_CODENAME | cut -d = -f 2) \ 29 | && KONG_REPO=$(echo ${KONG_VERSION%.*} | sed 's/\.//') \ 30 | && curl -fL https://packages.konghq.com/public/gateway-$KONG_REPO/deb/ubuntu/pool/$UBUNTU_CODENAME/main/k/ko/kong_$KONG_VERSION/kong_${KONG_VERSION}_$arch.deb -o /tmp/kong.deb \ 31 | && apt-get purge -y curl \ 32 | && echo "$KONG_SHA256 /tmp/kong.deb" | sha256sum -c - \ 33 | || exit 1; \ 34 | else \ 35 | # this needs to stay inside this "else" block so that it does not become part of the "official images" builds (https://github.com/docker-library/official-images/pull/11532#issuecomment-996219700) 36 | apt-get upgrade -y ; \ 37 | fi; \ 38 | apt-get install -y --no-install-recommends unzip git \ 39 | # Please update the ubuntu install docs if the below line is changed so that 40 | # end users can properly install Kong along with its required dependencies 41 | # and that our CI does not diverge from our docs. 42 | && apt install --yes --no-install-recommends /tmp/kong.deb \ 43 | && rm -rf /var/lib/apt/lists/* \ 44 | && rm -rf /tmp/kong.deb \ 45 | && chown kong:0 /usr/local/bin/kong \ 46 | && chown -R kong:0 /usr/local/kong \ 47 | && ln -sf /usr/local/openresty/bin/resty /usr/local/bin/resty \ 48 | && ln -sf /usr/local/openresty/luajit/bin/luajit /usr/local/bin/luajit \ 49 | && ln -sf /usr/local/openresty/luajit/bin/luajit /usr/local/bin/lua \ 50 | && ln -sf /usr/local/openresty/nginx/sbin/nginx /usr/local/bin/nginx \ 51 | && if [ "$ASSET" = "ce" ] ; then \ 52 | kong version ; \ 53 | fi 54 | 55 | COPY docker-entrypoint.sh /docker-entrypoint.sh 56 | 57 | USER kong 58 | 59 | ENTRYPOINT ["/docker-entrypoint.sh"] 60 | 61 | EXPOSE 8000 8443 8001 8444 $EE_PORTS 62 | 63 | STOPSIGNAL SIGQUIT 64 | 65 | HEALTHCHECK --interval=10s --timeout=10s --retries=10 CMD kong health 66 | 67 | CMD ["kong", "docker-start"] 68 | -------------------------------------------------------------------------------- /Dockerfile.rpm: -------------------------------------------------------------------------------- 1 | # When you update this file substantially, please update build_your_own_images.md as well. 2 | FROM registry.access.redhat.com/ubi9-minimal@sha256:92b1d5747a93608b6adb64dfd54515c3c5a360802db4706765ff3d8470df6290 3 | 4 | LABEL maintainer="Kong Docker Maintainers (@team-gateway-bot)" 5 | 6 | ARG KONG_VERSION=3.9.1 7 | ENV KONG_VERSION $KONG_VERSION 8 | 9 | # RedHat required labels 10 | LABEL name="Kong" \ 11 | vendor="Kong" \ 12 | version="$KONG_VERSION" \ 13 | release="1" \ 14 | url="https://konghq.com" \ 15 | summary="Next-Generation API Platform for Modern Architectures" \ 16 | description="Next-Generation API Platform for Modern Architectures" 17 | 18 | # RedHat required LICENSE file approved path 19 | COPY LICENSE /licenses/ 20 | 21 | ARG KONG_SHA256="880a832e1d4cb2b4a2fa6e5d673c66b224c37a968e81a10f48f8dc7411fd7ab3" 22 | 23 | ARG KONG_PREFIX=/usr/local/kong 24 | ENV KONG_PREFIX $KONG_PREFIX 25 | 26 | ARG ASSET=remote 27 | ARG EE_PORTS 28 | 29 | COPY kong.rpm /tmp/kong.rpm 30 | 31 | # hadolint ignore=DL3015 32 | RUN set -ex; \ 33 | if [ "$ASSET" = "remote" ] ; then \ 34 | KONG_REPO=$(echo ${KONG_VERSION%.*} | sed 's/\.//') \ 35 | && DOWNLOAD_URL="https://packages.konghq.com/public/gateway-$KONG_REPO/rpm/el/9/x86_64/kong-$KONG_VERSION.el9.x86_64.rpm" \ 36 | && curl -fL $DOWNLOAD_URL -o /tmp/kong.rpm \ 37 | && echo "$KONG_SHA256 /tmp/kong.rpm" | sha256sum -c - \ 38 | || exit 1; \ 39 | fi \ 40 | # findutils provides xargs (temporarily) 41 | && microdnf install --assumeyes --nodocs \ 42 | findutils \ 43 | shadow-utils \ 44 | unzip \ 45 | && rpm -qpR /tmp/kong.rpm \ 46 | | grep -v rpmlib \ 47 | | xargs -n1 -t microdnf install --assumeyes --nodocs \ 48 | # Please update the rhel install docs if the below line is changed so that 49 | # end users can properly install Kong along with its required dependencies 50 | # and that our CI does not diverge from our docs. 51 | && rpm -iv /tmp/kong.rpm \ 52 | && microdnf -y clean all \ 53 | && rm /tmp/kong.rpm \ 54 | && chown kong:0 /usr/local/bin/kong \ 55 | && chown -R kong:0 ${KONG_PREFIX} \ 56 | && ln -sf /usr/local/openresty/bin/resty /usr/local/bin/resty \ 57 | && ln -sf /usr/local/openresty/luajit/bin/luajit /usr/local/bin/luajit \ 58 | && ln -sf /usr/local/openresty/luajit/bin/luajit /usr/local/bin/lua \ 59 | && ln -sf /usr/local/openresty/nginx/sbin/nginx /usr/local/bin/nginx \ 60 | && kong version 61 | 62 | COPY docker-entrypoint.sh /docker-entrypoint.sh 63 | 64 | USER kong 65 | 66 | ENTRYPOINT ["/docker-entrypoint.sh"] 67 | 68 | EXPOSE 8000 8443 8001 8444 $EE_PORTS 69 | 70 | STOPSIGNAL SIGQUIT 71 | 72 | HEALTHCHECK --interval=60s --timeout=10s --retries=10 CMD kong-health 73 | 74 | CMD ["kong", "docker-start"] 75 | -------------------------------------------------------------------------------- /customize/readme.md: -------------------------------------------------------------------------------- 1 | # Customize Kong by injecting plugins and templates 2 | 3 | This dockerfile takes an existing Kong image and adds custom plugins 4 | and/or a custom template file to it. 5 | 6 | ``` 7 | docker build \ 8 | --build-arg KONG_BASE="kong:0.14.1-ubuntu" \ 9 | --build-arg PLUGINS="kong-http-to-https,kong-upstream-jwt" \ 10 | --build-arg TEMPLATE="/mykong/nginx.conf" \ 11 | --build-arg "KONG_LICENSE_DATA=$KONG_LICENSE_DATA" \ 12 | --tag "your_new_image" . 13 | ``` 14 | 15 | The above command will take the `kong:0.14.1-alpine` image and add the plugins 16 | (as known on [luarocks.org](https://luarocks.org)) `kong-http-to-https` and 17 | `kong-upstream-jwt` to it. Also the custom template ([for rendering the 18 | underlying nginx configuration file](https://docs.konghq.com/latest/configuration/#custom-nginx-templates--embedding-kong) 19 | ), located at `/mykong/nginx.conf` will be injected. 20 | The resulting new image will be tagged as `your_new_image`. 21 | 22 | When starting a container from the newly created image, the added plugins and 23 | template will automatically be applied. So there is no need to specify the 24 | environment variable `KONG_PLUGINS` nor the `--nginx-conf` command line 25 | switch to enable them. 26 | 27 | # Checking the available plugins 28 | 29 | To check the plugins available in an image, use the example 30 | [`list_plugins.sh`](list_plugins.sh) script. 31 | 32 | # Curated list of plugins 33 | 34 | This tool is based on the LuaRocks packagemanager to include all plugin 35 | dependencies. The `ROCKS_DIR` variable allows you to only use a curated list of 36 | rocks to be used (instead of the public ones). 37 | 38 | It will generate a local LuaRocks server, and not allow any public ones to be 39 | used. For an example of how to use it see the [`example.sh`](example.sh) script. 40 | 41 | ## Arguments: 42 | 43 | - `KONG_BASE` the base image to use, defaults to `kong:latest`. 44 | - `PLUGINS` a comma-separated list of the plugin names (NOT rock files!) that you wish to add to the image. All 45 | dependencies will also be installed. 46 | - `ROCKS_DIR` a local directory where the allowed plugins/rocks are located. If 47 | specified, only rocks from this location will be allowed to be installed. If 48 | not specified, then the public `luarocks.org` server is used. 49 | - `TEMPLATE` the custom configuration template to use 50 | - `KONG_LICENSE_DATA` this is required when the base image is an Enterprise 51 | version of Kong. 52 | 53 | Note that the `PLUGINS` entries are simply LuaRocks commands used as: 54 | `luarocks install `. So anything that LuaRocks accepts can be added 55 | there, including commandline options. For example: 56 | 57 | ``` 58 | --build-arg PLUGINS="luassert --deps-mode=none" 59 | ``` 60 | 61 | Will add the `luassert` module, without resolving dependencies (this is useless, 62 | but demonstrates how it works). 63 | 64 | 65 | ## Limitations 66 | 67 | - Only works for pure-Lua modules for now. 68 | -------------------------------------------------------------------------------- /tests/03-cis-sec.test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | function run_test { 4 | # the suite name below will only be used when rtunning this file directly, when 5 | # running through "test.sh" it must be provided using the "--suite" option. 6 | tinitialize "Docker-Kong test suite" "${BASH_SOURCE[0]}" 7 | 8 | tchapter "CIS-Sec tests $KONG_DOCKER_TAG" 9 | ttest "CIS-Sec for docker compose" 10 | 11 | docker kill $(docker ps -q) 12 | docker run -d kong-$BASE tail -f /dev/null 13 | docker rmi kong:1.5.0 14 | docker rmi postgres:9.5 15 | docker images 16 | 17 | rm -rf tests/docker-bench-security 18 | 19 | LOG_OUTPUT=docker-bench-security.log 20 | 21 | # * 5.1 is "apparmor". That option is not available in docker compose 3.x 22 | # * 5.10 is "mem_limit". That option is not available in docker compose 3.x (it has moved to resources) 23 | # * 5.11 is "cpu_shares". That option is not available in docker compose 3.x 24 | # * 5.28 is "pids_limit". That option is also not available in docker compose 3.x 25 | # * See https://github.com/docker/compose/issues/4513 for more examples of incompatibilities 26 | LINUX_EXCLUDE_TESTS=5_1,5_10,5_11,5_28 27 | 28 | if [[ -f /lib/systemd/system/docker.service ]]; then # Ubuntu 29 | mkdir tests/docker-bench-security 30 | pushd tests/docker-bench-security 31 | docker run --rm --net host --pid host --userns host --cap-add audit_control \ 32 | -e DOCKER_CONTENT_TRUST=$DOCKER_CONTENT_TRUST \ 33 | -v /etc:/etc:ro \ 34 | -v /lib/systemd/system:/lib/systemd/system:ro \ 35 | -v /usr/bin/containerd:/usr/bin/containerd:ro \ 36 | -v /usr/bin/runc:/usr/bin/runc:ro \ 37 | -v /usr/lib/systemd:/usr/lib/systemd:ro \ 38 | -v /var/lib:/var/lib:ro \ 39 | -v /var/run/docker.sock:/var/run/docker.sock:ro \ 40 | --label docker_bench_security \ 41 | docker/docker-bench-security -e $LINUX_EXCLUDE_TESTS > $LOG_OUTPUT 42 | 43 | else # all other linux distros 44 | mkdir tests/docker-bench-security 45 | pushd tests/docker-bench-security 46 | docker run --rm --net host --pid host --userns host --cap-add audit_control \ 47 | -e DOCKER_CONTENT_TRUST=$DOCKER_CONTENT_TRUST \ 48 | -v /etc:/etc:ro \ 49 | -v /usr/bin/containerd:/usr/bin/containerd:ro \ 50 | -v /usr/bin/runc:/usr/bin/runc:ro \ 51 | -v /usr/lib/systemd:/usr/lib/systemd:ro \ 52 | -v /var/lib:/var/lib:ro \ 53 | -v /var/run/docker.sock:/var/run/docker.sock:ro \ 54 | --label docker_bench_security \ 55 | docker/docker-bench-security -e $LINUX_EXCLUDE_TESTS > $LOG_OUTPUT 56 | fi 57 | 58 | if cat "$LOG_OUTPUT" | grep WARN | grep kong -B 1; then 59 | tmessage "Found warnings in docker-bench-security report" 60 | tfailure 61 | else 62 | tsuccess 63 | fi 64 | 65 | popd 66 | rm -rf tests/docker-bench-security 67 | 68 | tfinish 69 | } 70 | 71 | # No need to modify anything below this comment 72 | 73 | # shellcheck disable=SC1090 # do not follow source 74 | [[ "$T_PROJECT_NAME" == "" ]] && set -e && if [[ -f "${1:-$(dirname "$(realpath "$0")")/test.sh}" ]]; then source "${1:-$(dirname "$(realpath "$0")")/test.sh}"; else source "${1:-$(dirname "$(realpath "$0")")/run.sh}"; fi && set +e 75 | run_test 76 | -------------------------------------------------------------------------------- /update.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | if ! [ "$1" ] 5 | then 6 | echo "usage: $0 " 7 | echo "example: $0 1.2.3" 8 | exit 1 9 | fi 10 | 11 | version=$1 12 | 13 | if [[ "$version" =~ "rc" ]]; then 14 | version="${version//-}" 15 | fi 16 | 17 | function red() { 18 | echo -e "\033[1;31m$@\033[0m" 19 | } 20 | 21 | function die() { 22 | red "*** $@" 23 | echo "See also: $0 --help" 24 | echo 25 | exit 1 26 | } 27 | 28 | # get kong url from dockerfile 29 | # and fill it up with needed args 30 | function get_url() { 31 | dockerfile=$1 32 | arch=$2 33 | args=$3 34 | 35 | eval $args 36 | 37 | raw_url=$(egrep -o 'https?://packages.konghq.com/public/gateway-[^ ]+' $dockerfile | sed 's/\"//g') 38 | 39 | # set variables contained in raw url 40 | KONG_VERSION=$version 41 | KONG_REPO=$(echo ${KONG_VERSION%.*} | sed 's/\.//') 42 | ARCH=$arch 43 | 44 | eval echo $raw_url 45 | } 46 | 47 | 48 | hub --version &> /dev/null || die "hub is not in PATH. Get it from https://github.com/github/hub" 49 | 50 | #kbt_in_kong_v=$(curl -sL https://raw.githubusercontent.com/Kong/kong/$version/.requirements | grep 'KONG_BUILD_TOOLS_VERSION\=' | awk -F"=" '{print $2}' | tr -d "'[:space:]") 51 | kbt_in_kong_v=4.33.19 52 | if [[ -n "$kbt_in_kong_v" ]]; then 53 | sed -i.bak 's/KONG_BUILD_TOOLS?=.*/KONG_BUILD_TOOLS?='$kbt_in_kong_v'/g' Makefile 54 | fi 55 | 56 | # Dockerfile.deb 57 | url=$(get_url Dockerfile.rpm amd64 "VERSION=9") 58 | echo $url 59 | curl -fL $url -o /tmp/kong 60 | new_sha=$(sha256sum /tmp/kong | cut -b1-64) 61 | 62 | sed -i.bak 's/ARG KONG_SHA256=.*/ARG KONG_SHA256=\"'$new_sha'\"/g' Dockerfile.rpm 63 | sed -i.bak 's/ARG KONG_VERSION=.*/ARG KONG_VERSION='$version'/g' Dockerfile.rpm 64 | 65 | pushd ubuntu 66 | url=$(get_url Dockerfile amd64 "UBUNTU_CODENAME=noble") 67 | echo $url 68 | curl -fL $url -o /tmp/kong 69 | new_sha=$(sha256sum /tmp/kong | cut -b1-64) 70 | 71 | sed -i.bak 's/ARG KONG_AMD64_SHA=.*/ARG KONG_AMD64_SHA=\"'$new_sha'\"/g' Dockerfile 72 | 73 | url=$(get_url Dockerfile arm64 "UBUNTU_CODENAME=noble") 74 | echo $url 75 | curl -fL $url -o /tmp/kong 76 | new_sha=$(sha256sum /tmp/kong | cut -b1-64) 77 | 78 | sed -i.bak 's/ARG KONG_ARM64_SHA=.*/ARG KONG_ARM64_SHA=\"'$new_sha'\"/g' Dockerfile 79 | sed -i.bak 's/ARG KONG_VERSION=.*/ARG KONG_VERSION='$version'/g' Dockerfile 80 | popd 81 | 82 | # Dockerfile.deb 83 | url=$(get_url Dockerfile.deb amd64 "CODENAME=bookworm") 84 | echo $url 85 | curl -fL $url -o /tmp/kong 86 | new_sha=$(sha256sum /tmp/kong | cut -b1-64) 87 | 88 | sed -i.bak 's/ARG KONG_SHA256=.*/ARG KONG_SHA256=\"'$new_sha'\"/g' Dockerfile.deb 89 | sed -i.bak 's/ARG KONG_VERSION=.*/ARG KONG_VERSION='$version'/g' Dockerfile.deb 90 | 91 | echo "****************************************" 92 | git diff 93 | echo "****************************************" 94 | 95 | echo "Everything looks all right? (y/n)" 96 | echo "(Answering y will commit, push the branch, and open a browser with the PR)" 97 | read 98 | if ! [ "$REPLY" == "y" ] 99 | then 100 | exit 1 101 | fi 102 | 103 | git commit -av -m "chore(*) bump to Kong $version" 104 | git push --set-upstream origin release/$version 105 | 106 | hub pull-request -b master -h "$branch" -m "Release: $version" 107 | -------------------------------------------------------------------------------- /kong-build-tools/test/util.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | msg_test() { 4 | builtin echo -en "\033[1;34m" >&1 5 | echo -n "===> " 6 | builtin echo -en "\033[1;36m" >&1 7 | echo -e "$@" 8 | builtin echo -en "\033[0m" >&1 9 | } 10 | 11 | msg_yellow() { 12 | builtin echo -en "\033[1;33m" >&1 13 | echo -e "$@" 14 | builtin echo -en "\033[0m" >&1 15 | } 16 | 17 | msg_green() { 18 | builtin echo -en "\033[1;32m" >&1 19 | echo -e "$@" 20 | builtin echo -en "\033[0m" >&1 21 | } 22 | 23 | msg_red() { 24 | builtin echo -en "\033[1;31m" >&2 25 | echo -e "$@" 26 | builtin echo -en "\033[0m" >&2 27 | } 28 | 29 | err_exit() { 30 | msg_red "$@" 31 | exit 1 32 | } 33 | 34 | wait_for() { 35 | local i=$1 36 | local char=${2:-.} 37 | while [ "$i" -gt 0 ]; do 38 | echo -n "$char" 39 | i=$(( i-1 )) 40 | sleep 1 41 | done 42 | echo 43 | } 44 | 45 | start_kong() { 46 | KONG_FIPS=off 47 | if [ "$SSL_PROVIDER" = "boringssl" ]; then 48 | KONG_FIPS=on 49 | fi 50 | KONG_FIPS=$KONG_FIPS KONG_TEST_IMAGE_NAME=${1:-$KONG_TEST_IMAGE_NAME} docker compose -f "$TEST_COMPOSE_PATH" up -d 51 | } 52 | 53 | stop_kong() { 54 | KONG_TEST_IMAGE_NAME=${1:-$KONG_TEST_IMAGE_NAME} docker compose -f "$TEST_COMPOSE_PATH" down 55 | KONG_TEST_IMAGE_NAME=${1:-$KONG_TEST_IMAGE_NAME} docker compose -f "$TEST_COMPOSE_PATH" rm -f 56 | docker stop $(docker ps -a -q) || true 57 | docker rm $(docker ps -a -q) || true 58 | docker volume prune -f 59 | } 60 | 61 | kong_ready() { 62 | local TIMEOUT_SECONDS=$((5 * 60)) 63 | while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:8000)" != 404 ]]; do 64 | sleep 5; 65 | COUNTER=$((COUNTER + 5)) 66 | 67 | if (($COUNTER >= $TIMEOUT_SECONDS)) 68 | then 69 | printf "\xe2\x98\x93 ERROR: Timed out waiting for $KONG" 70 | exit 1 71 | fi 72 | done 73 | } 74 | 75 | wait_kong() { 76 | while ! kong_ready; do 77 | msg_test "Waiting for Kong to be ready " 78 | docker compose -f "$TEST_COMPOSE_PATH" ps 79 | docker compose -f "$TEST_COMPOSE_PATH" logs kong 80 | sleep 5 81 | done 82 | } 83 | 84 | assert_response() { 85 | local endpoint=$1 86 | local expected_code=$2 87 | local resp_code 88 | COUNTER=20 89 | while : ; do 90 | resp_code=$(curl -s -o /dev/null -w "%{http_code}" $endpoint) 91 | [ "$resp_code" == "$expected_code" ] && break 92 | ((COUNTER-=1)) 93 | [ "$COUNTER" -lt 1 ] && break 94 | sleep 0.5 # 10 seconds max 95 | done 96 | [ "$resp_code" == "$expected_code" ] || err_exit " expected $2, got $resp_code" 97 | } 98 | 99 | it_runs_free_enterprise() { 100 | info=$(curl $KONG_ADMIN_URI) 101 | msg_test "it does not have ee-only plugins" 102 | [ "$(echo $info | jq -r .plugins.available_on_server.canary)" != "true" ] 103 | msg_test "it does not enable vitals" 104 | [ "$(echo $info | jq -r .configuration.vitals)" == "false" ] 105 | msg_test "workspaces are not writable" 106 | assert_response "$KONG_ADMIN_URI/workspaces -d name=testworkspace" "403" 107 | } 108 | 109 | it_runs_full_enterprise() { 110 | info=$(curl $KONG_ADMIN_URI) 111 | msg_test "it does have ee-only plugins" 112 | [ "$(echo $info | jq -r .plugins.available_on_server | jq -r 'has("canary")')" == "true" ] 113 | msg_test "it does enable vitals" 114 | [ "$(echo $info | jq -r .configuration.vitals)" == "true" ] 115 | msg_test "workspaces are writable" 116 | assert_response "$KONG_ADMIN_URI/workspaces -d name=testworkspace" "201" 117 | } 118 | -------------------------------------------------------------------------------- /kong-build-tools/test/kong-tests-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '2.1' 2 | 3 | 4 | services: 5 | kong-migrations: 6 | image: "${KONG_TEST_IMAGE_NAME:-kong:latest}" 7 | command: kong migrations bootstrap 8 | depends_on: 9 | db: 10 | condition: service_healthy 11 | environment: 12 | KONG_DATABASE: postgres 13 | KONG_PG_DATABASE: ${KONG_PG_DATABASE:-kong} 14 | KONG_PG_HOST: db 15 | KONG_PG_PASSWORD: ${KONG_PG_PASSWORD:-kong} 16 | KONG_PG_USER: ${KONG_PG_USER:-kong} 17 | KONG_FIPS: ${KONG_FIPS:-off} 18 | restart: always 19 | networks: 20 | - kong-net 21 | 22 | kong-migrations-up: 23 | image: "${KONG_TEST_IMAGE_NAME:-kong:latest}" 24 | command: kong migrations up && kong migrations finish 25 | depends_on: 26 | db: 27 | condition: service_healthy 28 | environment: 29 | KONG_DATABASE: postgres 30 | KONG_PG_DATABASE: ${KONG_PG_DATABASE:-kong} 31 | KONG_PG_HOST: db 32 | KONG_PG_PASSWORD: ${KONG_PG_PASSWORD:-kong} 33 | KONG_PG_USER: ${KONG_PG_USER:-kong} 34 | KONG_FIPS: ${KONG_FIPS:-off} 35 | restart: always 36 | networks: 37 | - kong-net 38 | 39 | kong: 40 | image: "${KONG_TEST_IMAGE_NAME:-kong:latest}" 41 | user: "${KONG_USER:-kong}" 42 | container_name: "${KONG_TEST_CONTAINER_NAME:-kong-tests}" 43 | depends_on: 44 | db: 45 | condition: service_healthy 46 | environment: 47 | KONG_ADMIN_ACCESS_LOG: /dev/stdout 48 | KONG_ADMIN_ERROR_LOG: /dev/stderr 49 | KONG_PROXY_LISTEN: "0.0.0.0:8000" 50 | KONG_ADMIN_LISTEN: "0.0.0.0:8001" 51 | KONG_PLUGINS: "${KONG_PLUGINS:-bundled}" 52 | KONG_NGINX_WORKER_PROCESSES: "${KONG_NGINX_WORKER_PROCESSES:-1}" 53 | KONG_CASSANDRA_CONTACT_POINTS: db 54 | KONG_DATABASE: postgres 55 | KONG_PG_DATABASE: ${KONG_PG_DATABASE:-kong} 56 | KONG_PG_HOST: db 57 | KONG_PG_PASSWORD: ${KONG_PG_PASSWORD:-kong} 58 | KONG_PG_USER: ${KONG_PG_USER:-kong} 59 | KONG_PROXY_ACCESS_LOG: /dev/stdout 60 | KONG_PROXY_ERROR_LOG: /dev/stderr 61 | KONG_PORTAL: "on" 62 | KONG_ENFORCE_RBAC: 63 | KONG_LICENSE_DATA: 64 | KONG_FIPS: ${KONG_FIPS:-off} 65 | healthcheck: 66 | test: ["CMD", "kong", "health"] 67 | interval: 10s 68 | timeout: 10s 69 | retries: 10 70 | restart: on-failure 71 | networks: 72 | - kong-net 73 | ports: 74 | - "8000:8000/tcp" 75 | - "8443:8443/tcp" 76 | - "127.0.0.1:8001:8001/tcp" 77 | - "127.0.0.1:8002:8002/tcp" 78 | - "127.0.0.1:8003:8003/tcp" 79 | - "127.0.0.1:8004:8004/tcp" 80 | - "127.0.0.1:8444:8444/tcp" 81 | - "127.0.0.1:8445:8445/tcp" 82 | - "127.0.0.1:8446:8446/tcp" 83 | - "127.0.0.1:8447:8447/tcp" 84 | 85 | db: 86 | image: postgres:13 87 | ports: 88 | - '5432:5432' 89 | expose: 90 | - 5432 91 | environment: 92 | POSTGRES_DB: ${KONG_PG_DATABASE:-kong} 93 | POSTGRES_PASSWORD: ${KONG_PG_PASSWORD:-kong} 94 | POSTGRES_USER: ${KONG_PG_USER:-kong} 95 | stdin_open: true 96 | tty: true 97 | healthcheck: 98 | test: ["CMD", "pg_isready", "-U", "${KONG_PG_USER:-kong}"] 99 | interval: 5s 100 | timeout: 10s 101 | retries: 10 102 | networks: 103 | - kong-net 104 | 105 | mockbin: 106 | image: kennethreitz/httpbin 107 | ports: 108 | - '8080:80' 109 | expose: 110 | - 8000 111 | networks: 112 | - kong-net 113 | 114 | networks: 115 | kong-net: 116 | external: false 117 | 118 | -------------------------------------------------------------------------------- /compose/README.md: -------------------------------------------------------------------------------- 1 | # Kong in Docker Compose 2 | 3 | The official Docker Compose template for Kong Gateway. 4 | 5 | > **Note** 6 | > The Kong Docker Compose file uses the v3.9 compose schema; as such, 7 | > it requires Docker Engine version 20.10.0+. 8 | 9 | ## What is Kong? 10 | 11 | Kong or Kong API Gateway is a cloud-native, platform-agnostic, scalable API 12 | Gateway distinguished for its high performance and extensibility via plugins. 13 | 14 | - Kong's Official documentation can be found at [docs.konghq.com][kong-docs-url]. 15 | - You can find the official Docker distribution for Kong on [Docker Hub][kong-docker-url]. 16 | 17 | ## How to use this Compose file 18 | 19 | Kong Gateway can be deployed in different ways. This Docker Compose file provides 20 | support for running Kong in [db-less][kong-docs-dbless] mode, in which only a Kong 21 | container is spun up, or with a backing database. The default is db-less mode: 22 | 23 | ```shell 24 | $ docker compose up -d 25 | ``` 26 | 27 | This command will result in a single Kong Docker container: 28 | 29 | ```shell 30 | $ docker compose ps 31 | NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS 32 | compose-kong-1 kong:latest "/docker-entrypoint.…" kong 38 seconds ago Up 29 seconds (healthy) 0.0.0.0:8000->8000/tcp, 127.0.0.1:8001->8001/tcp, 0.0.0.0:8443->8443/tcp, 127.0.0.1:8444->8444/tcp 33 | $ docker ps 34 | ``` 35 | 36 | Kong entities can be configured through the `config/kong.yaml` declarative config 37 | file. Its format is further described [here][kong-docs-dbless-file]. 38 | 39 | You can also run Kong with a backing Postgres database: 40 | 41 | ```shell 42 | $ KONG_DATABASE=postgres docker compose --profile database up -d 43 | 44 | ``` 45 | 46 | Which will result in two Docker containers running -- one for Kong itself, and 47 | another for the Postgres instance it uses to store its configuration entities: 48 | 49 | ```shell 50 | $ docker compose ps 51 | NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS 52 | compose-db-1 postgres:9.5 "docker-entrypoint.s…" db About a minute ago Up About a minute (healthy) 5432/tcp 53 | compose-kong-1 kong:latest "/docker-entrypoint.…" kong About a minute ago Up About a minute (healthy) 0.0.0.0:8000->8000/tcp, 127.0.0.1:8001->8001/tcp, 0.0.0.0:8443->8443/tcp, 127.0.0.1:8444->8444/tcp 54 | ``` 55 | 56 | Kong will be available on port `8000` and `8001`. You can customize the template 57 | with your own environment variables or datastore configuration. 58 | 59 | ## Issues 60 | 61 | If you have any problems with or questions about this image, please contact us 62 | through a [GitHub issue][github-new-issue]. 63 | 64 | ## Contributing 65 | 66 | You are invited to contribute new features, fixes, or updates, large or small; 67 | we are always thrilled to receive pull requests, and do our best to process them 68 | as fast as we can. 69 | 70 | Before you start to code, we recommend discussing your plans through a [GitHub 71 | issue][github-new-issue], especially for more ambitious contributions. This 72 | gives other contributors a chance to point you in the right direction, give you 73 | feedback on your design, and help you find out if someone else is working on the 74 | same thing. 75 | 76 | [kong-docs-url]: https://docs.konghq.com/ 77 | [kong-docs-dbless]: https://docs.konghq.com/gateway/latest/production/deployment-topologies/db-less-and-declarative-config/#main 78 | [kong-docs-dbless-file]: https://docs.konghq.com/gateway/latest/production/deployment-topologies/db-less-and-declarative-config/#declarative-configuration-format 79 | [kong-docker-url]: https://hub.docker.com/_/kong 80 | [github-new-issue]: https://github.com/Kong/docker-kong/issues/new 81 | -------------------------------------------------------------------------------- /compose/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.9' 2 | 3 | x-kong-config: 4 | &kong-env 5 | KONG_DATABASE: ${KONG_DATABASE:-off} 6 | KONG_PG_DATABASE: ${KONG_PG_DATABASE:-kong} 7 | KONG_PG_HOST: db 8 | KONG_PG_USER: ${KONG_PG_USER:-kong} 9 | KONG_PG_PASSWORD_FILE: /run/secrets/kong_postgres_password 10 | 11 | volumes: 12 | kong_data: {} 13 | kong_prefix_vol: 14 | driver_opts: 15 | type: tmpfs 16 | device: tmpfs 17 | kong_tmp_vol: 18 | driver_opts: 19 | type: tmpfs 20 | device: tmpfs 21 | 22 | networks: 23 | kong-net: 24 | external: false 25 | 26 | services: 27 | kong-migrations: 28 | image: "${KONG_DOCKER_TAG:-kong:latest}" 29 | command: kong migrations bootstrap 30 | profiles: [ "database" ] 31 | depends_on: 32 | - db 33 | environment: 34 | <<: *kong-env 35 | secrets: 36 | - kong_postgres_password 37 | networks: 38 | - kong-net 39 | restart: on-failure 40 | 41 | kong-migrations-up: 42 | image: "${KONG_DOCKER_TAG:-kong:latest}" 43 | command: kong migrations up && kong migrations finish 44 | profiles: [ "database" ] 45 | depends_on: 46 | - db 47 | environment: 48 | <<: *kong-env 49 | secrets: 50 | - kong_postgres_password 51 | networks: 52 | - kong-net 53 | restart: on-failure 54 | 55 | kong: 56 | image: "${KONG_DOCKER_TAG:-kong:latest}" 57 | user: "${KONG_USER:-kong}" 58 | environment: 59 | <<: *kong-env 60 | KONG_ADMIN_ACCESS_LOG: /dev/stdout 61 | KONG_ADMIN_ERROR_LOG: /dev/stderr 62 | KONG_PROXY_LISTEN: "${KONG_PROXY_LISTEN:-0.0.0.0:8000}" 63 | KONG_ADMIN_LISTEN: "${KONG_ADMIN_LISTEN:-0.0.0.0:8001}" 64 | KONG_ADMIN_GUI_LISTEN: "${KONG_ADMIN_GUI_LISTEN:-0.0.0.0:8002}" 65 | KONG_PROXY_ACCESS_LOG: /dev/stdout 66 | KONG_PROXY_ERROR_LOG: /dev/stderr 67 | KONG_PREFIX: ${KONG_PREFIX:-/var/run/kong} 68 | KONG_DECLARATIVE_CONFIG: "/opt/kong/kong.yaml" 69 | secrets: 70 | - kong_postgres_password 71 | networks: 72 | - kong-net 73 | ports: 74 | # The following two environment variables default to an insecure value (0.0.0.0) 75 | # according to the CIS Security test. 76 | - "${KONG_INBOUND_PROXY_LISTEN:-0.0.0.0}:8000:8000/tcp" 77 | - "${KONG_INBOUND_SSL_PROXY_LISTEN:-0.0.0.0}:8443:8443/tcp" 78 | # Making them mandatory but undefined, like so would be backwards-breaking: 79 | # - "${KONG_INBOUND_PROXY_LISTEN?Missing inbound proxy host}:8000:8000/tcp" 80 | # - "${KONG_INBOUND_SSL_PROXY_LISTEN?Missing inbound proxy ssl host}:8443:8443/tcp" 81 | # Alternative is deactivating check 5.13 in the security bench, if we consider Kong's own config to be enough security here 82 | 83 | - "8001:8001/tcp" 84 | - "8444:8444/tcp" 85 | - "8002:8002/tcp" 86 | healthcheck: 87 | test: [ "CMD", "kong", "health" ] 88 | interval: 10s 89 | timeout: 10s 90 | retries: 10 91 | restart: on-failure:5 92 | read_only: true 93 | volumes: 94 | - kong_prefix_vol:${KONG_PREFIX:-/var/run/kong} 95 | - kong_tmp_vol:/tmp 96 | - ./config:/opt/kong 97 | security_opt: 98 | - no-new-privileges 99 | 100 | db: 101 | image: postgres:9.5 102 | profiles: [ "database" ] 103 | environment: 104 | POSTGRES_DB: ${KONG_PG_DATABASE:-kong} 105 | POSTGRES_USER: ${KONG_PG_USER:-kong} 106 | POSTGRES_PASSWORD_FILE: /run/secrets/kong_postgres_password 107 | secrets: 108 | - kong_postgres_password 109 | healthcheck: 110 | test: 111 | [ 112 | "CMD", 113 | "pg_isready", 114 | "-d", 115 | "${KONG_PG_DATABASE:-kong}", 116 | "-U", 117 | "${KONG_PG_USER:-kong}" 118 | ] 119 | interval: 30s 120 | timeout: 30s 121 | retries: 3 122 | restart: on-failure 123 | stdin_open: true 124 | tty: true 125 | networks: 126 | - kong-net 127 | volumes: 128 | - kong_data:/var/lib/postgresql/data 129 | 130 | secrets: 131 | kong_postgres_password: 132 | file: ./POSTGRES_PASSWORD 133 | -------------------------------------------------------------------------------- /compose/docker-compose.yml-e: -------------------------------------------------------------------------------- 1 | version: '3.9' 2 | 3 | x-kong-config: 4 | &kong-env 5 | KONG_DATABASE: ${KONG_DATABASE:-off} 6 | KONG_PG_DATABASE: ${KONG_PG_DATABASE:-kong} 7 | KONG_PG_HOST: db 8 | KONG_PG_USER: ${KONG_PG_USER:-kong} 9 | KONG_PG_PASSWORD_FILE: /run/secrets/kong_postgres_password 10 | 11 | volumes: 12 | kong_data: {} 13 | kong_prefix_vol: 14 | driver_opts: 15 | type: tmpfs 16 | device: tmpfs 17 | kong_tmp_vol: 18 | driver_opts: 19 | type: tmpfs 20 | device: tmpfs 21 | 22 | networks: 23 | kong-net: 24 | external: false 25 | 26 | services: 27 | kong-migrations: 28 | image: "${KONG_DOCKER_TAG:-kong:latest}" 29 | command: kong migrations bootstrap 30 | profiles: [ "database" ] 31 | depends_on: 32 | - db 33 | environment: 34 | <<: *kong-env 35 | secrets: 36 | - kong_postgres_password 37 | networks: 38 | - kong-net 39 | restart: on-failure 40 | 41 | kong-migrations-up: 42 | image: "${KONG_DOCKER_TAG:-kong:latest}" 43 | command: kong migrations up && kong migrations finish 44 | profiles: [ "database" ] 45 | depends_on: 46 | - db 47 | environment: 48 | <<: *kong-env 49 | secrets: 50 | - kong_postgres_password 51 | networks: 52 | - kong-net 53 | restart: on-failure 54 | 55 | kong: 56 | image: "${KONG_DOCKER_TAG:-kong:latest}" 57 | user: "${KONG_USER:-kong}" 58 | environment: 59 | <<: *kong-env 60 | KONG_ADMIN_ACCESS_LOG: /dev/stdout 61 | KONG_ADMIN_ERROR_LOG: /dev/stderr 62 | KONG_PROXY_LISTEN: "${KONG_PROXY_LISTEN:-0.0.0.0:8000}" 63 | KONG_ADMIN_LISTEN: "${KONG_ADMIN_LISTEN:-0.0.0.0:8001}" 64 | KONG_ADMIN_GUI_LISTEN: "${KONG_ADMIN_GUI_LISTEN:-0.0.0.0:8002}" 65 | KONG_PROXY_ACCESS_LOG: /dev/stdout 66 | KONG_PROXY_ERROR_LOG: /dev/stderr 67 | KONG_PREFIX: ${KONG_PREFIX:-/var/run/kong} 68 | KONG_DECLARATIVE_CONFIG: "/opt/kong/kong.yaml" 69 | secrets: 70 | - kong_postgres_password 71 | networks: 72 | - kong-net 73 | ports: 74 | # The following two environment variables default to an insecure value (0.0.0.0) 75 | # according to the CIS Security test. 76 | - "${KONG_INBOUND_PROXY_LISTEN:-0.0.0.0}:8000:8000/tcp" 77 | - "${KONG_INBOUND_SSL_PROXY_LISTEN:-0.0.0.0}:8443:8443/tcp" 78 | # Making them mandatory but undefined, like so would be backwards-breaking: 79 | # - "${KONG_INBOUND_PROXY_LISTEN?Missing inbound proxy host}:8000:8000/tcp" 80 | # - "${KONG_INBOUND_SSL_PROXY_LISTEN?Missing inbound proxy ssl host}:8443:8443/tcp" 81 | # Alternative is deactivating check 5.13 in the security bench, if we consider Kong's own config to be enough security here 82 | 83 | - "8001:8001/tcp" 84 | - "8444:8444/tcp" 85 | - "8002:8002/tcp" 86 | healthcheck: 87 | test: [ "CMD", "kong", "health" ] 88 | interval: 10s 89 | timeout: 10s 90 | retries: 10 91 | restart: on-failure:5 92 | read_only: true 93 | volumes: 94 | - kong_prefix_vol:${KONG_PREFIX:-/var/run/kong} 95 | - kong_tmp_vol:/tmp 96 | - ./config:/opt/kong 97 | security_opt: 98 | - no-new-privileges 99 | 100 | db: 101 | image: postgres:9.5 102 | profiles: [ "database" ] 103 | environment: 104 | POSTGRES_DB: ${KONG_PG_DATABASE:-kong} 105 | POSTGRES_USER: ${KONG_PG_USER:-kong} 106 | POSTGRES_PASSWORD_FILE: /run/secrets/kong_postgres_password 107 | secrets: 108 | - kong_postgres_password 109 | healthcheck: 110 | test: 111 | [ 112 | "CMD", 113 | "pg_isready", 114 | "-d", 115 | "${KONG_PG_DATABASE:-kong}", 116 | "-U", 117 | "${KONG_PG_USER:-kong}" 118 | ] 119 | interval: 30s 120 | timeout: 30s 121 | retries: 3 122 | restart: on-failure 123 | stdin_open: true 124 | tty: true 125 | networks: 126 | - kong-net 127 | volumes: 128 | - kong_data:/var/lib/postgresql/data 129 | 130 | secrets: 131 | kong_postgres_password: 132 | file: ./POSTGRES_PASSWORD 133 | -------------------------------------------------------------------------------- /tests/01-image.test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | function run_test { 4 | tinitialize "Docker-Kong test suite" "${BASH_SOURCE[0]}" 5 | 6 | # detect which type of image we're building 7 | # 1) less than 3.0, /Dockerfile or 8 | # 2) greater than 3.0, Dockerfile. 9 | # 10 | # ideally there's smarter logic, but right now, the logic containing the 11 | # image tag being built and tested are scattered across this and more repos, 12 | # and assume a "kong-" prefix 13 | if [[ -f Dockerfile.$BASE ]]; then 14 | docker run -i --rm -v $PWD/hadolint.yaml:/.config/hadolint.yaml hadolint/hadolint:2.7.0 < Dockerfile.$BASE 15 | fi 16 | 17 | if [[ -f $BASE/Dockerfile ]]; then 18 | docker run -i --rm -v $PWD/hadolint.yaml:/.config/hadolint.yaml hadolint/hadolint:2.7.0 < $BASE/Dockerfile 19 | fi 20 | 21 | # set KONG_DOCKER_TAG to kong-$BASE (if not already set) 22 | export KONG_DOCKER_TAG="${KONG_DOCKER_TAG:-kong-$BASE}" 23 | 24 | if [[ ! -z "${SNYK_SCAN_TOKEN}" ]]; then 25 | docker scan --accept-license --login --token "${SNYK_SCAN_TOKEN}" 26 | docker scan --accept-license --exclude-base --severity=high --file $BASE/Dockerfile kong-$BASE 27 | fi 28 | 29 | # Test the proper version was buid 30 | tchapter "test $BASE image" 31 | ttest "the proper version was build" 32 | 33 | if [[ -f Dockerfile.$BASE ]]; then 34 | version_given="$(grep 'ARG KONG_VERSION' Dockerfile.$BASE | awk -F "=" '{print $2}')" 35 | fi 36 | 37 | if [[ -f $BASE/Dockerfile ]]; then 38 | version_given="$(grep 'ARG KONG_VERSION' $BASE/Dockerfile | awk -F "=" '{print $2}')" 39 | fi 40 | 41 | version_built="$(docker run -i --rm kong-$BASE kong version | tr -d '[:space:]')" 42 | 43 | if [[ "$version_given" != "$version_built" ]]; then 44 | echo "Kong version mismatch:"; 45 | echo "\tVersion given is $version_given"; 46 | echo "\tVersion built is $version_built"; 47 | tfailure 48 | else 49 | tsuccess 50 | fi 51 | 52 | ttest "Dbless Test" 53 | 54 | function retry_health() { 55 | # 40 retries at 3 secs each = 120 seconds = 2 mins 56 | local retry=0 retries=40 57 | 58 | until docker ps -f health=healthy | grep -q "${KONG_DOCKER_TAG}"; do 59 | if [ $retry -ge $retries ]; then 60 | echo 61 | return 2 62 | fi 63 | echo -n '.' 64 | sleep 3 65 | retry=$(( retry + 1 )) 66 | done 67 | echo 68 | } 69 | 70 | pushd compose 71 | docker compose up -d 72 | retry_health 73 | 74 | curl -I localhost:8001 | grep -E '(openresty|kong)' 75 | if [ $? -eq 0 ]; then 76 | tsuccess 77 | else 78 | tfailure 79 | fi 80 | 81 | docker compose kill 82 | docker compose rm -f 83 | sleep 5 84 | docker volume prune -f 85 | popd 86 | 87 | ttest "Upgrade Test" 88 | 89 | export COMPOSE_PROFILES=database 90 | export KONG_DATABASE=postgres 91 | pushd compose 92 | curl -fsSL https://raw.githubusercontent.com/Kong/docker-kong/1.5.0/swarm/docker-compose.yml | KONG_DOCKER_TAG=kong:1.5.0 docker compose -p kong -f - up -d 93 | until docker ps -f health=healthy | grep -q kong:1.5.0; do 94 | curl -fsSL https://raw.githubusercontent.com/Kong/docker-kong/1.5.0/swarm/docker-compose.yml | docker compose -p kong -f - ps 95 | docker ps 96 | sleep 15 97 | curl -fsSL https://raw.githubusercontent.com/Kong/docker-kong/1.5.0/swarm/docker-compose.yml | KONG_DOCKER_TAG=kong:1.5.0 docker compose -p kong -f - up -d 98 | done 99 | curl -I localhost:8001 | grep 'Server: openresty' 100 | sed -i -e 's/127.0.0.1://g' docker-compose.yml 101 | 102 | KONG_DOCKER_TAG=${KONG_DOCKER_TAG} docker compose -p kong up -d 103 | until docker ps -f health=healthy | grep -q ${KONG_DOCKER_TAG}; do 104 | docker compose -p kong ps 105 | docker ps 106 | sleep 15 107 | done 108 | 109 | curl -I localhost:8001 | grep -E '(openresty|kong)' 110 | if [ $? -eq 0 ]; then 111 | tsuccess 112 | else 113 | tfailure 114 | fi 115 | 116 | echo "cleanup" 117 | 118 | docker compose -p kong kill 119 | docker compose -p kong rm -f 120 | sleep 5 121 | docker volume prune -f 122 | docker system prune -y 123 | git checkout -- docker-compose.yml 124 | popd 125 | 126 | # Run Kong functional tests 127 | ttest "Kong functional test" 128 | 129 | git clone https://github.com/Kong/kong.git || true 130 | pushd kong 131 | git checkout $version_given || git checkout next 132 | popd 133 | 134 | pushd kong-build-tools 135 | rm -rf test/tests/01-package 136 | docker tag kong-$BASE kong/kong:amd64-test 137 | KONG_TEST_CONTAINER_TAG=test KONG_VERSION=$version_given KONG_TEST_IMAGE_NAME=kong-$BASE RESTY_IMAGE_BASE=$BASE RESTY_IMAGE_TAG=$BASE make test 138 | if [ $? -eq 0 ]; then 139 | tsuccess 140 | else 141 | tfailure 142 | fi 143 | popd 144 | 145 | 146 | tfinish 147 | } 148 | 149 | # No need to modify anything below this comment 150 | 151 | # shellcheck disable=SC1090 # do not follow source 152 | [[ "$T_PROJECT_NAME" == "" ]] && set -e && if [[ -f "${1:-$(dirname "$(realpath "$0")")/test.sh}" ]]; then source "${1:-$(dirname "$(realpath "$0")")/test.sh}"; else source "${1:-$(dirname "$(realpath "$0")")/run.sh}"; fi && set +e 153 | run_test 154 | -------------------------------------------------------------------------------- /submit.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | gawk --version &> /dev/null || { 5 | echo "gawk is required to run this script." 6 | exit 1 7 | } 8 | 9 | mode= 10 | version= 11 | force= 12 | 13 | function usage() { 14 | echo "usage: $0 <-p|-m> " 15 | echo " -p for patch release (x.y.Z)" 16 | echo " -m for minor release (x.Y.0)" 17 | echo " -r for release candidate (x.Y.0rcZ)" 18 | echo "example: $0 -p 1.1.2" 19 | } 20 | 21 | while [ "$1" ] 22 | do 23 | case "$1" in 24 | --help) 25 | usage 26 | exit 0 27 | ;; 28 | -p) 29 | mode=patch 30 | ;; 31 | -r) 32 | mode=rc 33 | ;; 34 | -m) 35 | mode=minor 36 | ;; 37 | -f) 38 | force=yes 39 | ;; 40 | [0-9]*) 41 | version=$1 42 | ;; 43 | esac 44 | shift 45 | done 46 | 47 | function red() { 48 | echo -e "\033[1;31m$@\033[0m" 49 | } 50 | 51 | function die() { 52 | red "*** $@" 53 | echo "See also: $0 --help" 54 | echo 55 | exit 1 56 | } 57 | 58 | hub --version &> /dev/null || die "hub is not in PATH. Get it from https://github.com/github/hub" 59 | 60 | if [ "$mode" = "" ] 61 | then 62 | die "Error: mode flag is mandatory" 63 | fi 64 | 65 | if ! [ "$version" ] 66 | then 67 | die "Error: missing version" 68 | fi 69 | 70 | git checkout master 71 | git pull 72 | 73 | if ! grep -q "$version" Dockerfile.deb 74 | then 75 | if [[ "$force" = "yes" ]] 76 | then 77 | echo "Forcing to use the tag even though it is not in master." 78 | 79 | git checkout "$version" 80 | 81 | if ! grep -q "$version$" Dockerfile.deb 82 | then 83 | die "Error: version in build script doesn't match required version." 84 | fi 85 | else 86 | echo "****************************************" 87 | echo "Error: this script should be run only after the" 88 | echo "desired release is merged in master of docker-kong." 89 | echo "" 90 | echo "For making releases based on old versions," 91 | echo "Use -f to override and submit from the tag anyway." 92 | echo "****************************************" 93 | die "Failed." 94 | fi 95 | fi 96 | 97 | xy=${version%.*} 98 | z=${version#$xy.} 99 | 100 | rc=0 101 | if [ "$mode" = "rc" ] 102 | then 103 | rc=${version#*rc} 104 | z=${z%rc*} 105 | fi 106 | 107 | commit=$(git show "$version" | grep "^commit" | head -n 1 | cut -b8-48) 108 | 109 | if [ "$mode" = "patch" ] 110 | then 111 | prev="$xy.$[z-1]" 112 | prevcommit=$(git show "$prev" | grep "^commit" | head -n 1 | cut -b8-48) 113 | elif [ "$mode" = "rc" -a "$rc" -gt 1 ] 114 | then 115 | prev="$xy.${z}rc$[rc-1]" 116 | prevcommit=$(git show "$prev" | grep "^commit" | head -n 1 | cut -b8-48) 117 | fi 118 | 119 | rm -rf submit 120 | mkdir submit 121 | cd submit 122 | git clone https://github.com/kong/official-images 123 | cd official-images 124 | git remote add upstream http://github.com/docker-library/official-images 125 | git fetch upstream 126 | git checkout master 127 | git merge upstream/master 128 | 129 | git checkout -b release/$version 130 | 131 | if [ "$mode" = "patch" ] 132 | then 133 | sed "s|$prev-ubuntu|$version-ubuntu|; 134 | s|$prev,|$version,|; 135 | s|$prevcommit|$commit|; 136 | s|refs/tags/$prev|refs/tags/$version|" library/kong > library/kong.new 137 | mv library/kong.new library/kong 138 | 139 | elif [ "$mode" = "rc" -a "$rc" -gt 1 ] 140 | then 141 | sed "s|$prev-ubuntu|$version-ubuntu|; 142 | s|, ${xy}rc$[rc-1]|, ${xy}rc${rc}|; 143 | s|$prev,|$version,|; 144 | s|$prevcommit|$commit|; 145 | s|refs/tags/$prev|refs/tags/$version|" library/kong > library/kong.new 146 | mv library/kong.new library/kong 147 | 148 | elif [ "$mode" = "rc" -a "$rc" -eq 1 ] 149 | then 150 | gawk ' 151 | BEGIN { 152 | reset = 0 153 | not_yet_first = 1 154 | } 155 | /^Tags/ { 156 | if (not_yet_first == 1) { 157 | not_yet_first = 0 158 | before_first = 1 159 | } 160 | } 161 | { 162 | if (before_first == 1) { 163 | v = "'$version'" 164 | xy = "'$xy'" 165 | commit = "'$commit'" 166 | print "Tags: " v "-ubuntu" 167 | print "GitCommit: " commit 168 | print "GitFetch: refs/tags/" v 169 | print "Directory: ubuntu" 170 | print "Architectures: amd64, arm64v8" 171 | print "" 172 | before_first = 0 173 | } else { 174 | print 175 | } 176 | } 177 | ' library/kong > library/kong.new 178 | mv library/kong.new library/kong 179 | 180 | elif [ "$mode" = "minor" ] 181 | then 182 | gawk ' 183 | BEGIN { 184 | reset = 0 185 | not_yet_first = 1 186 | } 187 | /^Tags/ { 188 | if (not_yet_first == 1) { 189 | not_yet_first = 0 190 | before_first = 1 191 | } 192 | } 193 | /Tags: .*[0-9]rc[0-9].*/ { 194 | in_rc_tag = 1 195 | } 196 | /^ *$/ { 197 | if (in_rc_tag == 1) { 198 | reset = 1 199 | } 200 | } 201 | { 202 | if (before_first == 1) { 203 | v = "'$version'" 204 | xy = "'$xy'" 205 | commit = "'$commit'" 206 | print "Tags: " v "-ubuntu, " xy "-ubuntu, ubuntu" 207 | print "GitCommit: " commit 208 | print "GitFetch: refs/tags/" v 209 | print "Directory: ubuntu" 210 | print "Architectures: amd64, arm64v8" 211 | print "" 212 | before_first = 0 213 | } 214 | if (!(in_rc_tag == 1)) { 215 | gsub(", latest", "") 216 | gsub(", ubuntu", "") 217 | print 218 | } 219 | if (reset == 1) { 220 | in_rc_tag = 0 221 | reset = 0 222 | } 223 | } 224 | ' library/kong > library/kong.new 225 | mv library/kong.new library/kong 226 | fi 227 | 228 | echo "****************************************" 229 | git diff 230 | echo "****************************************" 231 | 232 | echo "Everything looks all right? (y/n)" 233 | echo "(Answering y will commit, push the branch, and submit the PR)" 234 | read 235 | if ! [ "$REPLY" == "y" ] 236 | then 237 | exit 1 238 | fi 239 | 240 | git commit -av -m "kong $version" 241 | git push --set-upstream origin release/$version 242 | 243 | hub pull-request -b docker-library:master -h "release/$version" -m "bump Kong to $version" 244 | -------------------------------------------------------------------------------- /customize/packer.lua: -------------------------------------------------------------------------------- 1 | local split = require("pl.utils").split 2 | local pretty = require("pl.pretty").write 3 | local strip = require("pl.stringx").strip 4 | local lines = require("pl.stringx").splitlines 5 | local _execex = require("pl.utils").executeex 6 | local _exec = require("pl.utils").execute 7 | local directories = require("pl.dir").getdirectories 8 | local writefile = require("pl.utils").writefile 9 | local readfile = require("pl.utils").readfile 10 | local is_dir = require("pl.path").isdir 11 | local is_file = require("pl.path").isfile 12 | 13 | local CUSTOM_TEMPLATE="/custom_nginx.conf" 14 | 15 | io.stdout:setvbuf("no") 16 | io.stderr:setvbuf("no") 17 | 18 | 19 | local function stderr(...) 20 | io.stderr:write(...) 21 | io.stderr:write("\n") 22 | end 23 | 24 | 25 | local function stdout(...) 26 | io.stdout:write(...) 27 | io.stdout:write("\n") 28 | end 29 | 30 | 31 | local function fail(msg) 32 | stderr(msg) 33 | os.exit(1) 34 | end 35 | 36 | 37 | local function header(msg) 38 | local fill1 = math.floor((80 - 2 - #msg)/2) 39 | local fill2 = 80 - 2 - #msg - fill1 40 | stdout( 41 | ("*"):rep(80).."\n".. 42 | "*"..(" "):rep(fill1)..msg..(" "):rep(fill2).."*\n".. 43 | ("*"):rep(80) 44 | ) 45 | end 46 | 47 | 48 | local platforms = { 49 | { 50 | check = "yum --version", -- check for rhel 51 | commands = { -- run before anything else in build container 52 | "yum -y install git", 53 | "yum -y install unzip", 54 | "yum -y install zip", 55 | "yum -y install gcc gcc-c++ make", 56 | }, 57 | }, { 58 | check = "stat /usr/bin/microdnf", -- check for ubi-minimal 59 | commands = { -- run before anything else in build container 60 | "microdnf -y install git", 61 | "microdnf -y install unzip", 62 | "microdnf -y install zip", 63 | "microdnf -y install gcc gcc-c++ make", 64 | }, 65 | }, { 66 | check = "apt -v", -- check for Ubuntu 67 | commands = { -- run before anything else in build container 68 | "apt update", 69 | "apt install -y zip", 70 | "apt install -y wget", 71 | "apt install -y build-essential", 72 | }, 73 | }, 74 | } 75 | 76 | 77 | local execex = function(cmd, ...) 78 | stdout("\027[32m", "[packer exec] ", cmd, "\027[0m") 79 | return _execex(cmd, ...) 80 | end 81 | 82 | 83 | local exec = function(cmd, ...) 84 | stdout("\027[32m", "[packer exec] ", cmd, "\027[0m") 85 | return _exec(cmd, ...) 86 | end 87 | 88 | 89 | local function prep_platform() 90 | for _, platform in ipairs(platforms) do 91 | local ok = exec(platform.check) 92 | if not ok then 93 | stdout(("platform test '%s' was negative"):format(platform.check)) 94 | else 95 | stdout(("platform test '%s' was positive"):format(platform.check)) 96 | for _, cmd in ipairs(platform.commands) do 97 | stdout(cmd) 98 | ok = exec(cmd) 99 | if not ok then 100 | fail(("failed executing '%s'"):format(cmd)) 101 | end 102 | end 103 | return true 104 | end 105 | end 106 | stderr("WARNING: no platform match!") 107 | end 108 | 109 | 110 | local function is_empty_file(filename) 111 | local t = readfile(filename) 112 | if t then 113 | if t:gsub("\n", ""):gsub("\t", ""):gsub(" ","") == "" then 114 | return true 115 | end 116 | end 117 | return false 118 | end 119 | 120 | 121 | local function get_args() 122 | if not arg or 123 | not arg[1] or 124 | arg[1] == "--" and not arg[2] then 125 | -- no args, but maybe a custom config file? 126 | 127 | if is_empty_file(CUSTOM_TEMPLATE) then 128 | fail("no arguments to parse, commandline: " .. pretty(arg or {})) 129 | else 130 | stdout("no plugins specified, but a custom template exists") 131 | return 132 | end 133 | end 134 | 135 | local list = {} 136 | for i = 1, #arg do 137 | if arg[i] and arg[i] ~= "--" then 138 | local sp = split(arg[i], ",") 139 | for n = 1, #sp do 140 | local rock = strip(sp[n]) 141 | if rock ~= "" then 142 | table.insert(list, rock) 143 | end 144 | end 145 | end 146 | end 147 | 148 | if #list == 0 then 149 | if is_empty_file(CUSTOM_TEMPLATE) then 150 | fail("no arguments to parse, commandline: " .. pretty(arg)) 151 | else 152 | stdout("no plugins specified, but a custom template exists") 153 | end 154 | end 155 | 156 | stdout("rocks to install: " .. pretty(list)) 157 | return list 158 | end 159 | 160 | 161 | local function get_plugins() 162 | local plugins = {} 163 | local cnt = 0 164 | 165 | for i = 1, 2 do 166 | local pattern, paths, extension 167 | if i == 1 then 168 | pattern = "%?%.lua$" 169 | extension = ".lua" 170 | paths = split(package.path, ";") 171 | else 172 | pattern = "%?%.so$" 173 | extension = ".so" 174 | paths = split(package.cpath, ";") 175 | end 176 | 177 | for _, path in ipairs(paths) do 178 | path = path:gsub(pattern, "kong/plugins/") 179 | if is_dir(path) then 180 | for _, dir in ipairs(directories(path)) do 181 | local plugin_name = dir:sub(#path + 1, -1) 182 | if is_file(dir .. "/handler" .. extension) then 183 | plugins[plugin_name] = true 184 | cnt = cnt + 1 185 | end 186 | end 187 | end 188 | end 189 | end 190 | 191 | stdout("Found ", cnt, " plugins installed") 192 | return plugins 193 | end 194 | 195 | 196 | local function get_rocks() 197 | local cmd = "luarocks list --tree=system --porcelain" 198 | local ok, _, sout, serr = execex(cmd) 199 | if not ok then 200 | fail(("failed to retrieve list of installed rocks: '%s' failed with\n%s\n%s"):format( 201 | cmd, sout, serr)) 202 | end 203 | 204 | local rocks = {} 205 | local cnt = 0 206 | for _, rock in ipairs(lines(sout)) do 207 | cnt = cnt + 1 208 | local name, spec = rock:match("^(.-)\t(.-)\t") 209 | local rock_id = name.."-"..spec 210 | rocks[rock_id] = { name = name, spec = spec } 211 | end 212 | stdout("Found ", cnt, " rocks installed") 213 | return rocks 214 | end 215 | 216 | 217 | local function install_plugins(plugins, lr_flag) 218 | local cmd = "luarocks install --tree=system %s " .. lr_flag 219 | for _, rock in ipairs(plugins) do 220 | stdout(cmd:format(rock)) 221 | 222 | local ok = exec(cmd:format(rock)) 223 | if not ok then 224 | fail(("failed installing rock: '%s' failed"):format(cmd:format(rock))) 225 | end 226 | 227 | stdout("installed: "..rock) 228 | exec("luarocks show "..rock) 229 | end 230 | end 231 | 232 | 233 | local function check_custom_template() 234 | if is_empty_file(CUSTOM_TEMPLATE) then 235 | -- it's the empty_file, delete it 236 | os.remove(CUSTOM_TEMPLATE) 237 | stdout("No custom template found") 238 | return 239 | end 240 | stdout("Found a custom template") 241 | end 242 | 243 | 244 | local function start_rocks_server() 245 | if is_empty_file("/rocks-server") then 246 | stdout("No custom rocks found, using public luarocks.org as server") 247 | return "" 248 | end 249 | assert(exec("luarocks-admin make_manifest /rocks-server")) 250 | stdout("Local LuaRocks server manifest created") 251 | assert(exec("mkdir /nginx")) 252 | assert(exec("mkdir /nginx/logs")) 253 | assert(writefile("/nginx/nginx.conf", [[ 254 | events { 255 | } 256 | 257 | http { 258 | server { 259 | listen 127.0.0.1:8080; 260 | 261 | location / { 262 | root /rocks-server; 263 | } 264 | } 265 | } 266 | ]])) 267 | assert(exec("touch /nginx/logs/error.log")) 268 | assert(exec("/usr/local/openresty/nginx/sbin/nginx " .. 269 | "-c /nginx/nginx.conf " .. 270 | "-p /nginx")) 271 | stdout("Nginx started as local LuaRocks server") 272 | stdout("List of locally available rocks:") 273 | assert(exec("luarocks search --all --porcelain --only-server=http://localhost:8080")) 274 | return " --only-server=http://localhost:8080 " 275 | end 276 | 277 | 278 | -- ********************************************************** 279 | -- Do the actual work 280 | -- ********************************************************** 281 | header("Set up platform") 282 | prep_platform() 283 | 284 | header("Set up LuaRocks server") 285 | local lr_flag = start_rocks_server() 286 | 287 | header("Get arguments") 288 | local rocks = get_args() 289 | 290 | 291 | header("Get existing rocks") 292 | local pre_installed_rocks = get_rocks() 293 | 294 | 295 | header("Get existing plugin list") 296 | local pre_installed_plugins = get_plugins() 297 | 298 | 299 | header("Getting custom template") 300 | check_custom_template() 301 | 302 | 303 | header("Install the requested plugins") 304 | install_plugins(rocks, lr_flag) 305 | 306 | 307 | header("Get post-install plugin list and get the delta") 308 | local plugins = {} 309 | for plugin_name in pairs(get_plugins()) do 310 | if not pre_installed_plugins[plugin_name] then 311 | table.insert(plugins, plugin_name) 312 | stdout("added plugin: "..plugin_name) 313 | end 314 | end 315 | if not next(plugins) then 316 | stdout("No plugins were added") 317 | end 318 | 319 | 320 | header("Write new entry-point script") 321 | assert(exec("mv /docker-entrypoint.sh /old-entrypoint.sh")) 322 | local entrypoint = [=[ 323 | #!/bin/sh 324 | set -e 325 | 326 | if [ "$KONG_PLUGINS" = "" ]; then 327 | KONG_PLUGINS="bundled" 328 | fi 329 | # replace 'bundled' with the new set, including the custom ones 330 | export KONG_PLUGINS=$(echo ",$KONG_PLUGINS," | sed "s/,bundled,/,bundled%s,/" | sed 's/^,//' | sed 's/,$//') 331 | 332 | # prefix the custom template option, since the last one on the command line 333 | # wins, so the user can still override this template 334 | INITIAL="$1 $2" 335 | if [ -f /custom_nginx.conf ]; then 336 | # only for these commands support "--nginx-conf" 337 | echo 1: $INITIAL 338 | if [ "$INITIAL" = "kong prepare" ] || \ 339 | [ "$INITIAL" = "kong reload" ] || \ 340 | [ "$INITIAL" = "kong restart" ] || \ 341 | [ "$INITIAL" = "kong start" ] ; then 342 | INITIAL="$1 $2 --nginx-conf=/custom_nginx.conf" 343 | fi 344 | fi 345 | # shift 1 by 1; if there is only 1 arg, then "shift 2" fails 346 | if [ ! "$1" = "" ]; then 347 | shift 348 | fi 349 | if [ ! "$1" = "" ]; then 350 | shift 351 | fi 352 | 353 | exec /old-entrypoint.sh $INITIAL "$@" 354 | ]=] 355 | local plugin_list = "," .. table.concat(plugins, ",") 356 | if plugin_list == "," then 357 | -- no plugins added 358 | plugin_list = "" 359 | end 360 | entrypoint = entrypoint:format(plugin_list) 361 | assert(writefile("/docker-entrypoint.sh", entrypoint)) 362 | assert(exec("chmod +x /docker-entrypoint.sh")) 363 | stdout(entrypoint) 364 | 365 | 366 | header("Completed building plugins, rocks and/or template") 367 | 368 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright 2016-2018 Kong Inc. 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /tests/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [ -n "${DEBUG:-}" ]; then 4 | set -x 5 | fi 6 | 7 | # source: https://github.com/Tieske/test.sh 8 | 9 | if [[ "$T_INIT_COUNT" == "" ]]; then 10 | # first time, initialize global variables 11 | T_PROJECT_NAME="" 12 | T_FILE_NAME="" 13 | T_COUNT_FAILURE=0 14 | T_COUNT_SUCCESS=0 15 | T_CURRENT_CHAPTER="" 16 | T_CHAPTER_START_FAILURES=0 17 | T_CHAPTER_START_SUCCESSES=0 18 | T_CURRENT_TEST="" 19 | T_COLOR_YELLOW="\033[1;33m" 20 | T_COLOR_RED="\033[0;31m" 21 | T_COLOR_GREEN="\033[1;32m" 22 | T_COLOR_CLEAR="\033[0m" 23 | T_INIT_COUNT=0 24 | T_FAILURE_ARRAY=() 25 | T_DEBUGGING="" 26 | 27 | figlet -v > /dev/null 2>&1 28 | T_FIGLET_AVAILABLE=$? 29 | else 30 | # assuming we're being sourced again, just exit 31 | return 0 32 | fi 33 | 34 | 35 | function texit { 36 | # internal function only 37 | unset T_PROJECT_NAME 38 | unset T_FILE_NAME 39 | unset T_COUNT_FAILURE 40 | unset T_COUNT_SUCCESS 41 | unset T_CURRENT_CHAPTER 42 | unset T_CHAPTER_START_FAILURES 43 | unset T_CHAPTER_START_SUCCESSES 44 | unset T_CURRENT_TEST 45 | unset T_COLOR_YELLOW 46 | unset T_COLOR_RED 47 | unset T_COLOR_GREEN 48 | unset T_COLOR_CLEAR 49 | unset T_INIT_COUNT 50 | unset T_FAILURE_ARRAY 51 | unset T_FIGLET_AVAILABLE 52 | unset T_DEBUGGING 53 | exit "$1" 54 | } 55 | 56 | 57 | function tfooter { 58 | # internal function only 59 | # Arguments: 60 | # 1) successes 61 | # 2) failures 62 | # 3) [optional] boolean; if set Project title, otherwise Chapter title 63 | local indent="" 64 | if [[ "$3" == "" ]]; then 65 | indent=" " 66 | local chapter 67 | if [[ "$T_FILE_NAME" == "" ]]; then 68 | chapter=$T_CURRENT_CHAPTER 69 | else 70 | chapter="$T_CURRENT_CHAPTER ($T_FILE_NAME)" 71 | fi 72 | echo "------------------------------------------------------------------------------------------------------------------------" 73 | echo -e "$T_COLOR_YELLOW$indent""Chapter : $chapter$T_COLOR_CLEAR" 74 | else 75 | echo "========================================================================================================================" 76 | echo -e "$T_COLOR_YELLOW$indent""Project : $T_PROJECT_NAME$T_COLOR_CLEAR" 77 | fi 78 | echo -e "$T_COLOR_YELLOW$indent""Successes: $1$T_COLOR_CLEAR" 79 | echo -e "$T_COLOR_YELLOW$indent""Failures : $2$T_COLOR_CLEAR" 80 | } 81 | 82 | 83 | function theader { 84 | # internal function only 85 | local header=$1 86 | echo "========================================================================================================================" 87 | if [ $T_FIGLET_AVAILABLE -eq 0 ]; then 88 | figlet -c -w 120 "$header" 89 | else 90 | printf "%*s\n" $(( (${#header} + 120) / 2)) "$header" 91 | fi 92 | echo "========================================================================================================================" 93 | } 94 | 95 | 96 | function tmessage { 97 | echo -e "$T_COLOR_YELLOW$T_PROJECT_NAME [ info ] $*$T_COLOR_CLEAR" 98 | } 99 | 100 | 101 | function tdebug { 102 | if [[ "$T_CURRENT_TEST" == "" ]]; then 103 | echo "calling tdebug without a test, call ttest first" 104 | exit 1 105 | fi 106 | T_DEBUGGING=true 107 | set -x 108 | } 109 | 110 | 111 | function tinitialize { 112 | # Initializes either a test suite or a single test file. Every tinitialize 113 | # MUST be followed by a tfinish, after the tests are completed. 114 | # Arguments: 115 | # 1) [required] name of the test suite (ignored if already set) 116 | # 2) [optional] filename of the testfile 117 | if [[ ! "$T_CURRENT_CHAPTER" == "" ]]; then 118 | echo "calling tinitialize after testing already started" 119 | exit 1 120 | fi 121 | if [[ "$1" == "" ]]; then 122 | echo "calling tinitialize without project name" 123 | exit 1 124 | fi 125 | 126 | if [[ $T_INIT_COUNT -eq 0 ]]; then 127 | # first time we're being initialized 128 | T_PROJECT_NAME=$1 129 | theader "$T_PROJECT_NAME" 130 | ((T_INIT_COUNT = T_INIT_COUNT + 1)) 131 | else 132 | # we're being called multiple times, because multiple files run in a row 133 | # do not intialize again, just update the counter 134 | ((T_INIT_COUNT = T_INIT_COUNT + 1)) 135 | fi 136 | T_FILE_NAME=$2 137 | } 138 | 139 | 140 | function tchapter { 141 | # Initializes a test chapter. 142 | # Call after tinitialize, and before ttest. 143 | if [[ ! "$T_CURRENT_TEST" == "" ]]; then 144 | echo "calling tchapter while test is unfinished, call tfailure or tsuccess first" 145 | exit 1 146 | fi 147 | if [[ "$1" == "" ]]; then 148 | echo "calling tchapter without chapter name" 149 | exit 1 150 | fi 151 | 152 | if [[ ! "$T_CURRENT_CHAPTER" == "" ]]; then 153 | tfooter $((T_COUNT_SUCCESS - T_CHAPTER_START_SUCCESSES)) $((T_COUNT_FAILURE - T_CHAPTER_START_FAILURES)) 154 | fi 155 | 156 | T_CURRENT_CHAPTER="$*" 157 | T_CHAPTER_START_FAILURES=$T_COUNT_FAILURE 158 | T_CHAPTER_START_SUCCESSES=$T_COUNT_SUCCESS 159 | 160 | theader "$T_CURRENT_CHAPTER" 161 | } 162 | 163 | 164 | function ttest { 165 | # Marks the start of a test. 166 | # The test MUST be finished with either tsuccess or tfailure. 167 | # Arguments: 168 | # 1) name of the test 169 | if [[ "$T_CURRENT_CHAPTER" == "" ]]; then 170 | echo "calling ttest without chapter, call tchapter first" 171 | exit 1 172 | fi 173 | if [[ "$1" == "" ]]; then 174 | echo "calling ttest without test description" 175 | exit 1 176 | fi 177 | T_CURRENT_TEST="$*" 178 | echo -e "$T_COLOR_YELLOW$T_PROJECT_NAME [ start ] $T_CURRENT_CHAPTER: $T_CURRENT_TEST$T_COLOR_CLEAR" 179 | } 180 | 181 | 182 | function tfailure { 183 | # Marks the end of a test, with a failure. 184 | # no arguments 185 | if [[ "$T_DEBUGGING" == "true" ]]; then set +x; T_DEBUGGING=""; fi 186 | if [[ "$T_CURRENT_TEST" == "" ]]; then 187 | echo "calling tfailure without a test, call ttest first" 188 | exit 1 189 | fi 190 | [[ ! "$1" == "" ]] && tmessage "$*" 191 | local failure="$T_CURRENT_CHAPTER: $T_CURRENT_TEST" 192 | echo -e "$T_COLOR_YELLOW$T_PROJECT_NAME$T_COLOR_RED [ failed ]$T_COLOR_YELLOW $failure$T_COLOR_CLEAR" 193 | 194 | if [[ ! $T_FILE_NAME == "" ]]; then 195 | failure="$failure ($T_FILE_NAME)" 196 | fi 197 | 198 | T_FAILURE_ARRAY+=("$failure") 199 | 200 | ((T_COUNT_FAILURE = T_COUNT_FAILURE + 1)) 201 | T_CURRENT_TEST="" 202 | } 203 | 204 | 205 | function tsuccess { 206 | # Marks the end of a test, as a success. 207 | # no arguments 208 | if [[ "$T_DEBUGGING" == "true" ]]; then set +x; T_DEBUGGING=""; fi 209 | if [[ "$T_CURRENT_TEST" == "" ]]; then 210 | echo "calling tsuccess without a test, call ttest first" 211 | exit 1 212 | fi 213 | [[ ! "$1" == "" ]] && tmessage "$*" 214 | echo -e "$T_COLOR_YELLOW$T_PROJECT_NAME$T_COLOR_GREEN [ success ]$T_COLOR_YELLOW $T_CURRENT_CHAPTER: $T_CURRENT_TEST$T_COLOR_CLEAR" 215 | ((T_COUNT_SUCCESS = T_COUNT_SUCCESS + 1)) 216 | T_CURRENT_TEST="" 217 | } 218 | 219 | 220 | function tfinish { 221 | # Finishes either a test suite or a single test file. 222 | # no arguments 223 | if [[ ! "$T_CURRENT_TEST" == "" ]]; then 224 | echo "calling tfinish while test is unfinished, call tfailure or tsuccess first" 225 | exit 1 226 | fi 227 | 228 | if [[ ! "$T_CURRENT_CHAPTER" == "" ]]; then 229 | tfooter $((T_COUNT_SUCCESS - T_CHAPTER_START_SUCCESSES)) $((T_COUNT_FAILURE - T_CHAPTER_START_FAILURES)) 230 | T_CURRENT_CHAPTER="" 231 | fi 232 | 233 | ((T_INIT_COUNT = T_INIT_COUNT - 1)) 234 | if [[ $T_INIT_COUNT -eq 0 ]]; then 235 | # this was the last testfile running, so actually wrap it up 236 | tfooter $((T_COUNT_SUCCESS)) $((T_COUNT_FAILURE)) Project 237 | local failure 238 | for failure in "${T_FAILURE_ARRAY[@]}"; do 239 | echo -e "$T_COLOR_YELLOW $failure$T_COLOR_CLEAR" 240 | done 241 | 242 | if [ "$T_COUNT_FAILURE" -eq 0 ] && [ "$T_COUNT_SUCCESS" -gt 0 ]; then 243 | if [ $T_FIGLET_AVAILABLE -eq 0 ]; then 244 | # split in lines and colorize each individually for CI 245 | figlet -c -w 120 "Success!" | while IFS= read -r line; do echo -e "$T_COLOR_GREEN$line $T_COLOR_CLEAR"; done 246 | else 247 | echo -e "$T_COLOR_GREEN Overall succes!$T_COLOR_CLEAR" 248 | fi 249 | texit 0 250 | else 251 | if [ $T_FIGLET_AVAILABLE -eq 0 ]; then 252 | # split in lines and colorize each individually for CI 253 | figlet -c -w 120 "Failed!" | while IFS= read -r line; do echo -e "$T_COLOR_RED$line $T_COLOR_CLEAR"; done 254 | else 255 | echo -e "$T_COLOR_RED Overall failed!$T_COLOR_CLEAR" 256 | fi 257 | texit 1 258 | fi 259 | else 260 | # we've finished a file, but not the last one yet. 261 | T_FILE_NAME="" 262 | fi 263 | } 264 | 265 | 266 | function tcreate { 267 | # Creates a new testfile from template. 268 | # Arguments: 269 | # 1) filename of the new testfile (.test.sh extension auto-appended) 270 | # 2) test suite name 271 | if [ "$1" == "" ]; then 272 | echo "first argument missing: filename to create" 273 | texit 1 274 | elif [ "$2" == "" ]; then 275 | echo "second argument missing: test suite name" 276 | texit 1 277 | elif [ ! "$3" == "" ]; then 278 | echo "too many arguments" 279 | texit 1 280 | fi 281 | 282 | local FILENAME="$1" 283 | if [[ "$FILENAME" != *.test.sh ]]; then 284 | FILENAME=$FILENAME.test.sh 285 | fi 286 | 287 | if [ -f "$FILENAME" ]; then 288 | echo "file already exists: $FILENAME" 289 | texit 1 290 | fi 291 | 292 | cat < "$FILENAME" 293 | #!/usr/bin/env bash 294 | 295 | : ' 296 | There is one dependency; "test.sh", the "figlet" utility is optional. 297 | 298 | Usage test.sh: 299 | 1: ./test.sh [--suite ] [files/dirs...] 300 | 2: ./test.sh --create 301 | 302 | 1: Runs tests. When "files/dirs" is not provided, it will run all "*.test.sh" files 303 | located in the same directory as "test.sh". The suite name defaults to "unknown 304 | test suite". 305 | 306 | 2: Creates a new template test file 307 | 308 | Usage test files: 309 | ./this.test.sh [path-to-test.sh] 310 | 311 | When "path-to-test.sh" is not provided it defaults to the same directory where 312 | the test file is located. 313 | 314 | Assuming "test.sh" is in the same directory as this file: 315 | 316 | /some/path/this.test.sh # runs only this file 317 | /some/path/test.sh # runs all "/some/path/*.test.sh" files 318 | /some/path/test.sh this.test.sh that.test.sh # runs "this.test.sh" and "that.test.sh" files 319 | 320 | When not in the same directory 321 | 322 | /some/path/this.test.sh other/path/test.sh # runs only this file 323 | /other/path/test.sh /some/path/this.test.sh # runs only this file 324 | 325 | 326 | The test themselves are located below this comment in the "run_test" function 327 | ' 328 | 329 | function run_test { 330 | # the suite name below will only be used when running this file directly, when 331 | # running through "test.sh" it must be provided using the "--suite" option. 332 | tinitialize "$2" "\${BASH_SOURCE[0]}" 333 | 334 | tchapter "great tests" 335 | 336 | ttest "ensures the file exists" 337 | tdebug # this enables 'set -x' until the first tfailure or tsuccess call 338 | if [ ! -f "some/local/file" ]; then 339 | tmessage "The file did not exist" 340 | tfailure 341 | else 342 | tmessage "The file was found" 343 | tsuccess 344 | fi 345 | 346 | tchapter "awesome tests" 347 | 348 | ttest "ensures the file does NOT exist" 349 | if [ ! -f "some/local/file" ]; then 350 | tsuccess "a success message" 351 | else 352 | tfailure "a failure message" 353 | fi 354 | 355 | tfinish 356 | } 357 | 358 | # No need to modify anything below this comment 359 | 360 | # shellcheck disable=SC1090 # do not follow source 361 | [[ "\$T_PROJECT_NAME" == "" ]] && set -e && if [[ -f "\${1:-\$(dirname "\$(realpath "\$0")")/test.sh}" ]]; then source "\${1:-\$(dirname "\$(realpath "\$0")")/test.sh}"; else source "\${1:-\$(dirname "\$(realpath "\$0")")/run.sh}"; fi && set +e 362 | run_test 363 | EOF 364 | 365 | if [ ! $? -eq 0 ]; then 366 | echo "failed to write file $FILENAME" 367 | texit 1 368 | fi 369 | chmod +x "$FILENAME" 370 | #bash ./test.sh "$FILENAME" 371 | 372 | echo "Successfully created a new test file: $FILENAME" 373 | echo "Instructions are in the file." 374 | texit 0 375 | } 376 | 377 | 378 | function main { 379 | # usage: test.sh [--suite ] [filenames...] 380 | # if no filenames given then will execute all "*.test.sh" files in the 381 | # same directory 382 | local FILE_LIST=() 383 | local FILENAME 384 | local SUITE_NAME 385 | 386 | if [[ "$1" == "--create" ]]; then 387 | shift 388 | tcreate "$@" 389 | texit 0 390 | elif [[ "$1" == "--suite" ]]; then 391 | shift 392 | SUITE_NAME=$1 393 | shift 394 | else 395 | SUITE_NAME="unknown test suite" 396 | fi 397 | 398 | if [[ $# -gt 0 ]]; then 399 | # filenames passed; only execute filenames passed in 400 | while [[ $# -gt 0 ]]; do 401 | if [ ! -f "$1" ] ; then 402 | if [ ! -d "$1" ] ; then 403 | echo "test file not found: $1" 404 | texit 1 405 | fi 406 | # it's a directory, add all files in it 407 | for FILENAME in "$1"/*.test.sh; do 408 | if [ -f "$FILENAME" ] ; then 409 | FILE_LIST+=("$FILENAME") 410 | fi 411 | done 412 | else 413 | # add a single file 414 | FILE_LIST+=("$1") 415 | fi 416 | shift 417 | done 418 | 419 | else 420 | # no parameters passed, go execute all test files we can find 421 | local MY_PATH 422 | if [[ "$0" == "/dev/stdin" ]]; then 423 | # script is executed from stdin, probably through run.sh 424 | MY_PATH=$PWD 425 | else 426 | MY_PATH=$(dirname "$(realpath "$0")") 427 | fi 428 | for FILENAME in "$MY_PATH"/*.test.sh; do 429 | if [[ "$FILENAME" != "$(realpath "$0")" ]]; then 430 | if [ -f "$FILENAME" ] ; then 431 | FILE_LIST+=("$FILENAME") 432 | fi 433 | fi 434 | done 435 | fi 436 | 437 | tinitialize "$SUITE_NAME" 438 | 439 | for FILENAME in ${FILE_LIST[*]}; do 440 | # shellcheck disable=SC1090 441 | source "$FILENAME" 442 | done 443 | 444 | tfinish 445 | } 446 | 447 | 448 | # see 'main' for usage 449 | if [[ $0 == "${BASH_SOURCE[0]}" ]]; then 450 | # this script is executed, not sourced, so initiate a test run 451 | main "$@" 452 | fi 453 | --------------------------------------------------------------------------------