Synopsis #
Docker images assume an OCI runtime and Linux kernel interfaces. OpenBSD does not provide a native Docker Engine or a base-system OCI container runtime, and a Linux container image cannot run directly as an OpenBSD process. Migration therefore begins with the workload’s actual requirements rather than with a command intended to reproduce Docker syntax.
OpenBSD packages, base-system daemons, pledge(2) , unveil(2) , filesystem chroots, and vmm(4) solve different problems. None is a drop-in Docker replacement. This guide selects the smallest accurate deployment model and identifies when the workload should remain on Linux.
Inventory the Workload Contract #
Record the container definition and its external behavior before selecting a target:
- application source and supported operating systems;
- required Linux kernel APIs, devices, capabilities, and filesystems;
- published ports and network dependencies;
- persistent volumes and ownership expectations;
- environment variables, secrets, and generated configuration;
- health checks, startup order, and restart policy;
- image build steps and native dependencies;
- backup, restore, update, and rollback procedures;
- CPU, memory, storage, and architecture requirements.
A Compose file is an orchestration description, not a portable system specification. Image layers can contain Linux executables and libraries even when the application language itself is portable.
Select the Deployment Model #
| Requirement | Appropriate OpenBSD direction |
|---|---|
| The application has a maintained OpenBSD package | Install the package and use its package README and rc.d service |
| A base-system daemon provides the required protocol | Configure the base daemon and preserve its privilege-separated design |
| The application can be ported and maintained on OpenBSD | Build or update a port, then install the resulting package |
| The application itself supports pledge or unveil | Add restrictions in the application and test every required operation |
| A legacy process needs a restricted filesystem view | Consider a purpose-built chroot with explicit limitations |
| The workload requires Linux or an OCI runtime | Run it on a maintained Linux host or, where suitable, a Linux virtual machine |
| The workload requires unsupported devices, graphics, or virtualization features | Keep it on infrastructure that supports those requirements |
Do not combine several partial mechanisms and label the result a container platform. Each choice has a different isolation, maintenance, and recovery boundary.
Prefer Packages and Service Accounts for Portable Applications #
Search the current package repository before rebuilding an application manually:
$ pkg_info -Q APPLICATION_NAME
When a package exists, install it with pkg_add(1)
, read its file under /usr/local/share/doc/pkg-readmes/, and manage a packaged daemon with rcctl(8)
. Preserve the package’s service account, directories, file ownership, login class, and startup script.
Store mutable data outside program directories, protect secrets with restrictive ownership and modes, and expose only required network addresses. This reproduces the workload’s operational contract without reproducing a container image’s internal filesystem.
Managing Software: Packages and Ports and Build Third-Party Software from Ports describe the supported package and ports boundaries.
Understand Application Restrictions #
pledge(2) limits the system-call capabilities retained by a process. unveil(2) limits the filesystem paths visible to a process. Applications normally call these interfaces in their own code, and packaged software can carry maintained policy.
They do not create an OCI image, virtual network, resource namespace, writable layer, or orchestration API. An administrator cannot safely infer the correct promises or paths for arbitrary software. When porting an application, add restrictions incrementally, test all lifecycle operations, and preserve diagnostics for denied operations.
Treat chroot as a Filesystem Tool #
chroot(2) changes a process’s apparent root directory. Several OpenBSD daemons use a chroot as one layer within a broader privilege-separated design.
A manually constructed chroot is not a complete container security boundary. It does not by itself provide a separate kernel, virtual network, resource accounting, image lifecycle, or safe orchestration. It can also require copied libraries, devices, users, configuration, and update procedures that become an additional maintenance burden.
Use a chroot only when the application’s documentation and threat model require a restricted filesystem view. Combine it with a dedicated unprivileged account, minimal files, explicit device policy, network controls, and a complete update procedure. Do not copy a Linux root filesystem into a chroot and expect its binaries to run.
Use a Linux Virtual Machine When Linux Is Required #
OpenBSD’s vmd(8)
manages virtual machines on supported amd64 hardware. The official virtualization FAQ currently limits supported guests to OpenBSD and Linux and requires a serial console. It also documents important unavailable features, including graphics, snapshots, guest SMP, hardware passthrough, and live migration.
A Linux guest can run its own supported Docker or OCI stack because it supplies the required Linux kernel. This creates a full guest-operating-system maintenance boundary:
- patch and monitor both host and guest;
- restrict the guest network with PF and guest policy;
- protect virtual disk images and configuration;
- use application-consistent backups rather than assuming disk-image copying is safe;
- plan console recovery and clean shutdown;
- confirm capacity and unsupported vmm features before migration.
Create and Network Virtual Machines with vmm provides the host procedure. A separate Linux host or another hypervisor is the correct choice when the workload needs features outside the documented vmm contract.
Translate Common Container Features #
| Container concept | Migration question |
|---|---|
| Image | Which package, source revision, configuration, and data schema must be reproduced? |
| Volume | Which OpenBSD filesystem path owns persistent data, with which user and backup policy? |
| Published port | Which daemon address and PF rule expose the service, and to whom? |
| Environment secret | Which protected configuration or credentials mechanism owns the secret? |
| Restart policy | Which rc.d service and failure-monitoring policy manages the process? |
| Health check | Which protocol-level or process-level check proves useful service? |
| Resource limit | Which login-class or VM resource boundary is documented and testable? |
| Compose dependency | Which explicit service dependency and recovery order must be documented? |
This translation makes hidden runtime assumptions visible. It also shows when a Linux container platform remains the simpler and safer operational choice.
Validate the Migration #
Build the target in a non-production environment and test:
- clean installation from documented inputs;
- startup after reboot without an interactive shell;
- network access from permitted and denied sources;
- secret and file permissions;
- application data backup and full restore;
- package or guest update and rollback;
- failure of each external dependency;
- log delivery, health checks, and capacity alerts;
- complete removal without deleting unrelated data.
Retain the original workload until the restored target passes functional and recovery tests. If the application depends on undocumented Linux behavior or cannot be maintained through OpenBSD packages, ports, or a supported guest, record that constraint and keep it on Linux rather than weakening the OpenBSD host.