Docker has revolutionized how we package and deploy applications. Combined with preview environments, you can ensure that what works in development works exactly the same way in your preview—and eventually in production.
Why Docker for Preview Environments?
Docker provides several advantages for preview environments:
- Consistency: Same container runs everywhere
- Isolation: Dependencies are bundled together
- Flexibility: Run any stack, any language
- Speed: Container images are cached and reused
Basic Docker Deployment
If your project has a Dockerfile, prev automatically detects and builds it:
prev
# Automatically detects Dockerfile and builds the image
Sample Dockerfile
Here's a basic Dockerfile for a Node.js application:
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
Deploying Pre-built Images
Already have an image in a registry? Deploy it directly:
prev --image myregistry.io/myapp:latest
Private Registry Authentication
For private registries, configure authentication:
prev --image registry.gitlab.com/team/app:v1.2 \
--registry-user $REGISTRY_USER \
--registry-password $REGISTRY_PASSWORD
Multi-Container Applications
For applications with multiple services (API, database, cache), use Docker Compose:
docker-compose.yml
version: '3.8'
services:
web:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgres://db:5432/app
- REDIS_URL=redis://cache:6379
depends_on:
- db
- cache
db:
image: postgres:15-alpine
environment:
- POSTGRES_DB=app
- POSTGRES_PASSWORD=secret
volumes:
- pgdata:/var/lib/postgresql/data
cache:
image: redis:7-alpine
volumes:
pgdata:
Deploy with Compose
prev --compose
Environment Variables
Pass environment-specific variables to your containers:
prev --env NODE_ENV=preview \
--env API_KEY=$STAGING_API_KEY \
--env LOG_LEVEL=debug
Using .env Files
For multiple variables, use an env file:
prev --env-file .env.preview
Build Arguments
Pass build-time arguments to your Dockerfile:
prev --build-arg VERSION=1.2.3 \
--build-arg BUILD_DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ)
Resource Configuration
Specify resource limits for your preview:
prev --memory 512m --cpu 0.5
Health Checks
Ensure your container is healthy before the preview URL goes live:
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
Optimizing Docker Builds
Multi-stage Builds
Reduce image size with multi-stage builds:
# Build stage
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Production stage
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/index.js"]
Layer Caching
Order your Dockerfile commands to maximize cache hits:
# Dependencies change less frequently
COPY package*.json ./
RUN npm ci
# Source code changes more frequently
COPY . .
RUN npm run build
Debugging Docker Previews
Access Container Logs
prev logs my-preview
Execute Commands in Container
prev exec my-preview -- sh
Check Resource Usage
prev stats my-preview
Best Practices
latestConclusion
Docker and preview environments are a perfect match. With prev's Docker support, you can deploy complex applications with confidence, knowing that your preview environment mirrors production exactly.
Start containerizing your previews today—your future self will thank you.