Current status: WIP draft. Please contribute. Not complete at all.
A vendor neutral format for Linux container images and runtime. This document specifies services the runtime needs to expose to the container, as well as the format the runtime expects to be able run the specified container image.
Please fork, then issue a pull request. We will discuss in the PRs.
- Portability, Given a standard container, many runtimes can run it
- Simple, should be already implemented or trivial to support in existing runtimes
The basic format is a root filesystem containing all the dependencies needed to run an application. A basic chroot should be a sufficient test to see if your filesystem is setup correctly.
For the purposes of this document, we are ignoring transport or packaging. The runtime simply needs a root filesystem to start from.
These files do not need to have any contents, but should be provided either by the runtime or the contents of the file.
Operating system identification. Can be a blank file, but the runtime can inspect it before starting. Here are a few comments on why it is important.
If provided by the container, the runtime must respect it. If not provided, the runtime can inject or add it to the container.
What is the smallest container we can make to test this?
The runtime should provide a mechanism to enter the container through an arbitrary executable. If not specified, runtime should default to /sbin/init. Otherwise fail.
Runtime should support configuring environment variables via a file.
The runtime should support three types of networking.
The hosts network adapter is attached directly to the container. No networking namespace.
A network namespace just for the container, no external networking.
Optionally, the runtime can provide its own networking virtualization layer. This should be exposed to the host as a nic.
Runtime should support full process, filesystem, user, network namespaces.
Runtime should support memory limiting, memory with swap limiting, disk IO limits, and CPU thresholds.
Once running, the runtime should provide a globally unique ID for the running container.
- Where does socket activation come in? does it?
- Runtime able to specify receiving port, and map to internal port or over a file descriptor
Runtime Support | Docker | systemd+nspawn | native LXC | libvirt-lxc | lmctfy | OpenVZ |
---|---|---|---|---|---|---|
/etc/resolv.conf | yes | yes | - | - | no | - |
/etc/os-release | no | yes | - | - | no | - |
/usr/sbin/init | no | yes | - | yes | no | - |
EnvironmentFile | no | yes | - | - | no | - |
NAT networking | yes | no | - | yes | yes | - |
Private networking | yes | yes | - | yes | yes | - |
Host networking | no | yes | - | yes | yes | - |
Socket activation | no | yes | no | yes | no | no |
Unique container id | yes | yes | - | yes | yes | - |
Network namespaces | yes | yes | - | yes | yes | - |
Filesystem namespaces | yes | yes | - | yes | yes | - |
Process namespaces | yes | yes | - | yes | yes | - |
User namespaces | no | no | - | yes | yes | - |
Cgroups | yes | yes | - | yes | yes | - |
MAC-based security | yes | yes | - | yes | no | - |
Some places of inspiration for this.
-
docker inspect
[{
"ID": "3c85249977e132676c68f2dd03c5e7ad556755cdfc9188ce8dd15a17b5f66e44",
"Created": "2013-11-09T05:13:10.109281735Z",
"Path": "/bin/sh",
"Args": [
"-c",
"/usr/sbin/nginx"
],
"Config": {
"Hostname": "3c85249977e1",
"Domainname": "",
"User": "",
"Memory": 0,
"MemorySwap": 0,
"CpuShares": 0,
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"PortSpecs": null,
"ExposedPorts": {
"9001/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"HOME=/",
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [],
"Dns": null,
"Image": "162.209.1.102:49193/pages",
"Volumes": {},
"VolumesFrom": "",
"WorkingDir": "",
"Entrypoint": [
"/bin/sh",
"-c",
"/usr/sbin/nginx"
],
"NetworkDisabled": false,
"Privileged": false
},
"State": {
"Running": true,
"Pid": 9363,
"ExitCode": 0,
"StartedAt": "2013-11-09T05:13:10.329784251Z",
"FinishedAt": "0001-01-01T00:00:00Z",
"Ghost": false
},
"Image": "b10492dd794a83c3be908bce78c17783b667130aa529ed9346db82b8fc637671",
"NetworkSettings": {
"IPAddress": "172.17.0.200",
"IPPrefixLen": 16,
"Gateway": "172.17.42.1",
"Bridge": "docker0",
"PortMapping": null,
"Ports": {
"9001/tcp": [
{
"HostIp": "0.0.0.0",
"HostPort": "49195"
}
]
}
},
"SysInitPath": "/usr/libexec/docker/dockerinit",
"ResolvConfPath": "/etc/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/3c85249977e132676c68f2dd03c5e7ad556755cdfc9188ce8dd15a17b5f66e44/hostname",
"HostsPath": "/var/lib/docker/containers/3c85249977e132676c68f2dd03c5e7ad556755cdfc9188ce8dd15a17b5f66e44/hosts",
"Name": "/blue_lion6",
"Volumes": {},
"VolumesRW": {}
}]