Docker changed how many teams 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 self-contained web apps across common stacks
  • Speed: Container images are cached and reused

Basic Docker Deployment

If your project has a Dockerfile, prev automatically detects and builds it:

prev create .
# 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 create --image myregistry.io/myapp:latest --port 3000

Private Registry Authentication

For private registries, use an image reference that your deployment environment can pull. If your registry needs extra credentials, configure access before deploying the image.

Multi-Service Applications

prev is designed for one web container per preview. For databases, use managed databases and attach them with --db; for larger multi-service systems, keep a dedicated staging environment or deploy a self-contained image that exposes one HTTP port.

Attach a Managed Database

prev create . --db app-postgres

Environment Variables

Pass environment-specific variables to your containers:

prev create . --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 create . --env-file .env.preview

Resource Configuration

Each preview gets a fixed resource profile based on the detected project type. For memory-heavy applications, keep the image lean and move durable state into a managed database or external service.

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

Use Build Logs

If a source deployment fails during image build, open the build logs in the dashboard to see the failing Docker step and the most recent build output.

Best Practices

  • Keep images small: Use Alpine-based images when possible
  • Don't run as root: Create a non-root user in your Dockerfile
  • Use .dockerignore: Exclude unnecessary files from the build context
  • Pin versions: Use specific image tags, not latest
  • Scan for vulnerabilities: Integrate security scanning in your pipeline
  • Conclusion

    Docker and preview environments are a practical match for self-contained web apps. With prev's Docker support, you can deploy the same container shape you expect to run elsewhere, without maintaining a shared staging server.

    Start with a small Dockerfile, keep the image lean, and attach managed services only where the preview really needs them.