npm package: @nesvel/docker-config
Description: Shared Dockerfile templates and Docker configurations for Node.js applications
Author: Nesvel
Latest version: 1.0.3

# @nesvel/docker-config

Production-ready Dockerfile templates and Docker configurations for Node.js applications.

## Features

- 🐳 **4 Optimized Templates**: Node.js, NestJS, Next.js, and Vite
- 🚀 **Multi-stage Builds**: Minimal production images
- 🔒 **Security First**: Non-root users, minimal attack surface
- 📦 **Smart Auto-detection**: Automatically detects your project type
- ⚡ **Performance Optimized**: Layer caching, fast builds
- 🛠️ **Helper Functions**: Generate .dockerignore and docker-compose.yml

## Installation

```bash
pnpm add -D @nesvel/docker-config
```

## Quick Start

### Automatic Installation (Recommended)

The smart installer automatically detects your project type and installs the appropriate Dockerfile:

```bash
# Auto-detect and install
pnpm docker-install

# Install with docker-compose.yml
pnpm docker-install --compose

# Manual template selection
pnpm docker-install --template=vite

# Install to specific directory
pnpm docker-install --dir=./apps/web
```

Alternatively, use the full path:

```bash
npx @nesvel/docker-config install
```

### Manual Installation

#### 1. Copy Template

Copy the appropriate Dockerfile template for your project:

```bash
# Node.js / Express
cp node_modules/@nesvel/docker-config/templates/node.dockerfile Dockerfile

# NestJS
cp node_modules/@nesvel/docker-config/templates/nestjs.dockerfile Dockerfile

# Next.js
cp node_modules/@nesvel/docker-config/templates/nextjs.dockerfile Dockerfile

# Vite / React / Vue
cp node_modules/@nesvel/docker-config/templates/vite.dockerfile Dockerfile
```

#### 2. Create .dockerignore

```bash
cat > .dockerignore << 'EOF'
node_modules
dist
build
.next
.git
.env*
!.env.example
EOF
```

## Templates

### Node.js

Generic Node.js application template with pnpm.

**Best for:** Express, Fastify, Koa, custom Node.js servers

**Features:**

- Multi-stage build (dependencies → builder → runner)
- Alpine Linux (minimal size)
- Non-root user
- Health checks
- Signal handling with dumb-init
- Production dependency pruning

**Build & Run:**

```bash
docker build -f node.dockerfile -t myapp:latest .
docker run -p 3000:3000 myapp:latest
```

### NestJS

Optimized for NestJS applications with TypeScript compilation.

**Best for:** NestJS APIs and microservices

**Features:**

- TypeScript compilation
- Production dependencies only
- Built-in health check endpoint support
- Proper signal handling
- Minimal image size

**Build & Run:**

```bash
docker build -f nestjs.dockerfile -t nest-api:latest .
docker run -p 3000:3000 nest-api:latest
```

### Next.js

Next.js with standalone output mode for minimal bundle size.

**Best for:** Next.js applications (SSR, SSG, or hybrid)

**Features:**

- Three-stage build (deps → builder → runner)
- Standalone output (~40MB production image)
- Static asset optimization
- Telemetry disabled
- Fast startup time

**Build & Run:**

```bash
docker build -f nextjs.dockerfile -t next-app:latest .
docker run -p 3000:3000 next-app:latest
```

**Requirements:**

- `output: 'standalone'` in next.config.js

### Vite

Vite SPA served with Nginx.

**Best for:** React, Vue, Svelte, or vanilla JS SPAs built with Vite

**Features:**

- Static file serving with Nginx
- SPA routing support (fallback to index.html)
- Gzip compression enabled
- API proxy configuration example
- Minimal image size (~25MB)
- Fast cold starts (<1s)

**Build & Run:**

```bash
docker build -f vite.dockerfile -t vite-app:latest .
docker run -p 80:80 vite-app:latest
```

## Programmatic Usage

### TypeScript/JavaScript API

```typescript
import { 
  templates, 
  generateDockerignore, 
  generateComposeService 
} from '@nesvel/docker-config';

// List available templates
console.log(templates);
// {
//   node: { name: 'node', path: 'templates/node.dockerfile', ... },
//   nestjs: { ... },
//   nextjs: { ... },
//   vite: { ... }
// }

// Generate .dockerignore content
const dockerignore = generateDockerignore([
  '*.log',
  'tmp/',
]);

// Generate docker-compose service configuration
const service = generateComposeService('nestjs', {
  name: 'api',
  port: 3001,
  environment: {
    DATABASE_URL: 'postgres://localhost:5432/db',
  },
  volumes: ['./uploads:/app/uploads'],
  dependsOn: ['postgres', 'redis'],
});
```

### Custom Build Scripts

```typescript
// build-docker.ts
import { templates } from '@nesvel/docker-config';
import { execSync } from 'child_process';

const template = templates.nextjs;
const imageName = 'my-nextjs-app:latest';

console.log(`Building with ${template.name} template...`);
execSync(
  `docker build -f ${template.path} -t ${imageName} .`,
  { stdio: 'inherit' }
);
```

## Docker Compose Integration

### Generate Configuration Programmatically

```typescript
import { generateComposeService } from '@nesvel/docker-config';
import { writeFileSync } from 'fs';
import YAML from 'yaml';

const services = {
  web: generateComposeService('nextjs', {
    name: 'web',
    port: 3000,
    dependsOn: ['api'],
  }),
  api: generateComposeService('nestjs', {
    name: 'api',
    port: 3001,
    environment: {
      DATABASE_URL: 'postgres://db:5432/mydb',
    },
    dependsOn: ['db'],
  }),
  db: {
    image: 'postgres:16-alpine',
    environment: {
      POSTGRES_DB: 'mydb',
      POSTGRES_PASSWORD: 'password',
    },
    volumes: ['postgres-data:/var/lib/postgresql/data'],
  },
};

const compose = {
  version: '3.8',
  services,
  volumes: { 'postgres-data': null },
};

writeFileSync('docker-compose.yml', YAML.stringify(compose));
```

### Manual docker-compose.yml

```yaml
version: '3.8'

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "3000:3000"
    environment:
      NODE_ENV: production
      DATABASE_URL: postgres://db:5432/mydb
    depends_on:
      - db
    restart: unless-stopped

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: mydb
      POSTGRES_PASSWORD: password
    volumes:
      - postgres-data:/var/lib/postgresql/data

volumes:
  postgres-data:
```

## Advanced Usage

### Monorepo Setup

For monorepo projects, build from the root and specify the app context:

```bash
# Build from monorepo root
docker build \
  -f packages/api/Dockerfile \
  -t api:latest \
  --build-context workspace=. \
  .

# Or use docker-compose with build context
services:
  api:
    build:
      context: .
      dockerfile: apps/api/Dockerfile
```

### Build Arguments

Add custom build arguments to your Dockerfile:

```dockerfile
# Add after ARG NODE_VERSION in template
ARG API_URL
ENV NEXT_PUBLIC_API_URL=$API_URL
```

Then build with:

```bash
docker build --build-arg API_URL=https://api.example.com -t app:latest .
```

### Multi-platform Builds

Build for multiple architectures:

```bash
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t myapp:latest \
  --push \
  .
```

### Development vs Production

Create separate Dockerfiles:

```dockerfile
# Dockerfile.dev
FROM node:22-alpine
WORKDIR /app
RUN corepack enable pnpm
COPY package.json pnpm-lock.yaml ./
RUN pnpm install
COPY . .
CMD ["pnpm", "dev"]
```

```bash
# Development
docker-compose -f docker-compose.dev.yml up

# Production
docker-compose -f docker-compose.yml up
```

## TypeScript Types

All templates and utilities are fully typed:

```typescript
import type { 
  DockerTemplate,
  DockerComposeService,
  ComposeServiceOptions,
} from '@nesvel/docker-config';

const template: DockerTemplate = {
  name: 'custom',
  path: 'custom.dockerfile',
  description: 'Custom template',
  features: ['feature1', 'feature2'],
};

const options: ComposeServiceOptions = {
  name: 'api',
  port: 3000,
  environment: { NODE_ENV: 'production' },
};
```

## Best Practices

### 1. Use .dockerignore

Always create a `.dockerignore` to reduce build context size:

```bash
npx @nesvel/docker-config install  # Generates .dockerignore automatically
```

### 2. Layer Caching

Order Dockerfile commands from least to most frequently changing:

```dockerfile
# ✅ Good - Dependencies cached unless package.json changes
COPY package.json pnpm-lock.yaml ./
RUN pnpm install
COPY . .

# ❌ Bad - Cache invalidated on any file change
COPY . .
RUN pnpm install
```

### 3. Multi-stage Builds

All templates use multi-stage builds to minimize production image size:

- **Build stage**: Compile TypeScript, bundle assets
- **Production stage**: Only runtime files, no dev dependencies

### 4. Security

- Run as non-root user (all templates do this)
- Keep base images updated
- Use specific version tags (not `latest`)
- Scan images: `docker scan myapp:latest`

### 5. Health Checks

Add health checks for container orchestration:

```dockerfile
HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
  CMD node -e "require('http').get('http://localhost:3000/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1))"
```

## Troubleshooting

### Build Fails with "Cannot find module"

Ensure your `package.json` has a `build` script:

```json
{
  "scripts": {
    "build": "tsc" // or "vite build", "next build", etc.
  }
}
```

### Image Size Too Large

Check for:

- Unused dependencies (use `pnpm install --prod`)
- Missing `.dockerignore`
- Not using multi-stage builds

### Permission Errors

The templates use non-root users. If you need to write files, ensure directories are writable:

```dockerfile
RUN chown -R nodejs:nodejs /app/uploads
```

### Port Already in Use

Map to a different host port:

```bash
docker run -p 8080:3000 myapp:latest  # Host:Container
```

## Migration Guide

### From Docker Hub Official Images

Replace:

```dockerfile
FROM node:22-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
CMD ["npm", "start"]
```

With:

```bash
npx @nesvel/docker-config install --template=node
```

Benefits:

- Production-optimized multi-stage build
- pnpm for faster installs
- Non-root user
- Health checks
- Proper signal handling

## Contributing

Contributions welcome! Please read our [Contributing Guide](../../CONTRIBUTING.md).

## License

MIT © Nesvel

## Related Packages

- [@nesvel/typescript-config](../typescript-config) - Shared TypeScript configurations
- [@nesvel/eslint-config](../eslint-config) - Shared ESLint configurations
- [@nesvel/prettier-config](../prettier-config) - Shared Prettier configurations

## Support

- 📖 [Documentation](https://github.com/nesvel/enterprise-platform/tree/main/packages/tools/docker-config)
- 🐛 [Issue Tracker](https://github.com/nesvel/enterprise-platform/issues)
- 💬 [Discussions](https://github.com/nesvel/enterprise-platform/discussions)