Back to Posts

Dockerizing My Local Development Environment | Sodiq Ardianto

January 10, 2025

3 min read

Dockerizing My Local Development Environment

For years, I managed my development environment manually - installing PHP, MySQL, Node.js versions directly on my machine. It worked until it didn’t. “Works on my machine” became an all-too-familiar phrase. Here’s how Docker changed my workflow.

The Problem with Manual Setup

Last year, I was working on three different Laravel projects simultaneously:

Switching between them was a nightmare. PHP version managers helped, but database versions and other dependencies were still painful.

My Current Docker Setup

I now use Docker Compose for all projects. Here’s a typical docker-compose.yml for my Laravel projects:

version: '3.8'

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - .:/var/www/html
    ports:
      - "8000:8000"
    environment:
      - APP_ENV=local
      - DB_HOST=db
    depends_on:
      - db
      - redis

  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_DATABASE: myapp
    volumes:
      - db_data:/var/lib/mysql
    ports:
      - "3306:3306"

  redis:
    image: redis:alpine
    ports:
      - "6379:6379"

  frontend:
    image: node:20-alpine
    working_dir: /app
    volumes:
      - ./frontend:/app
    command: npm run dev
    ports:
      - "3000:3000"

volumes:
  db_data:

The Benefits

1. Consistency Across Teams

New team member onboarding is now:

git clone <repo>
cd project
docker-compose up -d

No more “install PHP, then MySQL, then Redis, then…“

2. Isolation

Each project runs in its own container with exact versions it needs. No conflicts, no surprises.

3. Production Parity

My local environment now closely mirrors production. I caught a bug last month that only appeared in MySQL 8.0’s strict mode - something I would have missed with my old setup.

Frontend Development with Docker

For React/Vue projects, I use a multi-stage Dockerfile:

# Development stage
FROM node:20-alpine AS development
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
EXPOSE 3000
CMD ["npm", "run", "dev"]

# Production build stage
FROM node:20-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Production runtime (nginx)
FROM nginx:alpine AS production
COPY --from=build /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf

Common Commands I Use

Created some handy aliases in my .zshrc:

alias dcu="docker-compose up -d"
alias dcd="docker-compose down"
alias dcr="docker-compose restart"
alias dce="docker-compose exec app"
alias dcl="docker-compose logs -f"

Running artisan commands:

docker-compose exec app php artisan migrate
docker-compose exec app php artisan tinker

The Learning Curve

Docker isn’t without its challenges:

But the benefits far outweigh the initial learning investment.

My Recommendation

If you’re still managing local dependencies manually, give Docker a try. Start with a simple docker-compose.yml for your next project. You might struggle for the first few days, but you’ll thank yourself later.

Have you Dockerized your dev environment? What challenges did you face?

Written by Sodiq Ardianto

January 10, 2025 · 3 min read

Back to all posts