Skip to content

Docker Deployment Guide

HomeDocumentationSetup → Docker Deployment

Deploy Cesivi Server using Docker for production, development, and CI/CD environments.

Table of Contents

Quick Start

Fastest way to get running with Docker:

# Start container with Docker Compose
docker-compose up -d

# Verify container is running
docker-compose ps

# Check health
curl http://localhost:8080/_vti_bin/health

# View logs
docker-compose logs -f

Stop and cleanup:

docker-compose down

Docker Compose Setup

Default docker-compose.yml

The repository includes a production-ready docker-compose.yml:

version: '3.8'

services:
  cesivi:
    build:
      context: .
      dockerfile: Dockerfile
    image: Cesivi:latest
    container_name: cesivi-server
    hostname: mocksharepoint.local
    ports:
      - "8080:8080"
    environment:
      - ASPNETCORE_ENVIRONMENT=Production
      - ASPNETCORE_URLS=http://+:8080
      - Cesivi__DataRootPath=/app/MockData
      - Cesivi__HostName=mocksharepoint.local
    volumes:
      - ./MockData:/app/MockData
      - ./logs:/app/logs
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/_vti_bin/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    restart: unless-stopped

Start Container

# Build and start
docker-compose up -d

# Build without cache (after code changes)
docker-compose build --no-cache
docker-compose up -d

# View logs
docker-compose logs -f cesivi

# Check status
docker-compose ps

Stop Container

# Stop (keeps containers)
docker-compose stop

# Stop and remove containers
docker-compose down

# Stop and remove volumes (DELETES DATA!)
docker-compose down -v

Rebuild After Code Changes

# Stop existing container
docker-compose down

# Rebuild image (no cache)
docker-compose build --no-cache

# Start new container
docker-compose up -d

# Verify
curl http://localhost:8080/_vti_bin/health

Docker CLI Setup

Build Docker Image

# Build image
docker build -t Cesivi:latest .

# Build with specific tag
docker build -t Cesivi:1.0.0 .

# Build without cache
docker build --no-cache -t Cesivi:latest .

Run Container

Basic run:

docker run -d \
  --name cesivi-server \
  -p 8080:8080 \
  Cesivi:latest

Production run with volumes:

docker run -d \
  --name cesivi-server \
  --hostname mocksharepoint.local \
  -p 8080:8080 \
  -e ASPNETCORE_ENVIRONMENT=Production \
  -e Cesivi__DataRootPath=/app/MockData \
  -e Cesivi__HostName=mocksharepoint.local \
  -v ./MockData:/app/MockData \
  -v ./logs:/app/logs \
  --restart unless-stopped \
  Cesivi:latest

Manage Container

# List running containers
docker ps

# View logs
docker logs -f cesivi-server

# Execute command in container
docker exec -it cesivi-server bash

# Stop container
docker stop cesivi-server

# Start stopped container
docker start cesivi-server

# Remove container
docker rm cesivi-server

# Remove container and volumes
docker rm -v cesivi-server

Volume Mapping

MockData Persistence

Why volume mapping? - Data persists after container restart - Data survives container removal - Easy backup and restore - Can share data between containers

Volume mapping syntax:

-v <host-path>:<container-path>

Example Configurations

1. Relative path (development):

volumes:
  - ./MockData:/app/MockData

2. Absolute path (production):

volumes:
  - /var/lib/Cesivi/data:/app/MockData
  - /var/log/Cesivi:/app/logs

3. Named volumes (Docker-managed):

volumes:
  - mockdata:/app/MockData
  - logs:/app/logs

volumes:
  mockdata:
    driver: local
  logs:
    driver: local

4. Read-only volumes:

volumes:
  - ./config:/app/config:ro

Backup and Restore

Backup MockData:

# Create backup from running container
docker exec cesivi-server tar czf /tmp/backup.tar.gz /app/MockData

# Copy backup to host
docker cp cesivi-server:/tmp/backup.tar.gz ./mockdata-backup.tar.gz

# Or backup from host-mapped volume
tar czf mockdata-backup.tar.gz ./MockData

Restore MockData:

# Stop container
docker-compose down

# Restore from backup
tar xzf mockdata-backup.tar.gz

# Start container
docker-compose up -d

Environment Configuration

Common Environment Variables

