June 2026
Why I Stopped Using Docker for Small Agency Sites
One agency owner explains why Docker added unnecessary complexity to small client sites and what he uses instead
I run a small agency in Zagreb, and for years, Docker was my default for every client site. It felt professional, portable, and future-proof. But after a string of late-night debugging sessions and bloated deployment pipelines for simple brochure sites, I had to ask myself a hard question: was I making things better, or just more complex?
The Siren Call of Containers
When Docker first hit the mainstream, it solved real problems. Consistent environments between development and production, easy scaling for high-traffic applications, and a clear separation of services. For large-scale projects, it’s still a fantastic tool. But for a small agency site — a restaurant in Split, a dental practice in Osijek, or a local tradesman in Rijeka — the overhead quickly outweighs the benefits.
The Cognitive Load Problem
Every Docker setup I maintained required me to remember a specific mental model. I had to know the exact docker-compose.yml structure, the custom network settings, and the volume mounts for each project. When a client called with a broken contact form at 9 PM, I couldn’t just SSH in and look at a standard Apache error log. I had to mentally reconstruct the container orchestration first.
That extra cognitive step doesn’t sound like much, but over a dozen small sites, it becomes a tax on your time and patience. The tools that promised to simplify my workflow actually made me slower for the most common tasks: updating a PHP version, adding a cron job, or fixing a file permission issue.
The Resource Drain on Small VPS Instances
Many of my clients run on affordable VPS plans — 1 GB of RAM, a single CPU core. Docker, with its daemon, overlay networks, and container runtime, eats a non-trivial chunk of that. A clean WordPress site with a few plugins doesn’t need a container orchestrator. It needs PHP-FPM, a web server, and MySQL.
When I moved those same sites to a bare-metal LAMP stack, I freed up 200–300 MB of RAM. That’s real money on a budget VPS. It also meant the server responded faster to requests because there was no container abstraction layer between the application and the kernel.
The Deployment Complexity Trap
One of the biggest selling points of Docker is “it works everywhere.” In theory, you build once and deploy anywhere. In practice, for small agency sites, you end up building a custom pipeline that works nowhere else.
The CI/CD Illusion
I spent two full days setting up a GitLab CI pipeline with Docker Compose for a small real estate agency’s WordPress site. The pipeline built the image, ran tests, pushed to a registry, then pulled and restarted on the production server. It felt like a real engineering achievement.
Then the client wanted to change their theme. The pipeline broke. Then the hosting provider updated the Docker version, and the network driver changed. Then the SSL certificate renewal script stopped working because it ran inside a container with a different timezone.
I realized I had built a fragile house of cards for a site that gets 200 visitors a day. A simple git pull on the server and a database backup script would have been faster, more reliable, and infinitely easier to debug.
The Maintenance Tax
Every few months, Docker releases a security update or deprecates a feature. For a large team with dedicated DevOps, that’s manageable. For a solo developer or a small team in Croatia, it’s another thing on the to-do list that doesn’t directly improve the client’s business.
I remember a specific morning in December 2022. I had three client sites using Docker. Docker Desktop announced a licensing change that made it paid for commercial use. I had to scramble to find alternatives, update my local development setup, and retrain my workflow. None of that added value to my clients. They just wanted their sites to work.
What I Do Instead Now
I don’t hate Docker. I use it for specific projects where the complexity is justified — multi-service applications, machine learning pipelines, or projects with strict environment reproducibility requirements. But for the typical small agency site, I’ve gone back to simpler, more direct tools.
Direct LAMP/LEMP on Bare Metal
For most WordPress and static sites, I use a plain LEMP stack on Ubuntu. I install Nginx, PHP-FPM, MariaDB, and Redis manually. I configure them once, then clone the setup for each new client using a simple Ansible playbook or even a shell script.
This approach has a few clear advantages. First, when something breaks, I can SSH in and fix it immediately without context switching. Second, the server uses fewer resources, which means I can host more clients on the same VPS. Third, backup and restore processes become trivial — just copy the files and export the database.
Static Site Generators for Simpler Projects
For clients who don’t need a CMS — a small law firm, a freelance photographer, a local NGO — I now default to static site generators like Hugo or Eleventy. These produce pure HTML, CSS, and JavaScript. They can be hosted on Netlify, Cloudflare Pages, or even a simple S3 bucket for free.
This is a hard sell at first because clients often want a WordPress admin panel. But I’ve found that once I explain the trade-offs — zero security updates, instant load times, no hosting costs — most reasonable clients are open to it. For the ones who insist on a CMS, I use a flat-file CMS like Grav or Kirby, which still avoids the Docker complexity.
Managed Hosting as a Real Alternative
For the past year, I’ve started recommending managed WordPress hosting services like Kinsta or WP Engine for clients who can afford a slightly higher monthly fee. These services handle caching, security, and scaling automatically. They use their own containerized infrastructure, but they manage it for you.
This lets me focus on the actual work: building the site, optimizing the content, and helping the client grow their business. I don’t have to worry about Docker Compose files, image rebuilds, or container logs. The hosting provider does the heavy lifting, and I get to sleep through the night.
A Concrete Example: The Restaurant That Made Me Change
Last year, I built a site for a small family restaurant in Dubrovnik. They needed a menu, a reservation form, and a photo gallery. Nothing fancy. I set it up with Docker, Docker Compose, Nginx, PHP-FPM, and MariaDB. It worked perfectly in development.
On launch day, the server ran out of inotify watches because Docker’s file synchronization mechanism exhausted the kernel limit. The site loaded, but file uploads failed silently. I spent three hours debugging while the restaurant owner called me every twenty minutes asking when the menu images would work.
The fix was a single sysctl command to increase the inotify limit. But that three hours of stress, the missed calls, and the client’s frustration — all because I chose an over-engineered solution for a simple problem — convinced me to change my approach.
I rebuilt that site on a plain LEMP stack in under an hour. It’s been running for seven months without a single issue. The owner is happy, and I saved myself from a recurring mental overhead that wasn’t paying off.
When I Still Reach for Docker
I’m not throwing Docker out entirely. There are clear cases where it makes sense, even for small agencies.
Client Projects with Multiple Services
If a project requires a separate API server, a database, a queue worker, and a frontend application, Docker Compose is still my go-to. The complexity of managing those services manually on a single server is higher than the complexity of the container setup.
Testing and Local Development
For local development, Docker is excellent. I can spin up a clean environment for each project without polluting my host machine. The key difference is that I no longer use Docker in production for small sites. I develop locally with containers, then deploy to a bare-metal or managed environment.
Clients Who Already Use Docker
If a client comes to me with an existing Docker-based infrastructure and they’re happy with it, I won’t force a migration. But I will be honest about the maintenance costs and suggest alternatives if they start to feel the pain.
The Shift in Mindset That Made the Difference
The real change wasn’t technical — it was about what I value. Early in my career, I wanted every project to look impressive on my resume. Docker, Kubernetes, CI/CD pipelines — they made me feel like a serious engineer. But my clients don’t care about my tools. They care about reliability, speed, and cost.
Once I internalized that, the decision became obvious. I’m not building a platform for millions of users. I’m building websites for local businesses in Croatia that need to work, stay secure, and not break on a Tuesday afternoon.
The Pragmatic Agency Philosophy
I now follow a rule of thumb: use the simplest tool that solves the problem for the next six months. For most small agency sites, that’s a plain LEMP stack or a static site generator. If the client grows and needs horizontal scaling, I can always introduce Docker later. But starting simple saves time, money, and sanity.
This philosophy also applies to the tools I recommend to my clients. I don’t push them toward complex solutions because they sound impressive. I show them the trade-offs honestly, and let them decide what they value more — a cheap monthly bill or a fully managed solution.
What I’d Recommend to Other Croatian Agency Owners
If you’re running a small agency in Croatia and you’re using Docker for every site, try an experiment. Pick your next three brochure-style sites and deploy them without containers. Use a plain LEMP stack with Ansible for configuration management, or just do it manually for the first few.
Track how much time you spend on setup, maintenance, and debugging. Compare it to your Docker-based sites. I think you’ll find that the non-Docker sites take less time to set up, are easier to debug, and run faster on budget hardware.
The Tools I Actually Use Now
My current stack for small agency sites is intentionally boring:
- Server: Ubuntu 22.04 LTS on a Hetzner CX22 (2 vCPU, 4 GB RAM)
- Web server: Nginx with PHP-FPM
- Database: MariaDB with daily automated backups to a separate storage
- Deployment: Simple bash script that pulls from Git and runs
composer install - Monitoring: Uptime Kuma running in a single Docker container (yes, irony noted)
For static sites, I use Hugo with a Netlify deploy hook. For CMS sites, I use WordPress with a managed hosting provider or a flat-file CMS on a bare-metal server.
The Forward-Looking Note
The web development landscape is shifting again. Serverless functions, edge computing, and managed databases are making container orchestration less necessary for small projects. I’m watching tools like Coolify and Dokku that offer a middle ground — containerized deployment without the Docker complexity.
But for now, my advice is simple: don’t let the tool define your process. Let the problem define your tools. Your clients in Croatia don’t care about your Docker Compose file. They care about their site loading fast, staying secure, and costing them less than a cup of coffee per day.
Save your complexity budget for the projects that genuinely need it. For everything else, keep it simple. Your future self — and your sleep schedule — will thank you.