Skip to content

Basic Examples

Common usage patterns for docker-kotlin.

Running a Web Server

import io.github.joshrotenberg.dockerkotlin.core.Docker

suspend fun main() {
    val docker = Docker()

    // Run nginx
    val containerId = docker.run("nginx:alpine") {
        name("web-server")
        port(8080, 80)
        detach()
    }

    println("Nginx running at http://localhost:8080")
    println("Container ID: ${containerId.short()}")

    // Press enter to stop
    readLine()

    docker.stop("web-server")
    docker.rm("web-server")
}
import io.github.joshrotenberg.dockerkotlin.core.Docker;
import io.github.joshrotenberg.dockerkotlin.core.command.*;

public class WebServer {
    public static void main(String[] args) {
        Docker docker = Docker.create();

        ContainerId containerId = RunCommand.builder("nginx:alpine")
            .name("web-server")
            .port(8080, 80)
            .detach()
            .executeBlocking();

        System.out.println("Nginx running at http://localhost:8080");
        System.out.println("Container ID: " + containerId.short());

        // Cleanup
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            StopCommand.builder("web-server").executeBlocking();
            RmCommand.builder("web-server").executeBlocking();
        }));
    }
}

Running a Database

import io.github.joshrotenberg.dockerkotlin.core.Docker
import kotlin.time.Duration.Companion.seconds

suspend fun main() {
    val docker = Docker()

    // Run PostgreSQL
    val containerId = docker.run("postgres:16") {
        name("my-postgres")
        port(5432, 5432)
        env("POSTGRES_USER", "myuser")
        env("POSTGRES_PASSWORD", "mypassword")
        env("POSTGRES_DB", "mydb")
        namedVolume("postgres-data", "/var/lib/postgresql/data")
        detach()
    }

    println("PostgreSQL started: ${containerId.short()}")
    println("Connection: postgresql://myuser:mypassword@localhost:5432/mydb")

    // Wait for database to be ready
    var ready = false
    repeat(30) {
        try {
            val result = ExecCommand(containerId.value, "pg_isready", "-U", "myuser")
                .executeBlocking()
            if (result.exitCode == 0) {
                ready = true
                return@repeat
            }
        } catch (e: Exception) {
            // Not ready yet
        }
        Thread.sleep(1000)
    }

    if (ready) {
        println("Database is ready!")
    } else {
        println("Database failed to start")
    }
}

Building and Running Custom Image

import io.github.joshrotenberg.dockerkotlin.core.command.*

suspend fun main() {
    // Build image from Dockerfile
    val imageId = BuildCommand("./app")
        .tag("my-app:latest")
        .tag("my-app:v1.0")
        .buildArg("VERSION", "1.0.0")
        .execute()

    println("Built image: $imageId")

    // Run the image
    val containerId = RunCommand("my-app:latest")
        .name("my-app")
        .port(3000, 3000)
        .env("NODE_ENV", "production")
        .detach()
        .execute()

    println("App running at http://localhost:3000")
}

Running Multiple Containers

import io.github.joshrotenberg.dockerkotlin.core.Docker
import io.github.joshrotenberg.dockerkotlin.core.command.*
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope

suspend fun main() = coroutineScope {
    val docker = Docker()

    // Create a network
    NetworkCreateCommand("app-network").execute()

    // Start database
    val dbJob = async {
        docker.run("postgres:16") {
            name("db")
            network("app-network")
            networkAlias("database")
            env("POSTGRES_PASSWORD", "secret")
            detach()
        }
    }

    // Start cache
    val cacheJob = async {
        docker.run("redis:7-alpine") {
            name("cache")
            network("app-network")
            networkAlias("redis")
            detach()
        }
    }

    // Wait for infrastructure
    dbJob.await()
    cacheJob.await()

    // Start application
    docker.run("my-app:latest") {
        name("app")
        network("app-network")
        port(8080, 8080)
        env("DATABASE_URL", "postgresql://postgres:secret@database:5432/postgres")
        env("REDIS_URL", "redis://redis:6379")
        detach()
    }

    println("Application stack running!")
    println("App: http://localhost:8080")
}

Executing Commands in Containers

import io.github.joshrotenberg.dockerkotlin.core.command.*