# ASP.NET Core
ASPNETCORE_ENVIRONMENT=Production
ASPNETCORE_URLS=http://+:8080

# Cesivi
Cesivi__DataRootPath=/app/MockData
Cesivi__LogPath=/app/logs
Cesivi__HostName=mocksharepoint.local

# Performance
Cesivi__Performance__CacheEnabled=true
Cesivi__Performance__CacheDurationMinutes=30

# Logging
Logging__LogLevel__Default=Information
Logging__LogLevel__Microsoft.AspNetCore=Warning

Docker Compose with .env File

Create .env file:

# .env
ASPNETCORE_ENVIRONMENT=Production
MOCKDATA_PATH=/app/MockData
HTTP_PORT=8080
CONTAINER_NAME=cesivi-server

Use in docker-compose.yml:

services:
  cesivi:
    container_name: ${CONTAINER_NAME}
    ports:
      - "${HTTP_PORT}:8080"
    environment:
      - ASPNETCORE_ENVIRONMENT=${ASPNETCORE_ENVIRONMENT}
      - Cesivi__DataRootPath=${MOCKDATA_PATH}

Multi-Instance Deployment

Run multiple containers on different ports:

docker-compose-dev.yml:

services:
  cesivi-dev:
    image: Cesivi:latest
    container_name: spmock-dev
    ports:
      - "8080:8080"
    volumes:
      - ./MockData-dev:/app/MockData

docker-compose-staging.yml:

services:
  cesivi-staging:
    image: Cesivi:latest
    container_name: spmock-staging
    ports:
      - "8081:8080"
    volumes:
      - ./MockData-staging:/app/MockData

Start both:

docker-compose -f docker-compose-dev.yml up -d
docker-compose -f docker-compose-staging.yml up -d

Health Checks

Docker Health Check

The Dockerfile includes a built-in health check:

HEALTHCHECK --interval=30s --timeout=10s --retries=3 --start-period=40s \
  CMD curl -f http://localhost:8080/_vti_bin/health || exit 1

Check Container Health

# View health status
docker ps

# Output shows health status:
# CONTAINER ID   STATUS
# abc123def456   Up 5 minutes (healthy)

# Detailed health information
docker inspect cesivi-server | grep -A 10 Health

# View health check logs
docker inspect cesivi-server --format='{{json .State.Health}}' | jq

Custom Health Checks

For load balancers:

# Endpoint: GET /_vti_bin/health
# Expected: 200 OK with {"status": "Healthy"}
curl http://localhost:8080/_vti_bin/health

For orchestration (Kubernetes):

livenessProbe:
  httpGet:
    path: /_vti_bin/health
    port: 8080
  initialDelaySeconds: 40
  periodSeconds: 30
  timeoutSeconds: 10
  failureThreshold: 3

readinessProbe:
  httpGet:
    path: /_vti_bin/health
    port: 8080
  initialDelaySeconds: 20
  periodSeconds: 10
  timeoutSeconds: 5
  failureThreshold: 3

Production Best Practices

1. Security

Run as non-root user:

Dockerfile already includes this:

RUN addgroup --gid 1000 appuser && \
    adduser --uid 1000 --gid 1000 --disabled-password --gecos "" appuser
USER appuser

Use secrets for sensitive data:

# Don't use environment variables for secrets
# Use Docker secrets (Swarm) or Kubernetes secrets

# Docker Swarm example
echo "my-secret-token" | docker secret create api-token -
docker service create \
  --secret api-token \
  Cesivi:latest

Restrict network access:

services:
  cesivi:
    networks:
      - internal
    # Only expose via reverse proxy

  nginx:
    networks:
      - internal
      - external
    ports:
      - "443:443"

networks:
  internal:
    internal: true
  external:

2. Reverse Proxy (SSL Termination)

nginx as reverse proxy:

# /etc/nginx/conf.d/cesivi.conf
upstream cesivi {
    server 127.0.0.1:8080;
}

server {
    listen 443 ssl http2;
    server_name mocksharepoint.example.com;

    ssl_certificate /etc/nginx/ssl/cert.pem;
    ssl_certificate_key /etc/nginx/ssl/key.pem;

    location / {
        proxy_pass http://cesivi;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection keep-alive;
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Docker Compose with nginx:

version: '3.8'

services:
  cesivi:
    image: Cesivi:latest
    networks:
      - internal
    volumes:
      - ./MockData:/app/MockData

  nginx:
    image: nginx:alpine
    ports:
      - "443:443"
    networks:
      - internal
      - external
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
      - ./ssl:/etc/nginx/ssl:ro
    depends_on:
      - cesivi

networks:
  internal:
  external:

3. Resource Limits

services:
  cesivi:
    image: Cesivi:latest
    deploy:
      resources:
        limits:
          cpus: '2.0'
          memory: 2G
        reservations:
          cpus: '0.5'
          memory: 512M

4. Logging

Docker logging driver:

services:
  cesivi:
    image: Cesivi:latest
    logging:
      driver: "json-file"
      options:
        max-size: "100m"
        max-file: "10"

Forward logs to centralized system:

services:
  cesivi:
    image: Cesivi:latest
    logging:
      driver: "syslog"
      options:
        syslog-address: "tcp://logserver:514"
        tag: "Cesivi"

5. Auto-Restart Policy

services:
  cesivi:
    image: Cesivi:latest
    restart: unless-stopped  # or "always", "on-failure"

Restart policies: - no - Never restart (default) - always - Always restart on failure - on-failure - Restart only on error exit code - unless-stopped - Always restart unless manually stopped

Troubleshooting

Issue: Container Won't Start

Check logs:

docker-compose logs cesivi
docker logs cesivi-server

Common causes: - Port already in use - Invalid environment variables - Volume mount permission errors - Missing required files

Issue: Port Already in Use

Symptoms:

Error: bind: address already in use

Solution:

# Find process using port
netstat -ano | findstr :8080

# Kill process or use different port
docker-compose down
# Edit docker-compose.yml to use different port
# ports:
#   - "8081:8080"
docker-compose up -d

Issue: Volume Permission Denied

Symptoms:

System.UnauthorizedAccessException: Access to path '/app/MockData' is denied

Solution:

# Fix permissions on host
sudo chown -R 1000:1000 ./MockData

# Or run container as root (not recommended for production)
docker run -u root ...

Issue: Health Check Failing

Check health:

docker inspect cesivi-server --format='{{json .State.Health}}' | jq

Common causes: - Server not fully started (increase start_period) - Port not exposed correctly - Application crashed

Solution:

# Increase start period in docker-compose.yml
healthcheck:
  start_period: 60s  # Give more time to start

# Check application logs
docker-compose logs cesivi

Issue: Container Exits Immediately

Check exit code:

docker ps -a
docker logs cesivi-server

Solution:

# Run interactively to debug
docker run -it --rm Cesivi:latest bash

# Or check application logs
docker-compose logs -f

Issue: Can't Access from Host

Symptoms: - curl http://localhost:8080 fails - Container is running

Solution:

# Verify container is listening
docker exec cesivi-server netstat -tuln | grep 8080

# Check firewall
sudo ufw status
sudo ufw allow 8080/tcp

# Verify port mapping
docker port cesivi-server

Kubernetes Deployment

Example Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: cesivi
spec:
  replicas: 2
  selector:
    matchLabels:
      app: cesivi
  template:
    metadata:
      labels:
        app: cesivi
    spec:
      containers:
      - name: cesivi
        image: Cesivi:latest
        ports:
        - containerPort: 8080
        env:
        - name: ASPNETCORE_ENVIRONMENT
          value: "Production"
        - name: Cesivi__DataRootPath
          value: "/app/MockData"
        volumeMounts:
        - name: mockdata
          mountPath: /app/MockData
        livenessProbe:
          httpGet:
            path: /_vti_bin/health
            port: 8080
          initialDelaySeconds: 40
          periodSeconds: 30
        readinessProbe:
          httpGet:
            path: /_vti_bin/health
            port: 8080
          initialDelaySeconds: 20
          periodSeconds: 10
        resources:
          limits:
            cpu: "2"
            memory: "2Gi"
          requests:
            cpu: "500m"
            memory: "512Mi"
      volumes:
      - name: mockdata
        persistentVolumeClaim:
          claimName: cesivi-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: cesivi
spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: cesivi

Next Steps

Support Resources


← Back to Setup | Next: Configuration → | View All Docs