Skip to content

SpaceOS for Docker users

If you know Docker, you already know most of the SpaceOS workflow. An image is an OCI image, a service builds from a Dockerfile, and the CLI follows the grammar docker and kubectl established. What changes comes from where the image runs. A payload computer is the computer on a satellite that runs the mission's applications, beside the platform that keeps the satellite alive. It has no network for most of its orbit and no operator at the console when an update arrives. Some payload computers arrive empty, and SpaceOS is their whole operating system. Others keep the vendor's Linux, and SpaceOS runs on it as a set of daemons; Integration models describes both.

What carries over

A Dockerfile is the build recipe. space build -f Dockerfile -t NAME builds it the way docker build -f Dockerfile -t NAME does, and space run NAME runs the result on your computer:

Terminal window
space build -f Dockerfile -t my-app
space run my-app

An existing image works too. A service in space.yaml names any OCI image by reference, whoever built it, and space image push publishes a built image to any OCI registry. The Port a Linux app guide takes an image from docker push to a SpaceOS service.

DockerSpace CLI
docker buildspace build
docker runspace run
docker psspace status
docker logsspace logs
docker pushspace image push
docker imagesspace image ls
docker contextspace target

The image carries its own kernel

A Docker image runs on a kernel somebody else booted, so its trust starts at the container's first process. A SpaceOS image carries the kernel, the initramfs and the root filesystem beside your services, and the signature covers all of them. The chain of checks therefore starts at the board's secure-boot key and ends at the bytes your service runs.

The kernel belongs to the target, so space.yaml refuses a kernel: field. The SpaceOS runtime image supplies a kernel pinned by digest, and space show --sbom prints that digest before you build.

space build produces one image that does not depend on the target. space deploy then assembles the release for one board: its kernel, its device tree, its firmware, and its secure-boot signature. Docker has no such step, because one datacenter machine is interchangeable with the next.

Trust comes from a key on the satellite

A Docker tag can move, and the trust behind a pull comes from the registry you reach over TLS. A satellite cannot reach a registry when it launches a service. SpaceOS pins a trust root in the image: the system image assembled for the node carries the public keys of your signing identity (an Ed25519 key and an ML-DSA-65 key) in the signed initramfs it boots. The node checks the signed metadata of every launch against those keys, and the digest of the bytes against that metadata, with no network access. A registry that serves different bytes fails that check. The registry still carries bytes. It no longer decides which bytes may run.

Every build is signed with both keys. ML-DSA-65 is the lattice-based signature of NIST FIPS 204, designed to resist a quantum computer that would break Ed25519, and the node requires both signatures. space keys manages both halves, and Signing and verification follows the chain from the key to the running service.

Deploy sends a signed release

docker run and kubectl apply are commands sent over a live connection. A satellite link opens for a few minutes per pass, and some passes carry nothing. space deploy therefore sends a signed release: the whole set of images the node should run. The node makes one decision, which is whether to move to it.

The same release delivered twice changes nothing the second time. An older release that arrives late is refused, because the node keeps a version floor that only rises. A node that was out of contact for a month moves to the newest release in one step. Boot, updates, and rollback describes the trial boot and the automatic fallback.

Terminal window
space deploy my-app:release --target sat-42 --plan
space deploy my-app:release --target sat-42

You choose the isolation boundary per service

Docker isolates every container with Linux namespaces over one shared kernel. SpaceOS lets each service choose its boundary with the isolation field of space.yaml. runc runs the service as a Linux container. hvt runs a unikernel in its own hardware virtual machine through a Solo5 tender, on a target whose profile declares it. The partition model compares the boundaries.

The build is a graph of content-addressed steps

The Docker build cache checks each instruction's text and its parent layer. SpaceOS signs its build output, so the build names every step by the digests of its inputs. space build --plan prints that graph, with each step marked as cached or to be built:

Terminal window
space build --plan

No Docker daemon runs on your computer. space build runs the Dockerfile inside a disposable builder VM.

docker logs reads from a daemon you can reach. A SpaceOS node keeps each service's logs with a cursor, and a client that reconnects reads from where it stopped. space logs reads them. Playing that backlog back to the ground over CCSDS file delivery during the next contact is [roadmap].