Skip to content

Rewrite kodkod as a docker-compose autoheal + auto-update helper#1

Merged
IRus merged 2 commits into
mainfrom
feat/compose-autoheal-updater
Jun 3, 2026
Merged

Rewrite kodkod as a docker-compose autoheal + auto-update helper#1
IRus merged 2 commits into
mainfrom
feat/compose-autoheal-updater

Conversation

@IRus

@IRus IRus commented Jun 3, 2026

Copy link
Copy Markdown
Member

Pivots the project from a Docker-in-Docker AI-agent isolation environment into a small Kotlin docker-compose companion that does two things:

  1. Restarts unhealthy containers (autoheal) — like docker-autoheal.
  2. Auto-updates containers — pulls a container's image tag and recreates it (preserving config, env, labels and networks) when a newer image is published.

Both jobs talk directly to the Docker Engine API over the unix socket (no docker/compose CLI), and are opt-in per container via labels under a configurable namespace.

Stack

  • Kotlin 2.4.0, Gradle 9.5.1 (wrapper pinned), JDK 25
  • A single runtime dependency: kotlinx-serialization-json. HTTP-over-unix-socket (UnixDomainSocketAddress + manual HTTP/1.1) and scheduling (ScheduledExecutorService) use the JDK only.
  • Lightweight multi-stage BellSoft Liberica image (JDK 25 build → JRE 25 Alpine runtime).

Labels

  • kodkod.autoheal.enable — restart on unhealthy
  • kodkod.update.enable — pull + recreate when the image changes
  • kodkod.stop.timeout — per-container stop timeout

Configuration is via KODKOD_* env vars (interval, monitor-all, cleanup, registry auth, …); see the README.

How updates work

For each marked container: read its image ref (digest-pinned containers are skipped) → pull repo/tag → compare image ids → if changed, recreate (stop → rename old → create new from existing Config/HostConfig/networks against the new image → start → remove old), with rollback on failure. The kodkod container never acts on itself.

Verification

Tested end-to-end against real Docker (29.4.3 / API 1.54):

  • Autoheal: an isolated unhealthy container was restarted (honoring the stop timeout).
  • Updater: a container on a deliberately-stale image was recreated onto the new image with env, label, network alias and explicit hostname preserved, old container removed.
  • ./gradlew build, docker build, the no-socket "nothing to do" exit-0 path, and bytecode = Java 25 (major 69) all pass.

Cleanup

Removes the old isolation files (Amazon Linux Dockerfile, SDKMAN multi-JDK setup, run.sh, entrypoint.sh, setup-alias.sh, tmux.conf, .bashrc, .env.example) and refreshes CI to build/test the Kotlin app + image with the latest GitHub Actions.

🤖 Generated with Claude Code

IRus and others added 2 commits June 3, 2026 21:55
Pivot the project from a Docker-in-Docker AI-agent isolation environment
into a small Kotlin (2.4.0 / Gradle 9.5.1 / JDK 25) daemon that:

- restarts unhealthy containers (autoheal), and
- pulls and recreates containers when a newer image is published (auto-update),

talking directly to the Docker Engine API over the unix socket with a single
runtime dependency (kotlinx-serialization-json). Both jobs are opt-in per
container via labels under a configurable namespace. Ships as a lightweight
multi-stage BellSoft Liberica JRE Alpine image.

Remove the old isolation files (Amazon Linux Dockerfile, SDKMAN multi-JDK
setup, run.sh, entrypoint.sh, setup-alias.sh, tmux.conf, .bashrc, .env.example)
and refresh CI to build/test the Kotlin app and image with the latest actions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… test

Multi-arch + --load fails ('docker exporter does not currently support
exporting manifest lists'). Build linux/amd64 only on pull_request (load +
smoke test), keep multi-arch build+push for main/tags.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@IRus
IRus merged commit 4c6e96c into main Jun 3, 2026
2 checks passed
@IRus
IRus deleted the feat/compose-autoheal-updater branch June 3, 2026 19:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant