An Introduction to Docker: Stop asking your stakeholders to install Postgres! šŸš€

Published: (January 11, 2026 at 03:32 PM EST)
4 min read
Source: Dev.to

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:

  1. Install Node.js and PNPM.
  2. Set up a local Postgres instance.
  3. Switch to a Linux environment.
  4. 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

ConceptDescription
DockerfileBlueprint that defines how to build an image (OS, Node version, dependencies).
ImageRead‑only snapshot produced from a Dockerfile.
ContainerA 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_on ensures the app starts only after the DB container is up.
  • Named volume postgres_data persists 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:

  1. Build the Next.js image from the Dockerfile.
  2. Pull the Postgres image.
  3. Create a network linking the two containers.
  4. 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

Back to Blog

Related posts

Read more Ā»

Hello, Newbie Here.

Hi! I'm falling back into the realm of S.T.E.M. I enjoy learning about energy systems, science, technology, engineering, and math as well. One of the projects I...