suspend fun main() {
    // Start a container
    val containerId = RunCommand("ubuntu:22.04")
        .name("ubuntu-test")
        .detach()
        .command("sleep", "infinity")
        .execute()

    // Execute commands
    val whoami = ExecCommand(containerId.value, "whoami").execute()
    println("User: ${whoami.stdout.trim()}")

    val hostname = ExecCommand(containerId.value, "hostname").execute()
    println("Hostname: ${hostname.stdout.trim()}")

    // Install a package
    ExecCommand(containerId.value, "apt-get", "update").execute()
    ExecCommand(containerId.value, "apt-get", "install", "-y", "curl").execute()

    // Test curl
    val curl = ExecCommand(containerId.value, "curl", "-s", "https://httpbin.org/ip").execute()
    println("External IP: ${curl.stdout}")

    // Cleanup
    StopCommand(containerId.value).execute()
    RmCommand(containerId.value).execute()
}

Copying Files

import io.github.joshrotenberg.dockerkotlin.core.command.*
import java.io.File

suspend fun main() {
    // Start container
    val containerId = RunCommand("nginx:alpine")
        .name("nginx-test")
        .port(8080, 80)
        .detach()
        .execute()

    // Create a custom index.html
    File("/tmp/index.html").writeText("""
        <!DOCTYPE html>
        <html>
        <body>
            <h1>Hello from docker-kotlin!</h1>
        </body>
        </html>
    """.trimIndent())

    // Copy to container
    CpCommand("/tmp/index.html", "nginx-test:/usr/share/nginx/html/index.html")
        .execute()

    println("Custom page available at http://localhost:8080")

    // Copy nginx config out
    CpCommand("nginx-test:/etc/nginx/nginx.conf", "/tmp/nginx.conf")
        .execute()

    println("Nginx config saved to /tmp/nginx.conf")
}

Viewing Logs

import io.github.joshrotenberg.dockerkotlin.core.command.*

suspend fun main() {
    // Start container
    RunCommand("nginx:alpine")
        .name("nginx-logs")
        .port(8080, 80)
        .detach()
        .execute()

    // Generate some traffic
    repeat(5) {
        Runtime.getRuntime().exec("curl -s http://localhost:8080").waitFor()
    }

    // Get logs
    val logs = LogsCommand("nginx-logs")
        .tail(20)
        .timestamps()
        .execute()

    println("Container logs:")
    println(logs.stdout)

    // Cleanup
    StopCommand("nginx-logs").execute()
    RmCommand("nginx-logs").execute()
}

Error Handling

import io.github.joshrotenberg.dockerkotlin.core.Docker
import io.github.joshrotenberg.dockerkotlin.core.error.DockerException

suspend fun main() {
    val docker = Docker()

    try {
        // Try to run non-existent image
        docker.run("nonexistent-image:latest") {
            detach()
        }
    } catch (e: DockerException.CommandFailed) {
        println("Command failed!")
        println("Exit code: ${e.exitCode}")
        println("Error: ${e.stderr}")
    } catch (e: DockerException.ImageNotFound) {
        println("Image not found: ${e.image}")
    } catch (e: DockerException.Timeout) {
        println("Command timed out after ${e.duration}")
    } catch (e: DockerException) {
        println("Docker error: ${e.message}")
    }
}

Dry Run / Preview

import io.github.joshrotenberg.dockerkotlin.core.command.*

fun main() {
    val cmd = RunCommand("nginx:alpine")
        .name("web-server")
        .port(8080, 80)
        .port(8443, 443)
        .env("NGINX_HOST", "localhost")
        .env("NGINX_PORT", "80")
        .volume("/var/www", "/usr/share/nginx/html")
        .label("app", "nginx")
        .network("frontend")
        .memory("512m")
        .cpus("0.5")
        .restart(RestartPolicy.Always)
        .detach()

    // Preview without executing
    val preview = cmd.preview()

    println("Command that would be executed:")
    println(preview.commandLine)
    println()
    println("Arguments:")
    preview.args.forEach { println("  $it") }
}

Output:

Command that would be executed:
docker run --name web-server --publish 8080:80 --publish 8443:443 --env NGINX_HOST=localhost --env NGINX_PORT=80 --volume /var/www:/usr/share/nginx/html --label app=nginx --network frontend --memory 512m --cpus 0.5 --restart always --detach nginx:alpine

Arguments:
  run
  --name
  web-server
  --publish
  8080:80
  ...