Career OS

Docker — Ship It The Same Everywhere

You built SplitEase, it runs on your laptop, and then a teammate clones the repo and it explodes — wrong Java version, no Postgres, a missing env var, “works on my machine” turning into a two-hour debugging call. Docker is how you stop that forever: package the app and everything it needs to run into one sealed box that behaves identically on your machine, your teammate’s, the CI server and a rented cloud box. This track teaches you to build that box, run it, wire it to a database, and ship it.

The Goal

By the end of this track you can:

  • Explain what a container actually is — an isolated process, not a tiny virtual machine — and why it starts in milliseconds
  • Write a correct, small, non-root Dockerfile for the SplitEase Spring Boot API and understand every line
  • Run containers fluently — ports, logs, env vars, exec, restart policies — without copy-pasting commands blindly
  • Persist data with volumes and connect containers over a network so the app can actually reach Postgres
  • Compose the whole SplitEase stack (app + Postgres + Redis) and bring it up with one command
  • Push a tagged image to a registry and hand it cleanly to a CI/CD pipeline or a cloud deploy

The Lesson

What Docker actually is

Strip the whale logo and the buzzwords, and Docker is one idea: package your app together with its entire environment into a single image, then run that image as an isolated process called a container — and it runs the same everywhere.

“Its entire environment” is the important part. The image holds your compiled SplitEase JAR and the exact Java 21 runtime it needs, the right OS libraries, the file layout, the startup command — everything except the kernel. When you run it, you get a container: a real process on your machine, but walled off so it can’t see your other files, your other processes, or anyone else’s. To the process inside, it looks like it has the whole machine to itself. To your laptop, it’s just one more program running.

That’s the whole magic. No “but it needs Java 17 and you have 21,” no “did you set the DB password,” no “it needs this one library that’s only on the Linux box.” The box carries all of it.

The “works on my machine” pain — a real story

Picture it concretely. You finish the SplitEase API on a Friday. It runs perfectly: mvn spring-boot:run, Postgres is installed locally on port 5432, your application.properties points at it, your JAVA_HOME is set to Java 21. Done. Green.

Monday, a teammate pulls the repo to add a feature.

  • Their machine has Java 17. The build fails on a Java 21 syntax. (30 minutes lost.)
  • They install Java 21. Now it builds, but crashes on boot — no Postgres on their machine. (Another 30.)
  • They install Postgres. Wrong version, different default password, the schema isn’t there. (An hour.)
  • It finally starts — and behaves differently because their OS rounds something your OS didn’t.

That’s a half-day gone, and you’ve now had this exact conversation three times this month. The bug was never in the code. It was in the environment — all the invisible stuff around the code that has to be identical for the code to behave the same.

Docker deletes this entire category of problem. You define the environment once, in a file (the Dockerfile), check it into the repo, and everyone — every teammate, every CI run, every server — runs the same sealed box. “Works on my machine” becomes “works in the container,” and the container is the same machine everywhere. That single guarantee is why Docker is on nearly every backend job description you’ll read.

Where Docker sits — vs CI/CD, Cloud, and Networking

Docker is the packaging and local-runtime layer. It is not your pipeline, it is not your server, and it is not the wire. It’s easy to blur these, so pin them down now — and this track links to its neighbours instead of re-teaching them:

LayerWhat it ownsThe track
DockerBuild the image, run it locally, define the environmentthis track
CI/CDA pipeline that builds the image automatically on every push and tests itCI/CD track
CloudRented servers that run your image where users can reach itCloud track
NetworkingTCP, ports, DNS — the actual wire at runtimeNetworking track

The clean mental model of how an image flows from your editor to a running service:

flowchart LR
    A["Dockerfile: the recipe you write"] --> B["Image: the sealed, built box"]
    B --> C["Registry: the shared shelf, like Docker Hub"]
    C --> D["Container: the box running as a live process"]

Read it left to right. You write a Dockerfile (the recipe). Docker builds an image from it (the sealed box — built once, never changes). You push the image to a registry (a shared shelf like Docker Hub or GHCR, so other machines can grab it). Anywhere — your laptop, the CI server, a cloud box — pulls the image and runs it as a container (a live process). Same image in, same behaviour out, every time.

Docker owns the first two boxes and the act of running. CI/CD automates the build-and-push so you don’t do it by hand. Cloud is the machine on the far right that pulls and runs it for real users. Networking is how the bytes actually move once it’s running. Keep those boundaries straight and the whole stack stops feeling like one confusing blob.

This track

Eight modules, in order. Each one containerises or runs SplitEase — the same Spring Boot expense-splitter API you’ve been building — so you’re never learning Docker on a toy.

ModuleWhat it gives you
Docker 01 — What Containers Actually AreProcess isolation, namespaces and cgroups; why a container is NOT a VM; image vs container, made concrete
Docker 02 — Images & LayersHow a Dockerfile becomes stacked layers, the union filesystem, and the build cache that makes rebuilds fast
Docker 03 — Dockerfile Deep DiveEvery instruction; ENTRYPOINT vs CMD; ordering layers for cache; multi-stage builds; small, non-root images; .dockerignore
Docker 04 — Running ContainersThe CLI vs the daemon; run, ps, logs, exec, stop, rm; ports, detached mode, env vars, restart policies
Docker 05 — Data & NetworkingVolumes (named vs bind) and why your data vanishes without them; container networks, service DNS, publishing ports
Docker 06 — Docker ComposeThe whole SplitEase stack (app + Postgres + Redis) in one file, with depends_on, healthchecks, and one-command up
Docker 07 — Images In ProductionRegistries (push/pull, Docker Hub vs GHCR); tags vs digests; scanning and shrinking images; the CI/CD and Cloud handoff
Docker 08 — Capstone: Containerise SplitEaseThe full build end to end — Dockerfile, compose, run, push, a definition-of-done checklist, and staged debugging drills

Start with Docker 01 — once “a container is just an isolated process” clicks, every command in the track stops feeling like memorisation.

Before you start — a quick honesty check

You probably already have some beliefs about Docker, half-true and half from a YouTube thumbnail. Take this now and don’t worry about the score — the point is to see which ideas this track will fix.

Module done? Add it to today’s tracker

Saves your progress on this device.