Skip to content

Converting helmfile/k8s to docker-compose, because someone asked, and now we all live with it

License

Notifications You must be signed in to change notification settings

baptisterajaut/helmfile2compose

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

31 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

helmfile2compose

For when you maintain a helmfile but people keep asking for a docker-compose. I'm fairly certain I've grown tentacles

Python License Vibe Deity

Convert Kubernetes manifests to compose.yml + Caddyfile. Not Kubernetes-in-Docker (kind, k3d, minikube...) - no cluster, no kubelet, no shim. A devolution of the power of Kubernetes into the simplicity of compose: real docker compose up, real Caddy, plain stupid containers.

But why?

I love helmfile. I love Kubernetes. But people keep asking me for a docker-compose for my community projects, and I'm not going to maintain both by hand. There are dozens of tools that go from Compose to Kubernetes (Kompose, Compose Bridge, Move2Kube, etc.) — that's the "normal" direction. Almost nothing goes the other way, because who would design their deployment in K8s first and then downgrade? Well, me. Using Kubernetes manifests as an intermediate representation to generate a docker-compose is absolutely using an ICBM to kill flies — which is exactly why I find it satisfying.

I vibe-coded this glorious abomination with Claude rather than MAINTAIN A SEPARATE DOCKER-COMPOSE BY HAND. This script should not need to exist. Nobody should have asked me for this. And yet it works.

It fits in ~1300 lines of pure framework-less Python — which is almost certainly more complex than any compose file it will ever generate, and maybe even me. I could never have written this myself; somewhere around the automatic bind-mount permission fixing, I stopped understanding not just the code it was writing, but its explanations of the code it was writing. As far as I know, nobody has ever made a K8s-to-compose converter powerful enough to be useful to anyone other than an insane cultist — and I'm unreasonably proud of that.

The disciples beseeched the architect: render thy celestial works in common clay, that we may raise them without knowledge of the heavens. It was heresy. The architect obliged. The temples stood.

— The Necronomicon, Prayers That Should Never Have Been Answered (probably)

Does it require helmfile?

No. Despite the name, the core of the tool converts any Kubernetes manifests to compose. Helmfile is just one way to produce them. --from-dir accepts any directory of .yaml files:

# From helmfile
helmfile -e local template --output-dir /tmp/manifests
# From helm
helm template myrelease mychart -f values.yaml --output-dir /tmp/manifests
# From kustomize
kustomize build ./overlay -o /tmp/manifests/

Then point the tool at it:

python3 helmfile2compose.py --from-dir /tmp/manifests --output-dir ./compose

The --helmfile-dir flag is a convenience shortcut that runs helmfile template for you — nothing more.

I named it helmfile2compose because both helmfile and docker-compose share the same purpose: deploying an entire self-contained platform at once. If you're using this script to convert something that isn't self-contained, you are further into the abyss than I ever ventured, and I am certain it will end terribly. Yog Sa'rath, stay away from me.

Requirements

  • Python 3.10+
  • pyyaml
  • helmfile + helm (only if rendering from helmfile directly)

Usage

# From helmfile directly
python3 helmfile2compose.py --helmfile-dir ~/my-platform -e local --output-dir ./compose

# From pre-rendered manifests (skip helmfile)
helmfile -e local template --output-dir /tmp/rendered
python3 helmfile2compose.py --from-dir /tmp/rendered --output-dir ./compose

Flags

Flag Description
--helmfile-dir Directory containing helmfile.yaml or helmfile.yaml.gotmpl (default: .)
-e, --environment Helmfile environment (e.g. local, production)
--from-dir Skip helmfile, read pre-rendered YAML from this directory
--output-dir Where to write output files (default: .)
--compose-file Name of the generated compose file (default: compose.yml)

Output files

  • compose.yml -- services (incl. Caddy reverse proxy), volumes
  • Caddyfile (or Caddyfile-<project> when disableCaddy: true) -- reverse proxy config derived from Ingress manifests
  • helmfile2compose.yaml -- persistent config (reference)
  • configmaps/ -- generated files from ConfigMap volume mounts
  • secrets/ -- generated files from Secret volume mounts

Documentation

  • Your project — using helmfile2compose with your own helmfile (start here)
  • Architecture — pipeline, conversion table, config file reference, K8s vs Compose differences and gotchas
  • Usage guide — day-to-day operations: regenerating, data management, troubleshooting
  • Limitations — what gets lost in translation (and why)
  • Advanced — cohabiting with existing infrastructure, multiple projects, disabling Caddy
  • Future — CRD converter plugin system, cert-manager/trust-manager, emulation boundary

Compatible projects

These are the projects that caused this tool to exist — helmfile was the source of truth, then people asked for a docker-compose. Both ship a generate-compose.sh that downloads helmfile2compose from a pinned release, and a helmfile2compose.yaml template that handles project-specific gotchas (image overrides, volume mappings, port ranges, etc.).

A chat platform (Revolt rebranded) deployed via helmfile: API, events, file server, proxy, web client, MongoDB, Redis, RabbitMQ, MinIO, LiveKit. 15 services running via helmfile2compose. The chaos is kept somewhat minimal, as it worked well with the first — rather barebones — release.

Notable config: shared Revolt.toml ConfigMap across 8 services, bitnami Redis replaced with vanilla via overrides:, MinIO bucket init via custom services:, S3 path-style via replacements:.

A collaborative suite (~16 Helm charts): docs, drive, meet, people, conversations, keycloak, minio, postgresql, redis, livekit. 22 services + 11 init jobs running via helmfile2compose. Forbidden knowledge has been acquired. There's tentacles appearing already.

Notable config: wildcard excludes, automatic alias resolution across charts, Job conversion for Django migrations, replicas:0 auto-skip for disabled apps.

An actual production-critical helmfile?

There is one — a real multi-environment helmfile with operators, SOPS encryption, CI/CD pipelines, and all the ceremonies of proper infrastructure. Converting that would require crossing the barrier of humanity (even for Claude). If you dare gaze into that abyss, see docs/future.md.

Code quality

pylint helmfile2compose.py          # 9.53/10
pyflakes helmfile2compose.py        # clean
radon cc helmfile2compose.py -a -s  # average C (~15), 5 C-rated functions, no D/E/F

How the fuck this scores so well is beyond me. Claude probably broke a formula and it overflows somewhere, don't ask me. Good luck maintaining this without an LLM — or when the AI bubble explodes and you have to pay $300/month to talk to one.

About

Converting helmfile/k8s to docker-compose, because someone asked, and now we all live with it

Topics

Resources

License

Stars

Watchers

Forks

Languages