Docker shows up in almost every serious system I ship: Remix commerce apps, specialty ops services, webhook platforms, Terraform-adjacent build agents, and CodeBuild images. People still treat it like “put an app in a box.” That undersells it.
For me Docker is how environments stop lying.
The problem Docker actually solves
Without containers, teams argue about:
- which Node version is “current”
- which native libs a sharp/image tool needs
- whether Prisma engines match the OS
- why CI failed when a laptop passed
- why stage died after a host patch
Docker does not remove those concerns. It names them in a Dockerfile and makes them reviewable.
How I use Docker day to day
1. Same artifact shape from laptop to AWS
I want local docker build to produce something spiritually identical to what CodeBuild or a pipeline pushes to ECR. Not “similar vibes.” Same base image family, same lockfiles, same build steps.
When a Shopify app, Next portal, or Express webhook service ships as an image, rollback is an image tag conversation, not a “recreate the server by memory” conversation.
2. Multi-stage builds for smaller truths
A good Dockerfile separates:
- dependency install
- build
- runtime
That keeps runtime images leaner and attack surface smaller. It also forces you to know what the running service actually needs. If your runtime image still contains the entire build toolchain, you have not finished the design.
3. Compose for local platform reality
Bigger specialty platforms are not one process. POS companions, portals, webhooks, MySQL, Redis, and fake upstreams need a local constellation. Compose files are how juniors can boot a slice of the universe without a tribal setup doc from 2019.
4. CI as a container consumer
Pipelines should build and test inside known images. Host runners patch underneath you. Containers pin the contract. That is how “green on Monday, red on Tuesday” becomes rarer.
Docker made leadership easier
Teaching a new engineer “install these twelve things” does not scale. Teaching “here is the service image and the compose profile” does.
Docker becomes a mentoring interface:
- here is how we build
- here is how we run
- here is how we read logs
- here is how we reproduce prod-ish failure locally
Weekly shares about Dockerfile mistakes are some of the highest-ROI teaching I have seen. One bad COPY cache lesson saves a team hours every month.
The sharp edges I still respect
Docker is not free:
- volume performance differs wildly across OS hosts (another reason Linux daily driving helps)
- networking mental models take time
- fat images create slow deploys and sleepy clusters
- people use containers to avoid learning the app, which creates opaque failures
My rule: containers package known good builds; they do not replace architecture. A messy monolith in Docker is still a messy monolith, just portable.
Patterns that keep paying rent
- Pin base images deliberately; floating
latestis how surprises ship - Use
.dockerignorelike you mean it - Keep secrets out of layers
- Healthchecks that match real readiness, not just “process exists”
- One service, one reason to rebuild
- Document the escape hatch: how to run without compose when debugging deep
Leadership takeaway
Docker is one of the best tools I have for making teams honest about runtime. It shrinks environment drama, speeds onboarding, and makes AWS deploys a continuation of local craft instead of a separate religion.
If your team still debugs “works on my machine” as a personality conflict, start with the Dockerfile. Then teach everyone how to read it.
