<macos/> ·Friday, June 12, 2026· 2 min· 392 words

Running Ubuntu on Apple's Container

After getting Apple’s container running, the thing I actually wanted was a normal Ubuntu box to poke around in. That took one more step than I expected: systemd.

A container runs whatever its CMD is as PID 1. The stock ubuntu:26.04 image doesn’t ship an init, so you boot into a bare shell and not much else. If you want services, units, and a machine that behaves like a real Ubuntu install, systemd has to be the thing running as init. So you build your own image.

Here’s the Dockerfile. Most of it is the well-worn systemd-in-a-container cleanup: install systemd, then delete the units that make no sense inside a container so it doesn’t sit there trying to start hardware that isn’t there.

FROM ubuntu:26.04

ENV container container

RUN apt update -y && apt upgrade -y && apt install -y systemd init
RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == \
systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*;

VOLUME [ "/sys/fs/cgroup" ]
CMD ["/usr/sbin/init"]

Build it, create a machine from it, and run:

 container build -t local/devel -f devel.dockerfile
[+] Building 356.1s (7/7) FINISHED
 => [resolver] fetching image docker.io/library/ubuntu:26.04
 => [internal] load build definition from Dockerfile
 => [linux/arm64 1/3] RUN apt update -y && apt upgrade -y && apt install -y systemd init
 => [linux/arm64 2/3] RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do ... )
 => exporting to oci image format
local/devel:latest

 container machine create --name devel --set-default local/devel
devel

 container machine run
chris.houdeshell@devel:/Users/chris.houdeshell$

That last line is the Ubuntu shell. You’re in.

What the flags are doing, quickly:

  • container build -t local/devel -f devel.dockerfile: -t tags the image as local/devel; -f points at the Dockerfile by name, since I didn’t name it Dockerfile.
  • container machine create --name devel --set-default local/devel: builds a VM named devel from that image. --set-default makes it the machine everything else targets, so I don’t have to spell out the name on every command.
  • container machine run: boots the default machine and drops me into its shell.

One thing worth knowing: that build ran just shy of six minutes. The tool is young and the build path isn’t quick yet, so don’t assume it hung.

macoscontainersubuntusystemddocker