Skip to content

Consolidate Docker Images to GraalVM Only #570

@ujibang

Description

@ujibang

Brief overview
Currently RESTHeart docker image is shipped in three variants:

  • softinstigate/restheart:latest (OpenJDK)
  • softinstigate/restheart:latest-graalvm (GraalVM CE)
  • softinstigate/restheart:latest-native (native binary)

In order to enable all RESTHeart plugins, specifically restheart-polyglot that allows JavaScript plugins, the GraalVM version is required.
The reason why we still have the OpenJDK is that the GraalVM image used to be much bigger.
We want to simplify our packaging by consolidating to GraalVM and native variants only.


Rationale

Objectives:

  • Reduce maintenance overhead from three to two Docker image variants
  • Eliminate user confusion about which image to use
  • Enable full plugin ecosystem (including polyglot plugins) by default in JIT image
  • Leverage GraalVM's improved size parity with OpenJDK distributions
  • Maintain native image for Kubernetes deployments requiring minimal resource footprint

Current Pain Points:

  • Users must choose between OpenJDK and GraalVM without clear guidance
  • OpenJDK image cannot run JavaScript plugins, limiting functionality
  • CI/CD pipeline complexity with three variants
  • Overlapping use cases between OpenJDK and GraalVM variants

Benefits:

  • Two images with clear use cases: dynamic plugin loading (GraalVM) and cloud-native (native)
  • Simplified deployment and upgrade path
  • Reduced Docker registry storage and bandwidth
  • All JIT users get complete feature set by default

Detailed Documentation

Docker Image Consolidation

Starting from version X.X, RESTHeart ships two Docker images:

  • GraalVM variant (default): Full-featured with dynamic JAR and JavaScript plugin loading
  • Native variant: Optimized for Kubernetes with JavaScript plugins support

What Changed

Before:

# Limited functionality
docker pull softinstigate/restheart:latest

# Full functionality, required for polyglot
docker pull softinstigate/restheart:latest-graalvm

# Native binary
docker pull softinstigate/restheart:latest-native

After:

# Full functionality (GraalVM-based)
docker pull softinstigate/restheart:latest

# Native binary for Kubernetes
docker pull softinstigate/restheart:latest-native

Choosing the Right Image

Use softinstigate/restheart:latest when:

  • You need to deploy JAR-packaged plugins dynamically
  • Running in traditional environments (VMs, Docker Compose)
  • Maximum plugin flexibility is required
  • Development and testing with custom Java plugins

Use softinstigate/restheart:latest-native when:

  • Deploying to Kubernetes clusters
  • Minimal memory footprint is critical (<100MB RAM)
  • Instant startup time is required (milliseconds)
  • Using only JavaScript plugins or built-in plugins
  • Running many instances with horizontal scaling

Plugin Support Comparison

Feature GraalVM (latest) Native (latest-native)
JavaScript plugins
Built-in plugins
JAR plugins (dynamic)
Custom Java plugins ✅ Deploy as JAR ⚠️ Must rebuild binary

Important: With the native image, custom Java plugins must be compiled into the binary at build time. You cannot drop JAR files into the plugins directory.

Migration Guide

From OpenJDK variant:

# Old
docker run --rm softinstigate/restheart:7.x.x

# New - same command, now includes polyglot support
docker run --rm softinstigate/restheart:8.x.x

From GraalVM variant:
No changes required. The latest tag now points to the GraalVM image.

Native variant users:
No changes required. Continue using latest-native tag.

Image Specifications

GraalVM Variant (latest)

  • Base: GraalVM CE JDK 21
  • Size: ~XXX MB
  • Startup: ~2-3 seconds
  • Memory: ~256MB minimum
  • Plugin Loading: Dynamic (JAR + JavaScript)

Native Variant (latest-native)

  • Base: Distroless/minimal
  • Size: ~XXX MB
  • Startup: <100ms
  • Memory: ~64MB minimum
  • Plugin Loading: JavaScript only (Java plugins compiled-in)

Kubernetes Deployment Example

apiVersion: apps/v1
kind: Deployment
metadata:
  name: restheart
spec:
  replicas: 3
  template:
    spec:
      containers:
      - name: restheart
        image: softinstigate/restheart:latest-native
        resources:
          requests:
            memory: "64Mi"
            cpu: "100m"
          limits:
            memory: "128Mi"
            cpu: "500m"
        volumeMounts:
        - name: js-plugins
          mountPath: /opt/restheart/plugins/js
      volumes:
      - name: js-plugins
        configMap:
          name: restheart-js-plugins

The native image's instant startup and minimal footprint make it ideal for Kubernetes autoscaling and high-density deployments.

Building Custom Native Images

If you need custom Java plugins with the native image, build your own binary:

# Clone your plugin alongside RESTHeart
git clone https://github.com/your-org/your-plugin.git

# Build native image with custom plugins
cd restheart
./mvnw -Pnative package -DskipTests \
  -Dplugins=/path/to/your-plugin/target/your-plugin.jar

This produces a native binary with your Java plugins compiled-in.

Metadata

Metadata

Assignees

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions