The Story
Your app runs great on Vercel. You push, it deploys, it works. No complaints.
But then your teammate wants to run the whole project locally. Not just the frontend — the whole thing. The database. The auth system. The background job queue. Everything.
So you send them the README. “Install Node. Sign up for Vercel. Sign up for Clerk. Sign up for Upstash. Set up a PostgreSQL database. Get API keys for all three. Put them in a .env file. Run npm install. Run npm run dev. Pray.”
They come back two hours later. “I got errors about my Node version.” You fix it. “Now Clerk says my API key is invalid.” You fix it. “Now the database connection is failing.” You fix it. Three hours in and they still haven’t seen the app run.
Or maybe the problem is different. Maybe you want to run this app somewhere other than Vercel. Maybe on a different hosting platform, or on a server in your office, or in a demo environment that doesn’t touch production services. But your app is tangled up with Vercel’s infrastructure, Clerk’s auth service, Upstash’s queue system. You can’t just copy it somewhere else and run it.
This is the portability problem. Your app isn’t self-contained. It depends on a constellation of external services, and without every single one of them configured correctly, nothing works.
Docker solves this by packaging everything into boxes that run identically everywhere. Not just your app — every service it depends on. The database, the auth system, the job queue, all of it. One command starts the whole thing. No signups. No API keys from three different dashboards. No “works on my machine.” It works on every machine.
This lesson continues with the full course
The story intro above is free to read. The full lesson — prompts, explanations, and adapt-it exercises — requires the Full Course ($249) tier or above.