{"slug":"why-we-dont-default-to-docker","url":"https://tako.sh/blog/why-we-dont-default-to-docker/","canonical":"https://tako.sh/blog/why-we-dont-default-to-docker/","title":"Why We Don't Default to Docker (and When You Should Still Use It)","date":"2026-03-22T12:00","description":"Why we skip the Docker rebuild loop — and when containers still make sense.","author":null,"image":"f2216fe3649a","imageAlt":null,"headings":[{"depth":2,"slug":"docker-is-great","text":"Docker Is Great"},{"depth":2,"slug":"where-containers-add-overhead","text":"Where Containers Add Overhead"},{"depth":2,"slug":"takos-approach-direct-execution","text":"Tako’s Approach: Direct Execution"},{"depth":2,"slug":"when-docker-is-the-right-call","text":"When Docker Is the Right Call"},{"depth":2,"slug":"choose-your-abstraction","text":"Choose Your Abstraction"}],"markdown":"You change one line of code. You run the deploy. Then you wait.\n\nThe Docker image rebuilds. Layer cache misses because you touched `package.json`. The image pushes to a registry. The server pulls it back down. The container restarts. Three minutes later, your one-line fix is live.\n\nWe've all been there. That feedback loop is what led us to build Tako differently.\n\n## Docker Is Great\n\nLet's be clear: Docker is an incredible piece of engineering. It solved real problems — reproducible builds, portable environments, dependency isolation. The container ecosystem is massive and battle-tested. If you're running microservices at scale, orchestrating heterogeneous workloads, or need strict process isolation, containers are a proven choice.\n\nWe're not anti-Docker. We just think it shouldn't be the default for every deployment.\n\n## Where Containers Add Overhead\n\nFor many web applications — especially JavaScript/TypeScript apps — the container abstraction introduces friction that doesn't pay for itself:\n\n**Build time.** A typical Dockerfile rebuilds layers sequentially. Change a dependency? Invalidate the cache from that layer down. Multi-stage builds help, but they add complexity and still take time. In practice, Docker builds can add minutes to every deploy cycle.\n\n**Registry round-trips.** Push the image. Pull the image. For a 500MB Node.js image, that's real bandwidth and real time, especially if your CI and server aren't colocated.\n\n**Cold start latency.** Container startup isn't free. The runtime needs to pull layers (if not cached), set up the filesystem overlay, initialize networking, and then start your actual process. For scale-to-zero workloads, this overhead compounds.\n\n**Another abstraction to debug.** Dockerfiles look simple until they aren't. Layer ordering, cache busting, multi-stage builds, Alpine vs Debian, permission issues — it's a whole skill tree. When something breaks, you're debugging the build system instead of your app.\n\nHere's a concrete example of what a small change looks like in each model:\n\n| Step        | Docker-based deploy                        | Tako deploy                       |\n| ----------- | ------------------------------------------ | --------------------------------- |\n| Code change | Edit one file                              | Edit one file                     |\n| Build       | Rebuild image layers (~60-120s)            | Run build command locally (~1-5s) |\n| Transfer    | Push to registry, pull on server (~30-60s) | SFTP compressed archive (~2-5s)   |\n| Start       | Pull layers, start container (~10-30s)     | Start process (~0.1-0.5s)         |\n| **Total**   | **~2-4 minutes**                           | **~5-10 seconds**                 |\n\n_Times are illustrative and vary by setup, image size, and caching. Your mileage will differ — but the gap is real._\n\n## Tako's Approach: Direct Execution\n\nTako runs your app as a process, not a container. When you run [`tako deploy`](/docs/deployment), here's what happens:\n\n1. Your project is copied to a clean working directory (respecting `.gitignore`)\n2. Build commands run locally on your machine\n3. The result is compressed and sent to your server via SFTP\n4. The server installs production dependencies and starts your app directly\n\nNo image builds. No registry. No container runtime. Your app runs under the same [runtime](/docs/how-tako-works) (Bun or Node) in both development and production.\n\nThis means:\n\n- **Fast iteration** — change, build, deploy in seconds\n- **Simple debugging** — SSH in, look at the process, tail the logs\n- **Lower resource usage** — no Docker daemon, no overlay filesystem, no image layers\n- **True dev/prod parity** — [`tako dev`](/docs/development) uses the same runtime and SDK as production\n\nThe tradeoff is intentional. We support a focused set of runtimes — currently [Bun and Node.js](/docs/how-tako-works) for JavaScript apps, plus Go — and optimize deeply for them, rather than supporting anything-in-a-container at the cost of speed.\n\n## When Docker Is the Right Call\n\nThere are legitimate reasons to reach for containers:\n\n- **Complex native dependencies** — if your app needs system libraries, GPU drivers, or specific OS packages that are painful to manage directly\n- **Strict isolation requirements** — multi-tenant environments where process-level isolation isn't enough\n- **Existing infrastructure** — your team already has a container pipeline, registries, and tooling that works well\n- **Heterogeneous stacks** — you're running Go, Rust, Python, and Java services and need a single deployment model\n\nWe respect these use cases. Docker as an opt-in runtime option is on our [roadmap](https://github.com/lilienblum/tako/issues/8) — because the right tool depends on the job, and sometimes that tool is a container.\n\nThe key word is _opt-in_. We think the default should be the fastest, simplest path. For most web apps, that's direct execution.\n\n## Choose Your Abstraction\n\nThis isn't Docker vs Tako. It's about choosing the right level of abstraction for your workload.\n\nIf you need containers, use containers. If you want fast deploys, minimal overhead, and a tool that gets out of your way — [give Tako a try](/docs/quickstart). One `tako.toml`, one command, and your app is live.\n\n```bash\ntako init\ntako deploy\n```\n\nThat's it. No Dockerfile required."}