Skip to content

Conversation

@bobbyonmagic
Copy link
Collaborator

@bobbyonmagic bobbyonmagic commented Dec 6, 2025

Summary

This PR simplifies Docker configuration to a single universal Dockerfile controlled by a simple BUILD_ENV build argument. No more multi-stage targets, no more separate files - just one Dockerfile that switches between development and production modes.

Problem

Previously, we had:

  • Dockerfile (~160 lines) - Production multi-stage build
  • Dockerfile.dev (~47 lines) - Development single-stage
  • Dockerfile.unified (176 lines) - Multi-target approach with development and production targets

All of this was overly complex for what should be a simple environment switch.

Solution

Created a single universal Dockerfile (110 lines) controlled by:

  • BUILD_ENV=production (default) - Installs nginx, builds assets, serves on port 80
  • BUILD_ENV=development - Skips nginx, runs dev server on port 3000

Changes

Added:

  • ✨ New universal Dockerfile with conditional logic

Modified:

  • 🛠️ docker-compose.yaml - Uses BUILD_ENV arg instead of targets
  • 🛠️ .dockerignore - Removed specific Dockerfile references
  • 🛠️ .github/workflows/docker-validate.yml - Lints new Dockerfile
  • 📝 README.md - Simplified Docker documentation

Removed:

  • 🗑️ Dockerfile.unified (multi-target approach)
  • 🗑️ Dockerfile.dev (old development-only)
  • 🗑️ Old production Dockerfile replaced with universal version

Benefits

  1. 🎯 Maximum Simplicity: One file, one argument (BUILD_ENV)
  2. 📦 Smaller: 110 lines vs 176 lines (unified) or 207 lines (2 files)
  3. Easier to Understand: Linear flow with simple conditionals
  4. 🛠️ Simpler Builds: No targets, just --build-arg BUILD_ENV=<mode>
  5. 🔄 Flexible: Easy to add new modes if needed

Architecture

Single Dockerfile with conditional logic:
├─ Install base packages (Node.js, pnpm)
├─ Conditionally install nginx (production only)
├─ Install dependencies (prod-only or all)
├─ Conditionally build assets (production only)
├─ Conditionally configure nginx (production only)
└─ Start command: nginx (prod) or pnpm dev (dev)

Usage

Docker Compose (Recommended)

# Dev mode - automatically passes BUILD_ENV=development
docker compose up dev

# Prod mode - automatically passes BUILD_ENV=production
docker compose up prod --build

Direct Docker Build

# Production (default)
docker build -t devops-daily:prod .

# Production (explicit)
docker build --build-arg BUILD_ENV=production -t devops-daily:prod .

# Development
docker build --build-arg BUILD_ENV=development -t devops-daily:dev .

Testing

  • Replaced Dockerfile.unified with universal Dockerfile
  • Removed Dockerfile.dev
  • Updated docker-compose.yaml with BUILD_ENV args
  • Updated .dockerignore
  • Updated docker validation workflow
  • Updated README documentation
  • Verify docker compose up dev works
  • Verify docker compose up prod works
  • GitHub Actions validation passes

Ready for review and testing!

This PR simplifies Docker configuration by replacing two separate
Dockerfiles with a single unified Dockerfile using build targets.

## Changes

### Files Added:
- `Dockerfile.unified` - New unified Dockerfile with 'development' and 'production' targets

### Files Modified:
- `docker-compose.yaml` - Updated to use unified Dockerfile with explicit targets
- `.dockerignore` - Keep ignoring Dockerfile.dev specifically
- `.github/workflows/docker-validate.yml` - Updated to lint unified Dockerfile
- `README.md` - Updated Docker documentation to reflect unified approach

### Files To Remove (in next commit):
- `Dockerfile` (old production-only)
- `Dockerfile.dev` (old development-only)

## Benefits

1. **Single Source of Truth**: One Dockerfile to maintain instead of two
2. **Shared Base Layers**: Common stages (base, deps, deps-dev) are reused
3. **Better Caching**: BuildKit can optimize shared layers between targets
4. **Simpler Maintenance**: Changes to Node/pnpm versions in one place
5. **Consistent Behavior**: Same base configuration for dev and prod

## How It Works

The unified Dockerfile has 5 stages:
- `base`: Common setup (Node.js, pnpm installation)
- `deps`: Production dependencies only
- `deps-dev`: All dependencies (including devDependencies)
- `development` (TARGET): Dev server with hot-reload
- `builder`: Builds Next.js static export
- `production` (TARGET): Nginx serving static export

Docker Compose automatically selects the correct target:
- `dev` service → `development` target
- `prod` service → `production` target

## Migration Path

Existing users can continue using docker-compose without changes.
Direct docker build commands need to specify `-f Dockerfile.unified` and `--target`.

Once validated, we'll remove the old Dockerfiles in a follow-up commit.
@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Dec 6, 2025

Deploying devops-daily with  Cloudflare Pages  Cloudflare Pages

Latest commit: 984ff41
Status: ✅  Deploy successful!
Preview URL: https://38124f9b.devops-daily.pages.dev
Branch Preview URL: https://refactor-unified-dockerfile.devops-daily.pages.dev

View logs

…rgument

- Removed Dockerfile.unified and Dockerfile.dev
- Created single Dockerfile that switches between dev/prod via BUILD_ENV
- Simplified docker-compose.yaml to use BUILD_ENV instead of targets
- Updated health checks to use curl for both environments
- Updated .dockerignore to remove specific Dockerfile references
- Updated docker validation workflow to lint new Dockerfile
- Updated README documentation with simpler build commands
- Architecture: One Dockerfile, two modes, controlled by single argument
@bobbyonmagic bobbyonmagic changed the title refactor: Consolidate Dockerfiles into unified multi-target approach refactor: Consolidate to single universal Dockerfile with BUILD_ENV argument Dec 6, 2025
- Add --no-install-recommends to apt-get install (DL3015)
- Escape $uri variables in nginx config (SC2016)
- Use JSON notation for CMD (DL3025)
- Improves security and follows Docker best practices
DL3008 and SC2016 are ignored because:
- Pinning apt package versions creates maintenance burden
- System packages are upgraded for security (apt-get upgrade)
- Echo statements for nginx config are properly escaped
- These checks are too strict for our use case
@bobbyonmagic bobbyonmagic merged commit 0b97326 into main Dec 6, 2025
3 checks passed
@bobbyonmagic bobbyonmagic deleted the refactor/unified-dockerfile branch December 6, 2025 17:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants