Tell what a container inherits from what it overrides
Checked against a real stalwartlabs/stalwart image, `docker inspect` on an ordinary container reports User "stalwart", Entrypoint ["/usr/local/bin/stalwart"] and Cmd ["--config", "/etc/stalwart/config.json"] — all three inherited, none of them given. Two things followed from reading those as the operator's. A container user was listed as configuration a recreate would drop, so every container off the official image was refused as unrecreatable. That refusal lived in cutover, downstream of the stop, the settings conversion and the store migration: it arrived with mail down and data already moved, which is the failure issue #1 was filed for. Each of the three is now compared against `docker image inspect` of the image the container is on. Inherited values are left to the new image, whose own defaults are the ones that go with it. Overrides are carried: --user, --entrypoint, and the rest of an entrypoint as leading argv. Cmd and Entrypoint were not being read at all, so an overridden one was silently dropped — the exact loss the unsupported list exists to prevent. The recreatability question also moved into preflight, while the server is still running. Cutover asks it again, since the two are separated by the whole migration, but only one of them can refuse without cost. The other half: the recreated container is now started with `--config` pointing at the migrated config in the data volume. Left to the image's default command it came up on /etc/stalwart/config.json — a different volume, holding whatever the old version left there — so cutover would have produced a running server with nothing to do with the migration that preceded it. An overridden command and that --config are the same argv and cannot be merged honestly, so a container with one is refused and told why. The config is also chowned to whatever owns the data directory, before the recovery cycle opens it. The image runs as uid 2000 and this tool writes as root; §4.8 is the standing reminder that byte-perfect and unreadable is a way to report success. Found while checking @kaya-eu's field report in #1 against a real image. Their three manual migrations are where the config step comes from.
This commit is contained in:
+29
-3
@@ -300,7 +300,21 @@ against an already-migrated store.
|
||||
it carries across, naming what it found. The list is conservative and
|
||||
deliberately not exhaustive; docker's HostConfig has far more fields than
|
||||
it checks, and one it does not know about is a reason not to be
|
||||
recreating that container at all.
|
||||
recreating that container at all. That question is asked in preflight,
|
||||
while the server is still running, and again at cutover: the answer does
|
||||
not change between them, and only one of the two points can refuse
|
||||
without having already cost an outage.
|
||||
- What a container *inherits* from its image is not what it *overrides*,
|
||||
and only the override is the operator's. `docker inspect` reports
|
||||
`User`, `Cmd` and `Entrypoint` either way - a container off the official
|
||||
image reports user `stalwart` and command
|
||||
`--config /etc/stalwart/config.json` having been given neither - so each
|
||||
is compared against `docker image inspect` of the image the container is
|
||||
actually on. An inherited value is left to the new image, whose own
|
||||
defaults are the ones that go with it; an override is carried onto the
|
||||
recreate. Reading an inherited value as an override is not a harmless
|
||||
over-refusal: before this distinction existed, every ordinary container
|
||||
off the official image was refused at cutover, after the stop.
|
||||
- The old container is renamed rather than removed, and the old image is
|
||||
never pruned. Together they are the container's manual restore path, the
|
||||
nearest equivalent to the preserved binary of §4.2: one command starts
|
||||
@@ -852,8 +866,20 @@ happens to need them. `preflight.DeploymentKind` is a type alias for
|
||||
`run` writes it under the host side of whichever mount covers
|
||||
`--data-dir` and names it on the container side, because cutover recreates
|
||||
a container with the mounts it had and cannot invent a new one for a
|
||||
config file. That is an inference from how the mounts must line up rather
|
||||
than something a real deployment has confirmed.
|
||||
config file. Cutover then starts the new container with `--config` at
|
||||
that path, because the image's own default command points at
|
||||
`/etc/stalwart/config.json` - a different volume, holding whatever the
|
||||
old version left there. An overridden command and that `--config` are
|
||||
the same argv and cannot be merged honestly, so a container with one is
|
||||
refused rather than guessed at.
|
||||
The config is also chowned to whatever owns the data directory before
|
||||
anything reads it: the official image runs as uid 2000, and a
|
||||
root-owned 0640 config is one the server cannot open - a failure that
|
||||
arrives as a recovery boot that never comes up rather than as a
|
||||
permission error anyone would recognise. §4.8 is why that is not left to
|
||||
chance.
|
||||
The path itself remains an inference from how the mounts must line up
|
||||
rather than something a real deployment has confirmed.
|
||||
- **Cutover ignores systemd drop-ins.** It rewrites only the main unit
|
||||
file, so an `ExecStart` or `Environment` override in
|
||||
`/etc/systemd/system/stalwart.service.d/*.conf` is invisible to it -
|
||||
|
||||
Reference in New Issue
Block a user