Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions content/en/docs/images.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,11 @@ sudo nspawn pull REFERENCE [--name NAME] [--backend BACKEND] [--mode MODE] [--fo

It resolves the reference to the manifest for the host's
platform (image indexes are followed), downloads every layer and the config
blob that is not already in the store, checking each one against its sha256
digest while it streams (a blob is written next to its final name and renamed
only once verified, so an interrupted download never passes for a complete
one), and then:
blob that is not already in the store, three at a time as docker does, checking
each one against its sha256 digest while it streams (a blob is written next to
its final name and renamed only once verified, so an interrupted download never
passes for a complete one, and a download cut short takes its part file with
it), says of each blob when it is downloaded, and then:

1. assembles the root file system with the chosen [backend](#backends);
2. reads the OCI config and decides whether the image is a
Expand Down
17 changes: 10 additions & 7 deletions content/en/docs/machines.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,9 @@ What an app runs is decided exactly as with docker:
forgets them all, and `exec` sees the same environment as the program. Names
follow the usual rules (letters, digits and `_`, not starting with a digit).
- The working directory, the user and the stop signal come from the image
unless `-w`, `-u` and `--stop-signal` say otherwise. Of docker's `uid:gid`
form of the image's user, the uid part is used; the gid comes from the
image's `passwd`, and `-u uid:gid` is refused. The user is resolved as
unless `-w`, `-u` and `--stop-signal` say otherwise. docker's `USER:GROUP`
form is taken as docker takes it, from the image's config or from `-u`: the
group, a name or a number, is the program's primary and only group. The user is resolved as
docker resolves it, from the image's `passwd` and `group` files: systemd-nspawn
asks `getent` inside the machine, which busybox lacks and musl's (alpine)
cannot answer, so nspawn binds a stand-in that answers those lookups and
Expand Down Expand Up @@ -353,9 +353,11 @@ its unit:
- `--hostname NAME`: the hostname inside, the machine's name by default. A
booted machine gets it as its `/etc/hostname`, over the image's, since its
systemd sets the hostname from that file.
- `-u USER` and `-w DIR`: the user (a name or a uid, listed in the image's
`passwd` or not; `uid:gid` is refused) and the working directory the
program runs with, instead of the image's. App images only.
- `-u USER[:GROUP]` and `-w DIR`: the user (a name or a uid, listed in the
image's `passwd` or not, with a group of the image's `group` file or a gid
after a colon, as docker's `--user` takes it; a group name the image lacks
is refused) and the working directory the program runs with, instead of the
image's. App images only.
- `--cap-add`, `--cap-drop` and `--privileged`: capabilities on top of, or
out of, systemd-nspawn's default set (`NET_ADMIN` or `CAP_NET_ADMIN`;
`ALL`). `--cap-drop ALL --cap-add NET_BIND_SERVICE` keeps that one, as with
Expand Down Expand Up @@ -438,7 +440,8 @@ registers, libvirt's among them, are left out); machines that nspawn did not
install show `-` in the image columns. `-a` adds the nspawn machines that are
not running. `COMMAND` is the effective entrypoint and arguments of an app,
and `NETWORK` the machine's address on the default network, its other networks
as `NAME:ADDRESS`, and the published ports, or `host`, `veth` or `none`. A
as `NAME:ADDRESS`, and the published ports, or `host`, `veth`, `none` or
`container:NAME`. A
machine between two runs of its restart policy is listed as `restarting` even
without `-a`, a frozen one as `paused`, and a healthcheck follows the state:
`running (healthy)`.
Expand Down
30 changes: 30 additions & 0 deletions content/en/docs/networking.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ and the choice sticks for the next start.
| a network's name | | The same on a bridge of its own, made with `network create`; several at once, with `--network` repeated: see [Networks of your own](#networks-of-your-own). |
| `host` | | The host's network namespace, like `docker run --network host`: the machine sees the host's interfaces and binds to the host's ports. Works for both kinds of image. |
| `none` | | No network at all, like `docker run --network none`: `lo` and nothing else. Works for both kinds of image. |
| `container:NAME` | | The network namespace of the running machine `NAME`, like `docker run --network container:NAME`: its interfaces, address, hosts file and resolv.conf, nothing of the machine's own. App images only; see [container:NAME](#containername). |
| `veth` | Images not installed by nspawn | The classic systemd-nspawn setup: a virtual ethernet pair whose host end is configured by systemd-networkd through the stock `80-container-ve.network`. Booted images only. |

## The bridge
Expand Down Expand Up @@ -239,3 +240,32 @@ namespace.
`--network none` sets `Private=yes`: the machine has `lo` and nothing else,
like `docker run --network none`. Published ports do not apply, and an app that
runs this way keeps its user namespace too.

## container:NAME

`--network container:NAME` puts an app machine in the network namespace of the
machine `NAME`, docker's sidecar pattern (a VPN client with the programs that
must go through it, for one): the same interfaces and address, `NAME`'s hosts
and resolv.conf files, and nothing of the machine's own. A port the program
serves is published with `-p` on `NAME`, since that is where the address is.
`NAME` can be an app or a booted machine on any bridge network, has to be
running when the machine starts, and cannot be removed while a machine names
it. When `NAME` stops or restarts, the machine keeps the namespace it joined,
which then leads nowhere, and has to be restarted to join the new one, as with
docker.

