Skip to content

Commit ef73ec6

Browse files
committed
doc: explain docker image tags and rewrite upgrade section
Much of the content was made obsolete by recent changes, we now optimize the experience for users, avoiding recreate at boot unless checksums for configuration or base image have changed. This was also a good time to explain the difference between mutable and immutable tags, which sometimes is a cause for great confusion. Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
1 parent ff175c0 commit ef73ec6

File tree

1 file changed

+192
-51
lines changed

1 file changed

+192
-51
lines changed

doc/container.md

Lines changed: 192 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -246,80 +246,221 @@ archive, which helps greatly with container upgrades (see below):
246246

247247
admin@example:/> show log
248248
...
249-
Nov 20 07:24:56 infix container[5040]: Fetching ftp://192.168.122.1/curios-oci-amd64-v24.05.0.tar.gz
250-
Nov 20 07:24:56 infix container[5040]: curios-oci-amd64-v24.05.0.tar.gz downloaded successfully.
251-
Nov 20 07:24:56 infix container[5040]: curios-oci-amd64-v24.05.0.tar.gz checksum verified OK.
252-
Nov 20 07:24:57 infix container[5040]: Cleaning up extracted curios-oci-amd64-v24.05.0
253-
Nov 20 07:24:57 infix container[5040]: podman create --name sys --conmon-pidfile=/run/container:sys.pid --read-only --replace --quiet --cgroup-parent=containers --restart=always --systemd=false --tz=local --hostname sys --log-driver k8s-file --log-opt path=/run/containers/sys.fifo --network=none curios-oci-amd64-v24.05.0
254-
Nov 20 07:24:57 infix container[3556]: b02e945c43c9bce2c4be88e31d6f63cfdb1a3c8bdd02179376eb059a49ae05e4
249+
Nov 20 07:24:56 example container[5040]: Fetching ftp://192.168.122.1/curios-oci-amd64-v24.05.0.tar.gz
250+
Nov 20 07:24:56 example container[5040]: curios-oci-amd64-v24.05.0.tar.gz downloaded successfully.
251+
Nov 20 07:24:56 example container[5040]: curios-oci-amd64-v24.05.0.tar.gz checksum verified OK.
252+
Nov 20 07:24:57 example container[5040]: Cleaning up extracted curios-oci-amd64-v24.05.0
253+
Nov 20 07:24:57 example container[5040]: podman create --name sys --conmon-pidfile=/run/container:sys.pid --read-only --replace --quiet --cgroup-parent=containers --restart=always --systemd=false --tz=local --hostname sys --log-driver k8s-file --log-opt path=/run/containers/sys.fifo --network=none curios-oci-amd64-v24.05.0
254+
Nov 20 07:24:57 example container[3556]: b02e945c43c9bce2c4be88e31d6f63cfdb1a3c8bdd02179376eb059a49ae05e4
255255

256256

257-
Upgrading a Container Image
257+
Understanding Image Tags
258+
------------------------
259+
260+
Docker images use tags to identify different versions of the same image.
261+
Understanding the difference between *mutable* and *immutable* tags is
262+
important for managing container upgrades effectively.
263+
264+
### Mutable Tags
265+
266+
Tags like `:latest`, `:edge`, or `:stable` are *mutable* — they point to
267+
different images over time as new versions are published to the registry.
268+
269+
**Advantages:**
270+
271+
- Convenient: upgrade without changing configuration
272+
- Simple: use the CLI command `container upgrade NAME` to get the latest version,
273+
there is even a convenient RPC for controlling the remotely
274+
- Good for: development, testing, and systems that auto-update
275+
276+
**Trade-offs:**
277+
278+
- Less reproducible: different systems may run different versions
279+
- Less predictable: upgrades happen when you pull, not when you plan
280+
- Harder to rollback: previous version may no longer be available
281+
282+
**Example mutable tags:**
283+
284+
```
285+
docker://nginx:latest # Always points to newest release
286+
docker://myapp:edge # Development/bleeding edge version
287+
oci-archive:/var/tmp/app.tar # Local archive that may be replaced
288+
```
289+
290+
### Immutable Tags
291+
292+
Version-specific tags like `:v1.0.1`, `:24.11.0`, or digest references
293+
like `@sha256:abc123...` are *immutable* — they always reference the
294+
exact same image content.
295+
296+
**Advantages:**
297+
298+
- Reproducible: all systems run identical versions
299+
- Predictable: upgrades only happen when you change configuration
300+
- Auditable: clear history of what ran when
301+
- Good for: production, compliance, and controlled deployments
302+
303+
**Trade-offs:**
304+
305+
- More explicit: must update configuration to upgrade
306+
- Requires planning: need to know which version to use
307+
308+
**Example immutable tags:**
309+
310+
```
311+
docker://nginx:1.25.3 # Specific version number
312+
docker://myapp:v2.1.0 # Semantic version tag
313+
docker://nginx@sha256:abc123 # Cryptographic digest (most immutable)
314+
```
315+
316+
> [!TIP]
317+
> **Best practice for production:** Use specific version tags (`:v1.0.1`)
318+
> rather than mutable tags (`:latest`). This ensures all your systems run
319+
> identical software and upgrades happen only when you decide.
320+
321+
Upgrading Container Images
258322
---------------------------
323+
259324
![Up-to-date Shield](img/shield-checkmark.svg){ align=right width="100" }
260325

261326
The applications in your container are an active part of the system as a
262327
whole, so make it a routine to keep your container images up-to-date!
263328

264-
Containers are created at first setup and at every boot. If the image
265-
exists in the file system it is reused -- i.e., an image pulled from a
266-
remote registry is not fetched again.
329+
### How Container Lifecycle Works
330+
331+
Infix intelligently manages container lifecycles to provide a smooth
332+
experience while minimizing unnecessary work:
333+
334+
**At first setup:** When you configure a container for the first time,
335+
Infix fetches the image (if needed) and creates the container instance.
336+
337+
**At boot time:** Infix checks if the container needs to be recreated by
338+
comparing checksums for:
339+
340+
- The image archive that the container was built from
341+
- The container configuration script
342+
343+
**When configuration changes:** If you modify any container settings
344+
(network, volumes, environment, etc.), the container is automatically
345+
recreated with the new configuration.
346+
347+
**When explicitly upgraded:** Using the `container upgrade` command forces
348+
a fresh pull of the image and recreates the container.
349+
350+
This means that in most cases, **containers persist across reboots** and
351+
are only recreated when actually necessary. Your container's state stored
352+
in volumes is preserved across recreations. Since Infix containers use a
353+
read-only root filesystem, any changes written outside of volumes or the
354+
writable paths provided by Podman (`/dev`, `/dev/shm`, `/run`, `/tmp`,
355+
`/var/tmp`) will be lost when the container is recreated.
356+
357+
### Method 1: Upgrading Immutable Tags
267358

268-
To upgrade a versioned image:
269-
- update your `running-config` to use the new `image:tag`
270-
- `leave` to activate the change, if you are in the CLI
271-
- Podman pulls the new image in the background
272-
- Your container is recreated with the new image
273-
- The container is started
359+
When using version-specific tags, you upgrade by explicitly changing the
360+
image reference in your configuration:
274361

275-
For "unversioned" images, e.g., images using a `:latest` or `:edge` tag,
276-
use the following CLI command (`NAME` is the name of your container):
362+
```
363+
admin@example:/> configure
364+
admin@example:/config/> edit container web
365+
admin@example:/config/container/web/> set image docker://nginx:1.25.3
366+
admin@example:/config/container/web/> leave
367+
```
277368

278-
admin@example:/> container upgrade NAME
369+
**What happens:**
279370

280-
This stops the container, does `container pull IMAGE`, and recreates it
281-
with the new image. Upgraded containers are automatically restarted.
371+
1. Podman pulls the new image in the background (if not already present)
372+
2. Your container is automatically stopped
373+
3. The container is recreated with the new image
374+
4. The container is started with your existing volumes intact
375+
376+
**Example:** Upgrading from one version to another:
377+
378+
```
379+
admin@example:/> configure
380+
admin@example:/config/> edit container system
381+
admin@example:/config/container/system/> show image
382+
image ghcr.io/kernelkit/curios:v24.11.0;
383+
admin@example:/config/container/system/> set image ghcr.io/kernelkit/curios:v24.12.0
384+
admin@example:/config/container/system/> leave
385+
admin@example:/> show log
386+
...
387+
Dec 13 14:32:15 example container[1523]: Pulling ghcr.io/kernelkit/curios:v24.12.0...
388+
Dec 13 14:32:18 example container[1523]: Stopping old container instance...
389+
Dec 13 14:32:19 example container[1523]: Creating new container with updated image...
390+
Dec 13 14:32:20 example container[1523]: Container system started successfully
391+
```
392+
393+
### Method 2: Upgrading Mutable Tags
394+
395+
For images using mutable tags like `:latest` or `:edge`, use the
396+
`container upgrade` command:
397+
398+
```
399+
admin@example:/> container upgrade NAME
400+
```
401+
402+
This command:
403+
404+
1. Stops the running container
405+
2. Pulls the latest version of the image from the registry
406+
3. Recreates the container with the new image
407+
4. Starts the container automatically
282408

