Ktor 2.1.3 Help

Docker

In this section, we'll see how to use the Ktor Gradle plugin for packaging, running, and deploying applications using Docker.

Install the Ktor plugin

To install the Ktor plugin, add it to the plugins block of your build.gradle.(kts) file:

plugins { id("io.ktor.plugin") version "2.1.3" }
plugins { id "io.ktor.plugin" version "2.1.3" }

Plugin tasks

After installing the plugin, the following tasks are available for packaging, running, and deploying applications:

  • buildImage: builds a project's Docker image to a tarball. This task generates a jib-image.tar file in the build directory. You can load this image to a Docker daemon using the docker load command:

    docker load < build/jib-image.tar
  • publishImageToLocalRegistry: builds and publishes a project's Docker image to a local registry.

  • runDocker: builds a project's image to a Docker daemon and runs it. Executing this task will launch the Ktor server, responding on http://0.0.0.0:8080 by default. If your server is configured to use another port, you can adjust port mapping.

  • publishImage: builds and publishes a project's Docker image to an external registry such as Docker Hub or Google Container Registry. Note that you need to configure the external registry using the ktor.docker.externalRegistry property for this task.

Note that by default, these tasks build the image with the ktor-docker-image name and latest tag. You can customize these values in the plugin configuration.

Configure the Ktor plugin

To configure the Ktor plugin settings related to Docker tasks, use the ktor.docker extension in your build.gradle.(kts) file:

ktor { docker { // ... } }

JRE version

The jreVersion property specifies the JRE version to use in the image:

ktor { docker { jreVersion.set(io.ktor.plugin.features.JreVersion.JRE_17) } }

Image name and tag

If you need to customize the image name and tag, use the localImageName and imageTag properties, respectively:

ktor { docker { localImageName.set("sample-docker-image") imageTag.set("0.0.1-preview") } }

Port mapping

By default, the runDocker task publishes the 8080 container port to the 8080 Docker host port. If required, you can change these ports using the portMappings property. This might be useful if your server is configured to use another port.

The example below shows how to map the 8080 container port to the 80 Docker host port.

ktor { docker { portMappings.set(listOf( io.ktor.plugin.features.DockerPortMapping( 80, 8080, io.ktor.plugin.features.DockerPortMappingProtocol.TCP ) )) } }

In this case, you can access the server on http://0.0.0.0:80.

External registry

Before publishing a project's Docker image to an external registry using the publishImage task, you need to configure the external registry using the ktor.docker.externalRegistry property. This property accepts the DockerImageRegistry instance, which provides configuration for the required registry type:

  • DockerImageRegistry.dockerHub: creates a DockerImageRegistry for Docker Hub.

  • DockerImageRegistry.googleContainerRegistry: creates a DockerImageRegistry for Google Container Registry.

The example below shows how to configure the Docker Hub registry:

ktor { docker { externalRegistry.set( io.ktor.plugin.features.DockerImageRegistry.dockerHub( appName = provider { "ktor-app" }, username = providers.environmentVariable("DOCKER_HUB_USERNAME"), password = providers.environmentVariable("DOCKER_HUB_PASSWORD") ) ) } }

Note that the Docker Hub name and password are fetched from the environment variables, so you need to set these values before running the publishImage task:

export DOCKER_HUB_USERNAME=yourHubUsername export DOCKER_HUB_PASSWORD=yourHubPassword
setx DOCKER_HUB_USERNAME yourHubUsername setx DOCKER_HUB_PASSWORD yourHubPassword

Manual image configuration

If required, you can provide your own Dockerfile to assemble an image with a Ktor application.

Package the application

As a first step, you need to package your application along with its dependencies. For example, this might be a fat JAR or an executable JVM application.

Prepare Docker image

To dockerize the application, we'll use multi-stage builds:

  • First, we'll use the gradle/maven image to generate a fat JAR with the application.

  • Then, the generated distribution will be run in the environment created based on the openjdk image.

In the root folder of the project, create a file named Dockerfile with the following contents:

FROM gradle:7-jdk11 AS build COPY --chown=gradle:gradle . /home/gradle/src WORKDIR /home/gradle/src RUN gradle buildFatJar --no-daemon FROM openjdk:11 EXPOSE 8080:8080 RUN mkdir /app COPY --from=build /home/gradle/src/build/libs/*.jar /app/ktor-docker-sample.jar ENTRYPOINT ["java","-jar","/app/ktor-docker-sample.jar"]
FROM maven:3-openjdk-11 AS build COPY . /home/maven/src WORKDIR /home/maven/src RUN mvn package FROM openjdk:11 EXPOSE 8080:8080 RUN mkdir /app COPY --from=build /home/maven/src/target/*-with-dependencies.jar /app/ktor-docker-sample.jar ENTRYPOINT ["java","-jar","/app/ktor-docker-sample.jar"]

The second stage of the build works in the following way:

  • Indicates what image is going to be used (openjdk in this case).

  • Specifies the exposed port (this does not automatically expose the port, which is done when running the container).

  • Copies the contents from the build output to the folder.

  • Runs the application (ENTRYPOINT).

You can find the resulting project in the docker branch of the ktor-get-started-sample repository.

Build and run the Docker image

The next step is to build and tag the Docker image:

docker build -t my-application .

Finally, start the image:

docker run -p 8080:8080 my-application

This will launch the Ktor server, responding on https://0.0.0.0:8080.

Last modified: 14 September 2022