Openship DockerRuntime vs BareRuntime: A Complete Technical Comparison

Openship executes services using either DockerRuntime for containerized isolation or BareRuntime for native host execution, with the mode determined by the runtime field in packages/db/src/schema/project.ts or inferred from project files.

Openship is an open-source deployment platform that abstracts service execution through dual runtime strategies. Understanding the difference between DockerRuntime and BareRuntime is essential for optimizing resource utilization and deployment flexibility in production environments. This guide examines the implementation details, configuration schema, and operational characteristics of both runtimes as defined in the oblien/openship repository.

Core Runtime Concepts

Openship defines two distinct execution environments in its type system and database layer. Each runtime offers different trade-offs between isolation, performance, and operational complexity.

DockerRuntime Definition

The DockerRuntime executes services via the Docker daemon, providing full containerization with isolated filesystems, network stacks, and resource constraints. In packages/core/src/types.ts, the runtime is represented by the enum value "docker" at line 73. This mode handles image resolution, health checks, and container lifecycle management through Docker's API.

BareRuntime Definition

The BareRuntime executes services as native operating system processes directly on the host. Represented by the enum value "bare" (or "none" in legacy code) in packages/core/src/types.ts, this mode bypasses containerization entirely. The platform spawns the process using the resolved command line—often derived from scripts.start—without Docker daemon involvement.

Runtime Selection Logic

Openship determines which runtime to use through a hierarchical decision process defined in the project configuration and database schema.

Explicit Configuration

The primary selection mechanism is the runtime column in packages/db/src/schema/project.ts at line 183. Valid values are explicitly stored as "docker" or "bare". When set to "docker", the platform activates Docker-specific validation and image resolution workflows. When set to "bare", Openship skips container-related checks and prepares for direct process execution.

Implicit Detection

If the configuration omits the runtime field, Openship infers the runtime from project artifacts. Presence of a Dockerfile or Docker Compose definition triggers DockerRuntime selection, while projects lacking these descriptors default to BareRuntime.

Database Schema and Type System

The distinction between runtimes permeates Openship's data layer and core type definitions.

Project Schema Storage

In packages/db/src/schema/project.ts, the runtime column stores the execution mode as a string literal. Docker-specific fields include:

  • build_image: The image used for compilation (line 183-191)
  • runtime_image: The execution environment image
  • docker_healthcheck: Container health check configuration (line 117)

These columns are only relevant when runtime equals "docker".

Type Safety

The packages/core/src/types.ts file enumerates allowed runtime strings at line 73, providing compile-time validation that prevents invalid runtime specifications from entering the database.

Deployment Flow Comparison

The execution path diverges significantly based on the selected runtime, with distinct resolution and spawning mechanisms.

DockerRuntime Deployment

When runtime is "docker", Openship follows this sequence:

  1. Image Resolution: Calls stacks.getResolvedDockerRuntimeImage (defined in packages/core/src/stacks.ts at line 1091) to determine the correct container image
  2. Artifact Handling: Pulls or pushes images to the configured registry
  3. Container Execution: Issues docker run commands with configured options, ports, and resource limits

The project.build_image and project.runtime_image fields drive the build and execution phases respectively.

BareRuntime Deployment

For BareRuntime, the workflow eliminates containerization:

  1. Command Resolution: Parses the entry point from project scripts or configuration
  2. Process Spawning: Uses the Openship runtime manager to spawn the process directly on the host OS
  3. Execution Monitoring: Attaches to stdout/stderr streams without Docker abstraction

Operational Characteristics

Each runtime manages service health, resources, and failures through different mechanisms.

Health Checking

DockerRuntime utilizes Docker-specific health checks stored in the docker_healthcheck column (packages/db/src/schema/project.ts line 117). The Docker daemon enforces these checks automatically.

BareRuntime relies on platform-level monitoring through systemd integration or custom status scripts. No Docker health-check abstraction is applied; the platform monitors process existence and exit codes directly.

Resource Limits

DockerRuntime enforces constraints through Docker Compose definitions (mem_limit, cpu_quota) translated into Docker daemon parameters.

BareRuntime applies limits declared in the project's resources section using host-level mechanisms such as cgroups or ulimit configurations managed by the Openship orchestrator.

Failure Handling

In packages/core/src/service-status.ts at line 48, DockerRuntime maps container-specific statuses (restarting, paused, exited) to Openship's generic service status model.

BareRuntime surfaces process exit codes and terminal output directly to the Openship monitor without translation through Docker state abstractions.

Configuration Examples

Selecting Runtime in Configuration


# openship-config.yaml - Explicit Docker selection

runtime: docker
build_image: node:22
runtime_image: node:22-alpine
docker_healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
  interval: 30s

# openship-config.yaml - Bare runtime explicit

runtime: bare
resources:
  memory_limit: "512m"
  cpu_limit: "1.0"

Runtime-Aware Service Launch

// packages/core/src/launch.ts
import { startDockerService } from "./docker";
import { startBareService } from "./bare";

async function launchService(project) {
  if (project.runtime === "docker") {
    // Uses packages/core/src/stacks.ts resolution logic
    await startDockerService(project);
  } else {
    // Direct process spawn without Docker daemon
    await startBareService(project);
  }
}

Reading Runtime from Database

// Querying the runtime schema
import { db } from "@openship/db";
import { Project } from "@openship/db/schema";
import { eq } from "drizzle-orm";

async function getRuntime(projectId: string) {
  const proj = await db
    .select()
    .from(Project)
    .where(eq(Project.id, projectId))
    .then(rows => rows[0]);

  // Returns "docker" or "bare" per packages/core/src/types.ts
  return proj.runtime;
}

Summary

  • DockerRuntime provides containerized isolation using Docker daemon management, image-based deployments, and Docker-specific health checks defined in packages/db/src/schema/project.ts.
  • BareRuntime executes native processes directly on the host OS, bypassing containerization for improved performance and reduced overhead.
  • Runtime selection occurs via the runtime column in the database schema or implicit detection of Docker descriptors in the project root.
  • Image resolution for Docker uses getResolvedDockerRuntimeImage in packages/core/src/stacks.ts, while Bare runtimes resolve entry point commands from project scripts.
  • Status mapping differs by runtime: Docker states translate through packages/core/src/service-status.ts, while Bare processes report exit codes directly.

Frequently Asked Questions

How does Openship decide between DockerRuntime and BareRuntime?

Openship checks the runtime field in the project configuration stored in packages/db/src/schema/project.ts. If the field is "docker", it uses containerization; if "bare", it runs native processes. When unspecified, Openship infers the runtime from the presence of a Dockerfile or Docker Compose files in the project repository.

Can I use Docker for builds but BareRuntime for execution?

Yes. The schema in packages/db/src/schema/project.ts separates build_image from runtime configuration. You can specify a Docker image for building artifacts while setting runtime: "bare" to execute the compiled binary directly on the host, bypassing container runtime overhead.

What happens to health checks when using BareRuntime?

BareRuntime ignores Docker-specific health check configurations stored in the docker_healthcheck column. Instead, Openship relies on external process monitoring, systemd integration, or custom status scripts to detect service availability and restart failed processes.

Where are the runtime type definitions located in the source code?

The core type definitions reside in packages/core/src/types.ts at line 73, which exports the runtime enum containing "docker" and "bare" values. The database schema enforcing these types is located in packages/db/src/schema/project.ts, specifically around line 183 where the runtime column is defined with validation constraints.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →