Running Docker containers on OmniOS
Why?
I’ve used Docker for years. I actually kind of love it, but I have to admit that I’ve mostly used it in “isolated” configurations: meaning “Docker for Mac”, podman machine, ECS/k8s nodes, etc. So, I’ve been removed from running it on a host used for other things.
I had occasion to think to myself, “What is Docker actually doing?”
What is Docker doing?
If we break down what your typical docker run command does, it goes
something like this:
- create a writeable root filesystem from the specified image’s layers
- create a container with that filesystem as the root
- configure the container with limits, environment, networking, mounts, etc.
- run a process in the container
Ok, but why?
So now I think, “does this require Linux?” Sure enough, recent efforts have proven that FreeBSD Jails are not only viable, but an officially supported container platform.
Long time ago, I helped Tripwire add FreeBSD as a supported platform. So, this news is exciting to me. But, I was looking at this before this news came out and am only now getting around to writing about it. Don’t worry, I’m checking it out!
At the time, I was actually thinking about another OS we supported at Tripwire: Solaris. I got to check out ZFS and Zones in Solaris 10, so somewhere in my brain was some knowledge about these. A modern descendant of OpenSolaris is OmniOS, and it includes LX branded zones ported from Joyent’s SmartOS (another cousin). At the end of that page it says:
To use a tarball (like a docker one):
Clearly, I had to try this.
tarball? like a docker one?
It turns out you can export a tarball from a running docker container. This was interesting, but what if I don’t have a place to run a docker container? I actually do though, so more on that later.
What image to use? Let’s go with the SigNoz otel-collector image. SigNoz is a great observability tool, and the OpenTelemery Collector is amazing for piping traces, metrics, logs, and more around.
linux $ docker history signoz/signoz-otel-collector:v0.129.8 | rg '(CMD|ENTRY|ENV)'
8e072cdb38db 2 weeks ago CMD ["--config" "/etc/otel/config.yaml"] 0B buildkit.dockerfile.v0
<missing> 2 weeks ago ENTRYPOINT ["/signoz-otel-collector"] 0B buildkit.dockerfile.v0
linux $ docker run --rm --entrypoint /bin/sleep signoz/signoz-otel-collector:v0.129.8 infinity
<in another shell>
linux $ docker export -o signoz-otel-collector.tar container_name
linux $ docker stop container_name
linux $ gzip signoz-otel-collector.tar
linux $ du -h signoz-otel-collector.tar.gz
175M signoz-otel-collector.tar.gz
Configure and install the LX zone
Now, we’ve got a “docker one”. We scp that to our OmniOS host and switch over there. First, we install the LX brand, set up our ZFS for zones, and add an etherstub (if needed) and VNIC.
% pfexec pkg install brand/lx
...
% pfexec zfs create /rpool/zones
% pfexec dladm create-etherstub stub0
% pfexec dladm create-vnic -l stub0 stub0collector0
Then, we configure the zone.
% pfexec zonecfg -z signoz-collector
signoz-collector: No such zone configured
Use 'create' to begin configuring a new zone.
zonecfg:signoz-collector> create
zonecfg:signoz-collector> set zonepath=/rpool/zones/signoz-collector
zonecfg:signoz-collector> set autoboot=false
zonecfg:signoz-collector> set ip-type=exclusive
zonecfg:signoz-collector> set brand=lx
zonecfg:signoz-collector> add net
zonecfg:signoz-collector:net> set allowed-address=192.168.42.2/24
zonecfg:signoz-collector:net> set defrouter=192.168.42.1
zonecfg:signoz-collector:net> set physical=stub0collector0
zonecfg:signoz-collector:net> end
zonecfg:signoz-collector> add attr
zonecfg:signoz-collector:attr> set name=kernel-version
zonecfg:signoz-collector:attr> set type=string
zonecfg:signoz-collector:attr> set value=5.10.0
zonecfg:signoz-collector:attr> end
zonecfg:signoz-collector> add attr
zonecfg:signoz-collector:attr> set name=resolvers
zonecfg:signoz-collector:attr> set type=string
zonecfg:signoz-collector:attr> set value=10.0.0.1
zonecfg:signoz-collector:attr> end
zonecfg:signoz-collector> verify
zonecfg:signoz-collector> commit
zonecfg:signoz-collector> exit
Then we install the zone from the tarball.
% pfexec zoneadm -z signoz-collector install -t /path/to/signoz-otel-collector.tar.gz
A ZFS file system has been created for this zone.
Installing zone from tar file /path/to/signoz-otel-collector.tar.gz
Now, the moment of truth: let’s boot the zone, zlogin, and enter a shell in
file system from the Docker image, running in an LX zone emulating a 5.x kernel.
We’ll see if the otel-colector binary works, using the ENTRYPOINT and CMD from
the history command above.
% pfexec zoneadm -z signoz-collector boot
% pfexec zlogin signoz-collector
[Connected to zone 'signoz-collector' pts/7]
Linux signoz-collector 5.10.0 BrandZ virtual linux x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
root@signoz-collector:~# /signoz-otel-collector --config /etc/otel/config.yaml
{"level":"info","timestamp":"2025-09-10T23:37:39.322Z","caller":"service/service.go:69","msg":"Starting service"}
{"level":"info","timestamp":"2025-09-10T23:37:39.322Z","caller":"opamp/simple_client.go:26","msg":"Starting simple client","component":"simple-client"}
{"level":"info","timestamp":"2025-09-10T23:37:39.323Z","caller":"signozcol/collector.go:102","msg":"Starting collector service"}
...
Look at that! The collector is running in an LX zone, none the wiser 💅🏽.
Cool, (so|now) what?
Sooooo… this clearly doesn’t have the ergonomics that Docker provides. After all, this process required another Linux host running actual Docker. We also haven’t talked about how to Crossbow this container into being usable from the network, but that’s the same with any zone. Also, there is no supervision, orchestration, etc. - all pretty manual. I have some ideas…
At least one thing we can do is take the Linux Docker host out of the equation. We’ll tackle this in the next post!