Docker
Multi-stage Dockerfiles and reproducible deploys for Node, Java, and Next.js.
Docker is part of every project I ship. I write small, reproducible multi-stage Dockerfiles, use compose for local stacks, and prefer images built in CI over hand-rolled deploys. I treat the container as the unit of deploy, not an afterthought.
How I work with Docker
I started using Docker for parity between dev and prod — solving the classic 'works on my machine' problem on shared backend services. Over time it became the default deploy artifact across every stack I work with.
I have written production Dockerfiles for Node.js, NestJS, Spring Boot, and Next.js apps. I default to multi-stage builds, distroless or slim base images, non-root users, and explicit healthchecks. Compose handles local databases, Redis, and stub services for dev.
On the deploy side I have used Docker on EC2 directly (with simple compose + NGINX) and pushed images to ECR for use with Lambda container deployments. I do not over-engineer — when an app is a single service, a Dockerfile + a compose file are usually the right amount of complexity.
Docker across business domains
Containerized the inference workers + API tier with multi-stage builds; used GPU-enabled base images where applicable.
Shipped both the Spring Boot API and Next.js frontend as containers with reproducible builds via GitHub Actions.
Used Docker + compose to spin up Postgres + the app for fast local onboarding of new developers (single command).
Standardized deployments on Dockerized services behind NGINX, replacing ad-hoc JAR + supervisor setups.
Real issues I resolved using Docker
Cut Node image size from ~1.1GB to ~120MB
A Node.js API container was 1.1GB because it shipped the full devDependencies + multiple build artifacts + a fat base image.
Wrote a proper multi-stage Dockerfile: build stage on `node:lts`, run stage on `node:lts-alpine`, copying only the production node_modules and built artifacts. Set `NODE_ENV=production` and used `npm ci --omit=dev`.
Image size dropped to ~120MB, deploy and cold-start times improved noticeably, and registry storage costs fell.
Made local dev a single-command setup
New developers were spending half a day setting up Postgres, Redis, and env vars by hand. Setup steps drifted between people.
Wrote a `docker-compose.yml` with versioned database, Redis, mailhog, and the app — plus a `.env.example` and a `make dev` target.
New-dev onboarding time dropped from half a day to ~15 minutes; setup drift disappeared because the compose file was the source of truth.
Hardened a container by dropping root and adding healthchecks
An old container ran as root with no healthcheck — security scans flagged it and the orchestrator could not tell when it was actually ready.
Added a non-root user, locked down file permissions, and exposed an explicit HEALTHCHECK + readiness endpoint. Verified with a security scanner before rollout.
Security scan went green, rollouts became reliable thanks to real readiness signals, and the audit team stopped flagging the service.
Often used together
Have a Docker project in mind?
I am open to full-time and contract work where Dockeris core to the stack. Let's talk about what you are building.