283409
**Example using registry:**
284410

285-
admin@example:/> container upgrade system
286-
system
287-
Trying to pull ghcr.io/kernelkit/curios:edge...
288-
Getting image source signatures
289-
Copying blob 07bfba95fe93 done
290-
Copying config 0cb6059c0f done
291-
Writing manifest to image destination
292-
Storing signatures
293-
0cb6059c0f4111650ddbc7dbc4880c64ab8180d4bdbb7269c08034defc348f17
294-
system: not running.
295-
59618cc3c84bef341c1f5251a62be1592e459cc990f0b8864bc0f5be70e60719
296-
297-
An OCI archive image can be upgraded in a similar manner, the first step
298-
is of course to get the new archive onto the system (see above), and
299-
then, provided the `oci-archive:/path/to/archive` format is used, call
300-
the upgrade command as
301-
302-
admin@example:/> container upgrade system
303-
Upgrading container system with local archive: oci-archive:/var/tmp/curios-oci-amd64.tar.gz ...
304-
7ab4a07ee0c6039837419b7afda4da1527a70f0c60c0f0ac21cafee05ba24b52
305-
306-
OCI archives can also be fetched from ftp/http/https URL, in that case
307-
the upgrade can be done the same way as a registry image (above).
411+
```
412+
admin@example:/> container upgrade system
413+
system
414+
Trying to pull ghcr.io/kernelkit/curios:edge...
415+
Getting image source signatures
416+
Copying blob 07bfba95fe93 done
417+
Copying config 0cb6059c0f done
418+
Writing manifest to image destination
419+
Storing signatures
420+
0cb6059c0f4111650ddbc7dbc4880c64ab8180d4bdbb7269c08034defc348f17
421+
system: not running.
422+
59618cc3c84bef341c1f5251a62be1592e459cc990f0b8864bc0f5be70e60719
423+
```
424+
425+
**Example using local OCI archive:**
426+
427+
An OCI archive image can be upgraded in a similar manner. First, get the
428+
new archive onto the system (see Container Images section above), then,
429+
provided the `oci-archive:/path/to/archive` format is used in your
430+
configuration, call the upgrade command:
431+
432+
```
433+
admin@example:/> container upgrade system
434+
Upgrading container system with local archive: oci-archive:/var/tmp/curios-oci-amd64.tar.gz ...
435+
7ab4a07ee0c6039837419b7afda4da1527a70f0c60c0f0ac21cafee05ba24b52
436+
```
437+
438+
OCI archives can also be fetched from ftp/http/https URLs. In that case,
439+
the upgrade works the same way as a registry image — Infix downloads the
440+
new archive and recreates the container.
441+
442+
### Embedded Container Images
308443

309444
> [!TIP]
310445
> Containers running from OCI images embedded in the operating system,
311-
> e.g., `/lib/oci/mycontainer.tar.gz`, always run from the version in
312-
> the operating system. To upgrade, install the new container image at
313-
> build time, after system upgrade the container is also upgraded. The
314-
> system unpacks and loads the OCI images into Podman every boot, which
315-
> ensures the running container always has known starting state.
446+
> e.g., `/lib/oci/mycontainer.tar.gz`, are automatically kept in sync
447+
> with the Infix system image version.
448+
>
449+
> **How it works:** When you build a custom Infix image with embedded OCI
450+
> archives, those containers will be upgraded whenever you upgrade the
451+
> Infix operating system itself. At boot, Infix checks if the embedded
452+
> image has changed and automatically recreates the container if needed.
316453
>
317454
> **Example:** default builds of Infix include a couple of OCI images
318455
> for reference, one is `/lib/oci/curios-nftables-v24.11.0.tar.gz`, but
319456
> there is also a symlink called `curios-nftables-latest.tar.gz` in the
320457
> same directory, which is what the Infix regression tests use in the
321-
> image configuration of the container. This is what enables easy
322-
> upgrades of the container along with the system itself.
458+
> image configuration of the container. When the system is upgraded and
459+
> the embedded image changes, the test containers are automatically
460+
> recreated with the new version.
461+
>
462+
> This approach ensures your embedded containers always match your system
463+
> version without any manual intervention.
323464
324465

325466
Capabilities

0 commit comments

Comments
 (0)