Skip to content

Docker Deployment

Overview

Docker provides the fastest path to running CoSky in production. The official multi-arch image (ahoowang/cosky) supports both linux/amd64 and linux/arm64 platforms and is published to Docker Hub, GitHub Container Registry (GHCR), and Alibaba Cloud Container Registry on every release. The image bundles the CoSky REST API server, the built-in dashboard UI, and all required runtime dependencies into a single container that only needs a Redis instance to connect to.

Quick Start

Pull the latest image and start CoSky with a single command:

bash
# Pull the latest image
docker pull ahoowang/cosky:latest

# Run CoSky
docker run --name cosky -d -p 8080:8080 \
  -e SPRING_DATA_REDIS_URL=redis://your-redis-host:6379 \
  ahoowang/cosky:latest

Once the container is running, open http://localhost:8080 to access the CoSky Dashboard. On first launch the super-user password is printed to the console log:

bash
docker logs cosky

Look for a line like:

---------------- ****** CoSky -  init super user:[cosky] password:[xxxxxxxx] ****** ----------------

Container Architecture

The Docker image is built from a multi-stage Dockerfile based on Dragonwell JDK 21. The build stage installs the Gradle distribution, and the runtime stage runs as a non-root user (appuser) with a built-in health check.

mermaid
flowchart TB
    subgraph Docker Build Pipeline
        style Docker Build Pipeline fill:#161b22,stroke:#30363d,color:#e6edf3
        B1["Stage 1: base<br>Dragonwell JDK 21"] --> B2["Stage 2: build<br>copy install dist"]
        B2 --> B3["Stage 3: run<br>non-root appuser<br>HEALTHCHECK configured"]
    end

    B1:::node
    B2:::node
    B3:::node

    classDef node fill:#2d333b,stroke:#6d5dfc,color:#e6edf3

Deployment Topology

A typical Docker Compose deployment consists of the CoSky container and a Redis container connected via an internal Docker networ```mermaid flowchart LR subgraph docker-compose network style docker-compose network fill:#161b22,stroke:#30363d,color:#e6edf3 C["CoSky Container
:8080"] -->|"SPRING_DATA_REDIS_URL
redis://redis:6379"| R["Redis Container
:6379"] U["User / Browser"] -->|"HTTP :8080"| C C -.->|"Health Check
/actuator/health"| C end

C:::node
R:::node
U:::node

classDef node fill:#2d333b,stroke:#6d5dfc,color:#e6edf3

Environment Variables

VariableDefaultDescription
SPRING_DATA_REDIS_URL(required)Redis connection URL (e.g. redis://localhost:6379)
SPRING_DATA_REDIS_HOSTlocalhostRedis host (alternative to URL)
SPRING_DATA_REDIS_PASSWORD(none)Redis password
SERVER_PORT8080HTTP port for the REST API and dashboard
COSKY_SECURITY_ENABLEDtrueEnable CoSec JWT authentication
COSKY_SUPER_INITfalseForce re-initialization of the super-user password
COSKY_SECURITY_KEYbuilt-in secretJWT signing secret for CoSec tokens
COSKY_NAMESPACEcosky-{system}Default namespace
COSKY_AUTO_REGISTRYtrueAuto-register CoSky itself as a service
LANG(none)Set locale (e.g. C.utf8)
TZ(none)Timezone (e.g. Asia/Shanghai)

When running in cluster mode with Redis Cluster, use SPRING_DATA_REDIS_CLUSTER_NODES instead of SPRING_DATA_REDIS_URL, and set SPRING_DATA_REDIS_CLUSTER_MAX_REDIRECTS=3.

Docker Compose Example

The following docker-compose.yml starts CoSky together with Redis:

yaml
version: "3.8"

services:
  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redis-data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5

  cosky:
    image: ahoowang/cosky:latest
    ports:
      - "8080:8080"
    environment:
      SPRING_DATA_REDIS_URL: redis://redis:6379
      COSKY_SECURITY_ENABLED: "true"
      TZ: Asia/Shanghai
    depends_on:
      redis:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
      interval: 30s
      timeout: 3s
      retries: 3

volumes:
  redis-data:

Startup Sequence

The following diagram illustrates the container startup and health check flow:

mermaid
sequenceDiagram
    autonumber
    participant D as Docker Engine
    participant R as Redis Container
    participant C as CoSky Container
    participant H as Health Check

    D->>R: start redis
    R-->>D: healthy (redis-cli ping)
    D->>C: start cosky
    C->>R: connect via SPRING_DATA_REDIS_URL
    R-->>C: connection established
    C->>C: Spring Boot startup
    C->>C: load application.yaml
    C->>C: init CoSec JWT auth
    C->>C: register self as service
    C-->>D: container ready
    H->>C: GET /actuator/health
    C-->>H: 200 OK

Volume Mounts

Mount PathPurposeRequired
/etc/localtimeSync container timezone with hostRecommended

The CoSky container mounts the host's /etc/localtime to ensure log timestamps and audit records match the host timezone. This is configured in both the Kubernetes manifests and the Docker Compose example above.

Health Check Configuration

The Docker image includes a built-in HEALTHCHECK instruction that pings the Spring Boot Actuator health endpoint:

dockerfile
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
  CMD curl -f http://localhost:8080/actuator/health || exit 1

For Kubernetes deployments, the following probe paths are available:

ProbePathPurpose
Startup/actuator/healthVerifies the application has fully started
Readiness/actuator/health/readinessIndicates the pod can accept traffic
Liveness/actuator/health/livenessConfirms the application is still running

Networking

CoSky exposes port 8080 by default. In the Docker Compose setup, the CoSky and Redis containers share an internal network where Redis is reachable by its service name (redis://redis:6379). No Redis ports need to be exposed to the host unless you want direct access for debu```mermaid flowchart TB subgraph Docker Network style Docker Network fill:#161b22,stroke:#30363d,color:#e6edf3 subgraph cosky container style cosky container fill:#161b22,stroke:#30363d,color:#e6edf3 A["Spring Boot App
port 8080"] --> B["Dashboard UI
static files"] A --> C["REST API
/actuator/*"] A --> D["CoSec Auth
JWT validation"] end subgraph redis container style redis container fill:#161b22,stroke:#30363d,color:#e6edf3 E["Redis Server
port 6379"] end A -->|"Lettuce client"| E F["External Client"] -->|":8080"| A end

A:::node
B:::node
C:::node
D:::node
E:::node
F:::node

classDef node fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
edf3

CI/CD Pipeline

The Docker Image Deploy workflow builds and pushes images on every push and tag. The pipeline builds the dashboard UI with pnpm, creates the Gradle distribution, then uses Docker Buildx to produce multi-arch images for linux/amd64 and linux/arm64.

Images are published to three registries:

RegistryImage
Docker Hubahoowang/cosky
GitHub Container Registryghcr.io/ahoo-wang/cosky
Alibaba Cloud CRregistry.cn-shanghai.aliyuncs.com/ahoo/cosky

Feature Comparison

FeatureCoSkyEurekaConsulNacosApollo
CAPCP+APAPCPCP+APCP+AP
Health CheckClient BeatClient BeatTCP/HTTP/gRPCTCP/HTTP/Client BeatClient Beat
Access ProtocolHTTP/RedisHTTPHTTP/DNSHTTP/DNSHTTP
K8S IntegrationYesNoYesYesNo
PersistenceRedis--MySQLMySQL
Cross Registry SyncYesNoYesYesNo

References

Released under the Apache License 2.0.