Many of Portainer’s customers run Docker, whether as Swarm clusters or as fleets of discrete hosts; that has been the shape of our business for a long time, and it is a business we intend to keep serving well. Docker still works, Portainer still supports it, and for a lot of workloads it is still a perfectly reasonable place to run them.
At the same time, we have been publicly honest for a while now about the direction Docker is heading. I wrote earlier this year about the difficulty Docker CE faces as a sustainable free product (“Can Docker CE survive in a sea of...”) and about the fallout from the v29 release and what it signals about the project’s operational discipline (“Docker v29 and the fall-out”); both are on insights.portainer.io, and they are what initially triggered my research into an “offramp”.
The trajectory is beginning to concern us, and we think it should start to concern you too, with enough seriousness that you look into planning a docker “exit” now, vs doing so in a panic later.
Why an “off-ramp” though?. With Kubernetes, there are more moving parts, more failure modes, more configuration surface, and a much larger operational vocabulary that your team is expected to speak fluently. Dropping in Kubernetes as a replacement for Docker is not a 5 minute task, nor is it operationally neutral. If a Kubernetes vendor tells you otherwise, they are trying to sell you something. Spinning up a Kubernetes environment overnight has been doable for years; getting you onto Kubernetes without your operational load doubling and your team’s Docker muscle memory becoming useless overnight is the harder problem, and that is the one we set out to solve.
The first piece pf the puzzle we built was KubeSolo (kubesolo.io), which is a single-binary Kubernetes distribution that we deliberately fit inside the memory and CPU footprint of Docker or Podman. You install it, and you get a real Kubernetes API on a single node, with no separately-managed internal components, a CLI TUI for the operational surface, and near-zero ongoing operational overhead for the Kubernetes layer itself; the operational shape looks a lot more like Docker than like a “real” Kubernetes cluster. KubeSolo solved the “I have a Docker host and I want a Kubernetes host of the same weight class” problem, but it did not, on its own, solve the harder one, which is that your applications are defined in docker-compose files, your CI pipelines shell out to the Docker CLI, and every operational reflex your team has is Docker-shaped.
For that, we built d2k (github.com/portainer/d2k), which presents a Docker-compatible API endpoint on top of a Kubernetes backend. The Docker CLI works against it, Docker Compose works against it, and the workloads land as native Kubernetes resources on the cluster underneath, without asking anybody on your team to learn a Kubernetes primitive on day one. We then tested d2k inside Portainer and validated that our existing Docker to Docker migration feature moves running applications from a real Docker environment to a d2k-backed synthetic Docker environment on Kubernetes, in place, without a rewrite.
What that gives you, put simply, is a way to take a Docker deployed application estate off Docker and land it on Kubernetes with the operational surface still looking Docker-shaped on day one, and with the real Kubernetes waiting underneath for when your team is ready to work with it directly.
Even with the offramp in place, Kubernetes has meaningfully larger operational overhead than Docker, and no distribution ships that overhead away; a well-chosen distribution pushes most of it onto somebody else, so your team does not carry it. The difference between a manageable Kubernetes and an unmanageable one is almost entirely a question of who is on-call for the pieces of the stack that fail.
For single-node deployments, and for the branch office, edge site, and small production node cases, KubeSolo is the right answer for the reasons already covered; the operational load of the Kubernetes layer is close enough to Docker’s that your existing team can absorb it, and the front-end is the real Kubernetes front-end, so the skills your team builds transfer directly to any larger cluster you land on later.
For clusters, our recommended approach is Sidero’s Talos Linux with their Kubernetes bootstrapper, backed by a Sidero support agreement that Portainer OEMs. The Sidero support agreement means Sidero take responsibility for triaging and remedying the Kubernetes operational failures that will inevitably occur on any real cluster; functionally, you get KaaS on hardware you own and operate, without handing your workloads to a hyperscaler. That is a materially different proposition to hand-rolling a cluster and hoping your team can support it.
If your workloads can live in public cloud and your CFO is comfortable with the run-rate, managed Kubernetes from your hyperscaler of choice is of course the easiest operational of all; that is full outsourcing of the platform, and it is a bargain where it fits. Where it does not fit, for sovereignty, data gravity, cost at scale, or an existing on-premises footprint you are not going to abandon, Talos with Sidero support is as close as you can get without handing over the keys.
Does this mean Kubernetes equals Docker, operationally? No, not at all. It is, however, the closest you can get to a Docker-shaped operational experience without fully outsourcing the operation of your platform, and it comes with a real migration path (KubeSolo, d2k, and Portainer’s Stack migration) that lets your team keep using the Docker tooling they know, while the runtime underneath quietly becomes Kubernetes. We built this specifically because we know what it feels like to be sitting on a Docker estate today, watching the ground shift, and being told by every vendor in the market that the answer is Kubernetes without any of them offering you a path that starts from where you actually are. That path is what we have built for you, and it is there for the day the trajectory of Docker convinces you it is time to take it.
