I am trying to understand the OCI container runtime: in particular, where pid 1 comes from.
If I launch the “ubuntu” image, it keeps running:
nsrc@brian-kit:~$ incus launch oci-docker:ubuntu foo2
nsrc@brian-kit:~$ incus list | grep foo2
| foo2 | RUNNING | 10.11.12.72 (eth0) | | CONTAINER (APP) | 0 |
Docker has Entrypoint and/or Cmd: I can see only Entrypoint here though.
nsrc@brian-kit:~$ incus config show foo2 | grep oci
image.type: oci
oci.cwd: /
oci.entrypoint: /bin/bash
oci.gid: "0"
oci.uid: "0"
volatile.container.oci: "true"
Does that imply there is a long-running “bash” process in this container?
nsrc@brian-kit:~$ incus shell foo2
root@foo2:~# ps auxwww
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 6346000 19100 ? Ss 16:43 0:00 init
root 21 0.0 0.0 4588 3984 pts/0 Ss+ 16:43 0:00 /bin/bash
root 25 0.0 0.0 4780 2992 pts/1 Ss 16:45 0:00 su -l
root 26 0.0 0.0 5016 4124 pts/1 S 16:45 0:00 -bash
root 31 0.0 0.0 8272 3896 pts/1 R+ 16:45 0:00 ps auxwww
Looks like pid 21 is that process: if I exit and re-run incus shell, it’s still there. What is its stdin connected to? Then I remembered “incus console”:
nsrc@brian-kit:~$ incus console foo2
To detach from the console, press: <ctrl>+a q
root@foo2:/# echo $$
21
root@foo2:/#
OK, then this Entrypoint shell is what incus console connects to. And indeed, if I hit ctrl-D to exit this shell, the whole container exits. That’s good: I understand the persistence part now.
But the ps listing also begs the question, what is the init process in pid 1?
In a regular incus container, pid 1 is what you expect:
root@unifi:~# ps auxwww
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 21228 9060 ? Ss 17:10 0:00 /sbin/init
...
root@unifi:~# ls -l /sbin/init
lrwxrwxrwx 1 root root 22 Jul 11 2025 /sbin/init -> ../lib/systemd/systemd
The incus documentation says:
Incus assumes that any image it uses to create a new container comes with at least the following root-level directories:
…
- /sbin/init (executable)
…
Incus spawns whatever is located at/sbin/initas the initial process of the container (PID 1)
However, the Ubuntu docker image is heavily cut down; it has no systemd, and there is no /sbin/init (although sysvinit-utils is installed, providing directory /usr/lib/init/)
root@foo2:~# ls -l /sbin/init
ls: cannot access '/sbin/init': No such file or directory
root@foo2:~# ls -l /proc/1/exe
lrwxrwxrwx 1 root root 0 Feb 23 16:49 /proc/1/exe -> /opt/incus/bin/incusd
root@foo2:~# cat /proc/1/cmdline; echo
init
root@foo2:~# ls /opt/incus/bin/incusd
ls: cannot access '/opt/incus/bin/incusd': No such file or directory
So it looks like incusd (or its child) on the host is acting as the init inside the container. Possibly this one:
1000000 563731 0.0 0.0 6272004 19204 ? Ss 16:49 0:00 init
root@brian-kit:/home/nsrc# ls -l /proc/563731/exe
lrwxrwxrwx 1 1000000 1000000 0 Feb 23 17:00 /proc/563731/exe -> /opt/incus/bin/incusd
root@brian-kit:/home/nsrc# ls -l /proc/563731/cmdline
-r--r--r-- 1 1000000 1000000 0 Feb 23 16:50 /proc/563731/cmdline
root@brian-kit:/home/nsrc# cat /proc/563731/cmdline; echo
init
However, I’m having difficulty locating the init process in the incus source. Is it in a separate library, like lxc perhaps?
If the OCI image did contain /sbin/init, would incus run that instead? I think that’s worth documenting.
(Aside: with docker engine, whatever you give as your entrypoint is pid 1, unless you do docker run --init in which case you get tini as your pid 1. I’m just trying to understand what the key differences are between running a container in incus versus docker engine)