```shell
sudo nspawn run -d docker.io/qmcgaw/gluetun --name vpn --cap-add NET_ADMIN --device /dev/net/tun -p 8080:8080
sudo nspawn run -d docker.io/library/nginx:1.27 --name web --network container:vpn
```

Behind the scenes the service binds the name systemd-nspawn looks for
(`/run/netns/nspawn-web`) to the network namespace of `vpn`'s leader process,
the mount `ip netns attach` would make, so the settings are the ones of any
app on a bridge, and drops the name when `web` stops while the namespace
stays `vpn`'s. `-p`,
`--network-alias`, `--dns`, `--dns-search`, `--add-host` and `--sysctl` are
refused on such a machine, since they shape a network of its own, and so is a
booted image, whose systemd would configure the shared interfaces again. `ps`
and `inspect` show the network as `container:NAME`; `network inspect` does not
list the machine among the network's members, as it has no address there.
6 changes: 3 additions & 3 deletions content/en/docs/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ nspawn start NAME [--network NETWORK]... [--network-alias [NETWORK=]NAME]... [-p
[--restart POLICY] [-m SIZE] [--cpus N] [--pids-limit N]
[--health-cmd COMMAND] [--health-interval D] [--health-timeout D] [--health-retries N]
[--health-start-period D] [--health-start-interval D] [--no-healthcheck]
[--hostname NAME] [-u USER] [-w DIR] [--cap-add CAP]... [--cap-drop CAP]... [--privileged]
[--hostname NAME] [-u USER[:GROUP]] [-w DIR] [--cap-add CAP]... [--cap-drop CAP]... [--privileged]
[--read-only] [--tmpfs PATH[:OPTIONS]]... [--shm-size SIZE]
[--device HOST[:CONTAINER[:PERMISSIONS]]]... [--dns ADDRESS]... [--dns-search DOMAIN]...
[--add-host HOST:IP]... [--ulimit NAME=SOFT[:HARD]]... [--oom-score-adj N]
Expand All @@ -269,7 +269,7 @@ Boots an image as a machine. Every option is remembered for the next start.

| Option | Meaning |
| --- | --- |
| `--network NETWORK` | Network of the machine: `bridge`, the default network (the default); the name of a network made with [network create](#network-create); `veth`, a veth pair configured by systemd-networkd on the host (booted images only); `host`, the host's own network; or `none`, no interface but `lo`. Repeatable for several bridge networks, the first one primary: its address is where published ports lead and its gateway the default route, unless it is internal, in which case the first network that is not has the route. `veth` and `host` go alone. |
| `--network NETWORK` | Network of the machine: `bridge`, the default network (the default); the name of a network made with [network create](#network-create); `veth`, a veth pair configured by systemd-networkd on the host (booted images only); `host`, the host's own network; `none`, no interface but `lo`; or `container:NAME`, the network namespace of that running machine, like `docker run --network container:NAME` (app images only; see [container:NAME](/docs/networking/#containername)). Repeatable for several bridge networks, the first one primary: its address is where published ports lead and its gateway the default route, unless it is internal, in which case the first network that is not has the route. `veth`, `host`, `none` and `container:NAME` go alone. |
| `--network-alias [NETWORK=]NAME` | Another name for the machine on its primary network, or on `NETWORK`, like `docker --network-alias`: every member of that network resolves it. Repeatable; `none` forgets them. |
| `-p`, `--publish [IP:]HOST:CONTAINER[/udp]` | Publish a port on the host, like `docker -p`: on every address of the host, or on `IP` alone (`127.0.0.1:8080:80`). `8000-8010:8000-8010` publishes a range, one mapping per port. Repeatable; `none` forgets them all. |
| `--entrypoint PROGRAM` | Replace the image's entrypoint; an empty string runs the arguments alone. App images only. |
Expand All @@ -288,7 +288,7 @@ Boots an image as a machine. Every option is remembered for the next start.
| `--health-start-interval D` | Time between probes during the start period. Default: `5s`. |
| `--no-healthcheck` | No probes, whatever the image says. |
| `--hostname NAME` | Hostname inside the machine. Default: its name. A booted machine gets it as its `/etc/hostname`. |
| `-u`, `--user USER` | User the program runs as, a name or a uid (listed in the image's `passwd` or not), instead of the image's; `uid:gid` is refused. nspawn resolves it from the image's `passwd` and `group` files through a stand-in for getent, as docker does. App images only. |
| `-u`, `--user USER[:GROUP]` | User the program runs as, a name or a uid (listed in the image's `passwd` or not), instead of the image's, with a group after a colon as docker takes it: a name of the image's `group` file or a number, which becomes the primary and only group of the program; a name the image lacks is refused. nspawn resolves both from the image's `passwd` and `group` files through a stand-in for getent, as docker does. App images only. |
| `-w`, `--workdir DIR` | Working directory of the program, instead of the image's. App images only. |
| `--cap-add CAP` | Capability to keep on top of systemd-nspawn's default set: `NET_ADMIN`, `CAP_NET_ADMIN`, `ALL`. Repeatable; `none` forgets them. |
| `--cap-drop CAP` | Capability to drop from the default set. `--cap-drop ALL --cap-add X` keeps `X`, as with docker. Repeatable; `none` forgets them. |
Expand Down
2 changes: 1 addition & 1 deletion hugo.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ params:
privacy_policy: /about/#privacy

# Version of nspawn the documentation describes.
version: 1.3.1
version: 1.4.0
archived_version: false

# In-page links to open issues and suggest changes.
Expand Down