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 imagedocker_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:
- Image Resolution: Calls
stacks.getResolvedDockerRuntimeImage(defined inpackages/core/src/stacks.tsat line 1091) to determine the correct container image - Artifact Handling: Pulls or pushes images to the configured registry
- Container Execution: Issues
docker runcommands 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:
- Command Resolution: Parses the entry point from project scripts or configuration
- Process Spawning: Uses the Openship runtime manager to spawn the process directly on the host OS
- 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
runtimecolumn in the database schema or implicit detection of Docker descriptors in the project root. - Image resolution for Docker uses
getResolvedDockerRuntimeImageinpackages/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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →