An Introduction to Docker: Stop asking your stakeholders to install Postgres! š
Source: Dev.to
I once asked a major stakeholder to install Postgres on his laptop just to see my progress.
It was SeptemberāÆ2024 ā early in my career ā and the shame of that moment still fuels my obsession with Docker and developer experience (DX) today.
The project was in its early stages. When the stakeholder asked to try it himself, I gave him a toādo list:
- Install Node.js and PNPM.
- Set up a local Postgres instance.
- Switch to a Linux environment.
- Manually configure credentials and run migrations.
I didnāt share a project; I shared a liability.
Today, I donāt ship code; I ship environments.
That experience was my wakeāup call. As a developer, my job isnāt just to write code ā itās to deliver value. If a stakeholder or a new teammate canāt run the project in minutes, Iāve failed.
Why Docker for Development?
Docker is often marketed as a DevOps tool, but itās equally powerful for professional development environments.
The manual alternative
- Install Postgres on your machine
- Set up WSL (or another Linux layer)
- Ensure each service is running
- Configure each service individually
- Verify version compatibility
- ā¦and so on
The Docker alternative
āInstall Docker Desktop and run a few commands to start building.ā
Quick sanity check
docker --version # Verify Docker is installed
docker run hello-world # Pull an image and spin it up in seconds
Docker lets you package code, runtime, and libraries into a single unit called a container that runs on any OS/machine.
- VMs are heavy: they need a full OS copy and consume significant RAM/CPU.
- Containers share the host OS kernel and only install the libraries they need.
Core Docker Concepts
| Concept | Description |
|---|---|
| Dockerfile | Blueprint that defines how to build an image (OS, Node version, dependencies). |
| Image | Readāonly snapshot produced from a Dockerfile. |
| Container | A running instance of an image; you can start/stop/delete it without affecting your host. |
Solving the āPostgres Headacheā with Docker Compose
Remember the stakeholderās list? With Docker Compose, the entire manual process becomes a single command:
docker compose up
Think of each service (app, database, message queue) as an instrument. In a dockerācompose.yaml file you orchestrate them in YAML, turning a band of services into a harmonious whole.
Note: Docker Compose is ideal for development environments and small MVPs. For largeāscale production youāll eventually need load balancers and Kubernetes.
Project Structure
/project-root
ā
āā docker-compose.yaml
āā Dockerfile
āā .dockerignore
Dockerfile (Next.js app)
# Dockerfile
FROM node:20-alpine
# Install pnpm globally
RUN npm install -g pnpm
# Set working directory
WORKDIR /app
# Install dependencies
COPY package.json pnpm-lock.yaml* ./
RUN pnpm install
# Copy source code
COPY . .
# Expose the dev server port
EXPOSE 3000
# Start the app
CMD ["pnpm", "dev"]
.dockerignore
Just like .gitignore, this file prevents unnecessary or sensitive files from being added to the image.
node_modules
.pnpm-debug.log
.next
out
build
.env
.env.local
.env*.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
.git
.gitignore
.DS_Store
Thumbs.db
dockerācompose.yaml
# docker-compose.yaml
services:
db:
image: postgres:15-alpine
container_name: nextjs-db
restart: always
environment:
POSTGRES_USER: admin
POSTGRES_PASSWORD: supersecretpassword
POSTGRES_DB: db
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
app:
build: .
container_name: nextjs-app
ports:
- "3000:3000"
environment:
DATABASE_URL: postgresql://admin:supersecretpassword@db:5432/db
volumes:
- .:/app
- /app/node_modules
depends_on:
- db
command: pnpm dev
volumes:
postgres_data:
Key points
- Base image:
node:20-alpine(lightweight; you can pick another Node image if needed). depends_onensures the app starts only after the DB container is up.- Named volume
postgres_datapersists DB data across container restarts. - Healthchecks (optional) can be added to make the dependency more robust.
OneāCommand Setup
With the three files above in your project root, youāve turned a 1āhour manual setup into a 10āsecond command:
docker compose up
Docker will:
- Build the Next.js image from the
Dockerfile. - Pull the Postgres image.
- Create a network linking the two containers.
- Start the dev server with hotāreload enabled.
You can also add startup or seeding scripts as needed.
Takeaway
I used to think Docker was only a complex DevOps toolāuntil that afternoon in 2024 when I realized seniority isnāt just about writing fancy code, but about using code as a tool for the business.
By shipping environments instead of just code, I reclaimed my time, improved onboarding, and delivered real value.
Ready to turn your āPostgres headacheā into a oneācommand workflow? š
Containerizing Your Development Environment
Teamās DX, and made sure that no stakeholder ever has to install a database on their laptop again.
If you want to scale your project or your career, start containerizing today. Your future self and your team will thank you.
What was your worst setup story? Share below in the comments!
I help startups engineer scalable applications and internal tools that stay fast as they grow. See how I build scalable systems here: š www.itsfranciscoluna.com