What we use Docker for
In development, every project brings its own environment with it. The PHP 8 version the project requires, plus MariaDB, Redis and, where needed, Elasticsearch — described in a Compose file that lives in the repository. Anyone joining the project starts the environment and gets to work. That replaces half a day of setting up a local system, and the arguments about why a bug only appears on one machine.
In operations we use containers for our own applications: Node.js services, Python tools, interfaces between shop and ERP. The real gain is the separation by service. Database, cache and search index each run on their own, can be updated individually and do not affect one another. Classic shop and CMS installations, by contrast, we often still run on a dedicated virtual machine — more on that below.
How we work with Docker
One Compose setup per project, versioned in the Git repository, with the same services as the target environment. We build images from slim base images and pin versions instead of trusting latest — otherwise the environment changes without anyone having changed anything. Configuration comes in through environment variables; credentials do not go into the image. Databases get named volumes so that a restart does not cost data.
Building and rolling out happen through the CI pipeline: tests run in the container, the image is built, pushed to a registry and pulled onto the target machine. That target machine is usually a virtual machine in our own Proxmox cluster, on servers in Germany. Logs go outside, not into the container. And every container gets limits for memory and CPU, so that one outlier does not take its neighbour down with it.
Limits and alternatives
Containers do not solve an architecture problem. Containerise an unclear system and you have an unclear system in containers, only with more moving parts. Before we put anything into containers, we establish which services actually exist, where state lives and how data flows. Skip that step and Docker merely moves the pain from the server into the build pipeline. The second point: not every system gains from it.
Kubernetes is overkill for the vast majority of mid-sized projects. One shop, one CMS, a handful of background services — that does not need a cluster scheduler, it needs a properly sized machine. Running Kubernetes costs attention that is then missing elsewhere in the project. It starts to make sense when there really are many services to orchestrate, or when several teams deploy independently. For a single TYPO3 or Shopware installation we stay with the virtual machine, with backup and snapshot.