Hybrid Container Governance: Scaling Patterns That Work A developer built a hybrid container governance pattern to manage multiple WSL instances running the same MCP server stack. Instead of installing the stack on each instance, they containerized the entire environment using Docker, enabling a single deployment served to all WSL instances. The approach eliminated environmental drift and installation script debugging, shifting focus from deployment to feature development. The third WSL instance didn't need a reinstall. That's when I knew the pattern worked. WSL 1 had the full stack — six ark- MCP servers, oh-my-mcp gateway, server-commands-rtk, all configured, tested, running. WSL 2 was planned for the same setup. So was WSL 3. Each one would need npx @ev3lynx/oh-my-mcp , the npm dependencies, the config files, the supergateway wrappers, the port allocations, the CLI bridge, the permission schema in opencode.jsonc. I started scripting the install. Halfway through, I stopped and deleted the script. Installing the same stack N times is the wrong answer. The right answer is one installation, served. The architecture we'd built was already multi-process — oh-my-mcp managing six child servers, each with its own port, its own lifecycle, its own restart budget. The step from "multi-process on one machine" to "multi-WSL via one container" was smaller than expected: FROM ghcr.io/anomalyco/opencode:dev-debian oh-my-mcp gateway RUN npm install -g @ev3lynx/oh-my-mcp COPY supervisord.conf /etc/supervisor/conf.d/opencode-stack.conf CMD "supervisord", "-c", "/etc/supervisor/conf.d/opencode-stack.conf" The container runs two supervised processes: opencode serve --hostname 0.0.0.0 --port 4096 oh-my-mcp --port 8090 management API on 8080 Ports exposed: 4096 OpenCode SSE , 8080 management , 8090 MCP gateway . Volume mounts for persistence: volumes: - ~/.config/opencode:/home/ev3lynx/.config/opencode - ~/.local/share/opencode:/home/ev3lynx/.local/share/opencode - ~/server:/home/ev3lynx/server - ~/.ssh:/home/ev3lynx/.ssh - /var/run/docker.sock:/var/run/docker.sock From any WSL instance: docker exec -it opencode-stack opencode . Same env, same config, same servers. Zero npm installs per distro. But I didn't start with a container. I started the wrong way. The first WSL instance got the full manual setup: npx @ev3lynx/oh-my-mcp install, fnm multishell resolution, port allocation for each ark server, supergateway wrappers for every stdio→SSE bridge, systemd user service registration, and a fire-and-forget shell script that was already one edit away from breaking silently. When WSL 2 needed the same thing, I ran the script again. It failed because systemctl --user doesn't behave the same across WSL instances — Debian's systemd vs Alpine's OpenRC vs Ubuntu's snap-wrapped systemd. The paths were different. The fnm node version was different. The /run/user/1000/ socket path was absent on the second instance because the user ID was 1001. I spent an afternoon fixing environmental drift between two WSL instances that were supposed to be identical. I caught myself debugging the wrong thing: not the architecture, not the code — but the installation path . That was the moment the container decision made itself. Not because containers are trendy. Because I was debugging installation scripts instead of shipping features. The tension isn't technical. The container is trivially simple — a Dockerfile, a docker-compose.yml, a volume mapping. The tension is architectural: we had built an MCP server ecosystem without a deployment story. Every server in the ark- family was designed as a standalone process with clear boundaries focused tools, independent lifecycle . But standalone doesn't mean deployable. A process without a reproducible environment is a test that passes on your machine. Here's the voice that argues against it: "It's three WSL instances. You can script the install. Docker adds overhead, a learning curve for the next person, another moving part. A Makefile and a README note is cheaper." This voice isn't wrong — it's looking at the right cost but the wrong time horizon. At WSL 3, the Makefile is still fine. At WSL 5, when they're different distros Debian, Ubuntu, Alpine, Fedora, Arch , each with different systemd quirks, different package managers, different default shells — the Makefile becomes a liability audit. At a CI runner and a team member's machine and a deployment target, it's a full-time maintenance job. The cost of the container is paid once. The cost of environment-specific setup scripts compounds with every new target. Six servers is a manageable number. Sixteen is not — unless you have a pattern that makes each one predictable. Every ark- server follows the same template: Adding a new server is five files, not five hours: server/ark-