Docker & Deployment — Ship It Anywhere
What you'll learn
- The "works on my machine" problem — and how containers solve it
- What Docker actually does, in plain terms
- The path from your laptop to a live server
- Core deployment vocabulary
The shipping container 📦
Every developer has said it: "but it works on my machine!" The app runs on your laptop, then breaks on the server — a different OS, a missing library, a wrong version. Chaos.
Docker solves this the way global trade solved cargo: the shipping container. Before containers, loading a ship meant custom-fitting every odd-shaped item. The standardized container changed everything — any container fits any ship, truck, or crane, anywhere.
A Docker container packs your app plus everything it needs — the exact OS libraries, the right language version, all dependencies — into one standardized box. That box runs identically on your laptop, your teammate's machine, and the production server. "Works on my machine" becomes "works on every machine."
You describe the box in a Dockerfile (a recipe):
FROM node:20 # start from a box that already has Node 20
WORKDIR /app
COPY package.json . # copy dependency list
RUN npm install # install them
COPY . . # copy your code
CMD ["node", "server.js"] # command to run when the box starts
The deployment journey:
- Write code → 2. Build a Docker image (the packed box) → 3. Push it to a registry → 4. Run it on a server in the cloud (AWS, a VPS, etc.) → 5. Users reach it via a domain name.
Related words you'll hear: an image is the blueprint, a container is a running instance of it; hosting is renting the server; a domain points to that server's IP (remember DNS!).
CI/CD — the automatic safety net 🤖
Packaging your app in a container answers "how do I ship it?" A different question is "how do I make sure what I ship actually works, every single time, without me babysitting it?" That's CI/CD.
CI (Continuous Integration) means every time someone pushes code, a robot automatically: installs dependencies, runs the test suite, and checks the code builds — before it's allowed to merge. Nobody has to remember to run tests by hand; the pipeline just refuses broken code.
CD (Continuous Deployment/Delivery) picks up right after: once code passes CI on the main branch, it's automatically built into an image and shipped to production — no human manually copying files onto a server at 2am. "Delivery" means it's staged and ready for a human to click "go"; "Deployment" means it goes live with no click at all.
A typical pipeline, as a sequence of steps that must each pass before the next runs:
push code → install deps → run tests → build Docker image → deploy to staging → (manual approval) → deploy to production
If any step fails, the pipeline stops — bad code never reaches users. Popular tools: GitHub Actions, GitLab CI, Jenkins. This entire platform's own static site rebuilds and redeploys automatically through exactly this kind of pipeline every time code is pushed — no one manually uploads files.
Simulate a CI/CD pipeline. Write runPipeline(steps) where steps is an array of functions, each returning true (pass) or false (fail). Run them in order, stopping at the first failure. Return { passed: N, stoppedAt: index or null } — stoppedAt is the index of the failing step, or null if all passed.
This mirrors a real pipeline: one broken step blocks everything after it.
Real-world case study: Knight Capital's 45-minute, $460 million deploy 🔍
In August 2012, Knight Capital, a major U.S. stock trading firm, deployed new trading software to its production servers. The deployment process was manual: an engineer was supposed to copy the new code to eight servers, but it only actually got copied to seven — the eighth kept running old, dormant code that had been dead for years, repurposed for a different feature with the same flag name reused.
When the markets opened, that eighth server started executing the old code path, which triggered millions of unintended trades in 45 minutes, before anyone could diagnose what was happening or roll it back cleanly. The company lost roughly $460 million and nearly collapsed overnight, eventually getting acquired.
This is the textbook argument for everything in this lesson. A real CI/CD pipeline deploys the same built artifact to every server automatically, so "it went to 7 of 8 machines" simply cannot happen — there's no manual copy step to get half-right. Automated tests would have run against a full deploy, not a partial one. And a proper rollback mechanism (redeploy the last known-good image) would have ended the incident in seconds instead of 45 minutes of manual scrambling. The whole discipline of CI/CD exists because human hands copying files to production, one server at a time, is a genuine, well-documented, company-ending risk.
Question 1 of 5
What problem does Docker primarily solve?
Question 2 of 5
What's the difference between an image and a container?
Question 3 of 5
In a Dockerfile, what does FROM node:20 do?
Question 4 of 5
What does CI (Continuous Integration) automatically do on every push?
Question 5 of 5
What went wrong in the Knight Capital incident?
Summary
- Containers package your app + its entire environment → runs identically everywhere
- A Dockerfile is the recipe; you build an image and run it as a container
- Deploy path: code → image → registry → server → domain
- CI/CD automates testing and deployment so broken code can't reach users — you built a pipeline runner that stops at the first failing step
- Knight Capital's $460M manual-deploy disaster is the real-world case for automating this
Try it: install Docker Desktop, write the Dockerfile above for a small Node app, and run docker build then docker run. Next: System Design — architecting backends that scale to millions.
Practice
Reading is not learning until you run something. Pick one.