Skip to content
melonfleet edited this page Oct 20, 2026 · 10 revisions

Images

Everything you can do with images lives in the Images section: pull them, build them from a Dockerfile, browse Docker Hub, tag them, delete them, prune the unused ones, send them to other Macs, and run a container from one.

Once you have paired a host, the list includes each host's images, with a host chip on the row and a Host filter. The same image on two Macs is two rows, because it is two copies.

Getting an image: one form, two sources

+ in the Images toolbar opens New Image, and Source at the top picks how:

  • Pull — download one somebody else published.
  • Build — make one from a Dockerfile on this Mac.

They were two toolbar buttons and two screens. Both forms are short, and neither filled the column it was given, so they share one screen with one information rail that follows whichever source you pick. The main action at the top right is ▶ for both. Hover over it to see whether it will Pull or Build. Starting either returns you to the Images list, and the job runs in Tasks. Two pulls are two tasks, and a pull or a build on this Mac has a Stop button. Pull Image… and Build Image from Dockerfile… are also in the File menu.

Pulling an image

Give it a Reference — alpine:latest, docker.io/library/nginx:alpine, ghcr.io/example/webapp:1.4.2, or a digest-pinned name@sha256:…. A bare name works; the registry and latest are filled in the way the CLI fills them in, so nginx becomes docker.io/library/nginx:latest.

A tag can be moved by whoever published it. Pin a digest when you need the same bytes every time.

Pulls are slow and Flotilla expects that: the deadline for a pull is 30 minutes, not the few seconds a list command gets. Progress is reported as the CLI reports it.

Pull to: one Mac or several

Once a host is paired, Pull to lists This Mac and every host, each with its container version or why it cannot be asked — "not answering", or "checking…". Tick the Macs you want and each one pulls from the registry itself, all at the same time, with a line per Mac in its task.

A Mac signed in to a private registry pulls with its own sign-in. Flotilla sends none: the admin's registry password never leaves the admin Mac. If a host needs to pull from a private registry, sign that host in on that host — or use Send to Hosts.

Pull from: which registry completes a bare name

Pull from picks the registry a bare name is completed with. A reference that already names a host ignores it — quay.io/prometheus/busybox comes from Quay whatever is picked. Docker Hub is left to the CLI, which adds the library/ namespace that only it has. The picker starts on your default registry; see Registries.

Beside the reference there is Browse Docker Hub when the registry is Docker Hub, or a link to the registry's own website when it has one. registry.k8s.io has none, and a link to nothing is worse than no link.

HTTPS, or HTTP for a development registry

Connect using picks the scheme, and it is HTTPS every time the form opens.

container 1.4.1 removed the old auto scheme that fell back to plaintext on its own, so a registry with no TLS — a loopback or LAN development registry — is unreachable unless you ask for HTTP. Choosing it warns you, in the column and not only in the rail, that image layers cross the network unencrypted.

It has to be an anonymous registry: container refuses to send credentials over HTTP even when you have asked for it, failing with "refusing insecure credential exchange". And the choice is not remembered — a stored "use HTTP" would apply to your next pull from Docker Hub too, which is the silent downgrade 1.4.1 got rid of.

Over HTTP only This Mac pulls. The other Macs in Pull to cannot be ticked. Pulling over plaintext on another Mac is that Mac's owner's decision, not one an admin makes for it, so the fleet connection refuses the scheme flag outright.

Signing in

If a registry needs an account, sign this Mac in from Registries. container keeps the credential in the Keychain, and every pull from this Mac uses it. If you have already authenticated container outside Flotilla, that credential is what gets used.

Browse Docker Hub

The magnifying glass in the Images toolbar opens Browse Docker Hub. With nothing typed it shows the Docker Official Images; type to search, and Show More pages through the rest. Each result says whether it has an Apple silicon build or is Intel only — runs under Rosetta.

Choose an image and its tags appear, newest first, each with its architecture, size and age. Pick a tag and Pull opens the ordinary Pull form with that reference — the browser never pulls by itself.

Some Docker Hub listings are not images you can pull from docker.io by name — Docker Hardened Images, MCP server listings, Docker Desktop extensions and plugins. They are shown dimmed and say which they are, rather than offering a pull that would fail.

The browser asks hub.docker.com only when you open it or type, and the request carries what you typed and nothing else: no account, no cookies. It searches Docker Hub only. If your default registry is another one, the browser says so — that registry has no public search, and pulls from here come from Docker Hub.

Building from a Dockerfile

Choose Build in New Image. You pick a Folder for the context with Choose…, name the Tag — myapp:latest is the placeholder — and Flotilla runs the build on This Mac. Also on the form:

  • Dockerfile, defaulting to <context>/Dockerfile. A path here must stay inside the folder.
  • Target stage, for a multi-stage Dockerfile. Optional.
  • Platform, defaulting to linux/arm64.
  • Build arguments, one KEY=VALUE per row, for the Dockerfile's ARG instructions. These are visible in the image's own history, so they are the wrong place for a token or a password.
  • Ignore the build cache, for when a cached layer is the problem.

Leave the tag empty and container names the image with a random UUID, so it is not findable by name afterwards. The form says so rather than letting you find out.

Why the file panel matters

This is the one place Flotilla deliberately builds a CLI with a boundary of its own, and it is worth understanding because it is the model for how any future exception should look.

A build has to read a directory on your Mac, so for that one command Flotilla builds a CLI scoped to exactly the directory you chose — and nothing else. The Dockerfile, which may sit elsewhere, has to be inside it too, or the same policy refuses it.

The file panel is the authorisation. You picking the folder is the grant. It is narrow, explicit, scoped to a single invocation, and named at the call site rather than inherited from a global setting somebody forgot about.

Two related details:

  • The context path is resolved through symlinks before use. Choosing a folder in a panel and having a link inside it silently redirect the build somewhere else is a real class of bug.
  • The context argument is required, even though the CLI defaults it to .. Defaulting it meant a build silently archived the process working directory — and a relative path cannot be checked against an absolute policy root anyway.

Sending an image to hosts

Send to Hosts… is on the row menu of an image on This Mac. It is for images only This Mac can reach — one built here, or one from a private registry This Mac is signed in to. A public image is quicker pulled by each host itself.

Flotilla saves the image once, as one variant — linux/arm64, or linux/amd64 when there is no arm64 build — and sends that archive to every host you tick, at the same time, with bytes sent shown per host. Each host loads it itself. No credential leaves This Mac, only the image.

Before anything runs, each host says what a send would do there:

  • will receive it;
  • already has it — the exact image is there, so it cannot be ticked;
  • has a different copy of that reference — sending replaces it;
  • not answering, or needs container 1.3.1 or later, which cannot load archives safely before that.

It is This Mac to hosts only. There is no host-to-host copy, and a host's image has no Send. A partial send is reported as a failure that names what did arrive, and the archive is deleted when every host is done with it.

Tagging

A tag is a name pointing at an image, not a copy of it. Tagging docker.io/library/nginx:alpine as myapp:v1 gives you a second name for the same bytes — no disk is used, and deleting one name leaves the image reachable by the other.

It is worth doing when you want a short local name instead of a long registry path, or a stable name like myapp:current that you can re-point at a newer image later without changing anything that refers to it.

Tag… from the row's overflow menu, on the Mac that holds the image. Source and target are both validated as image references before anything runs, and the form shows the container image tag command it will run.

(Images take this kind of tag, a name. Flotilla's own coloured tags — the ones on containers, volumes and networks — are not offered for images.)

Filtering a long image list

A row carries the Tag, Platform, Digest, Size, Created and Host. A platform filter appears once you have images for more than one architecture — it earns its place exactly when an amd64 or multi-arch image lands, because those are the ones that will run under emulation or not at all. The row has a Copy submenu: Reference, Repository, Tag, Digest, and Host for a host's image. See Views and filtering.

Deleting and pruning

Delete… removes one image, on whichever Mac holds it. Delete images no container is using is the prune action — it is labelled by what it does rather than as "Prune", because "prune" does not say what will be lost. With a host paired it says on this Mac, because that is the only Mac it looks at.

Flotilla shows you exactly which images will go, with their sizes, and asks before doing it. That preview always appears, whatever Confirm destructive actions is set to: a bulk prune must show what dies, which is more than a yes or no. "Unused" is worked out from the containers Flotilla can see, so the list you are shown is the list that is deleted.

Bulk deletion always confirms and that cannot be turned off.

Vulnerabilities

An image from the suggestions library shows a Vulnerabilities card on its page, and a chip on its row, when the daily report lists critical or high findings for it. The same card shows on the page of a container made from it. Findings are advice only, and nothing is stopped or changed because of them. An image you built or pulled yourself is not covered. See Vulnerability reports.

Running a container from an image

Run… on an image row opens the run form with that image prefilled, on the Mac that holds it. Same form as Run Container…, so there is one screen to learn rather than two.

What the run form gives you

  • Image reference and container name, and Run on once a host is paired.
  • Published ports, environment variables and volume mounts — each an add-and-remove list with a counter showing how many of the maximum you have used.
  • A Command to run instead of the image's own entrypoint.
  • Detach (run in background) — on for a service, off when you want to watch it.
  • Architecture and Rosetta inside the container; see Containers for the difference.
  • Limit CPU and memory, which reveals the two fields. Left alone, the defaults come from Settings ▸ Resources, and the form says so.
  • A live command preview showing the exact container run … that will execute, updated as you type and validated against the allowlist as you go, with Copy the container command to the clipboard beside it.
  • A verdict rather than a guess: "Valid — ready to run." or "Fix the highlighted field to run this."

Errors stay quiet until a required field has content. An empty image field is not filled in yet, not wrong — an earlier version showed two red validation errors on a form you had not touched.

The preview is the honest part: if the allowlist would refuse what you have typed, you find out on the form rather than after pressing Run. For a host, it is checked against that host's rules.

Empty states say which kind of empty

"Pull one to run a container from it" appears when you have no images, with Pull an Image… and Browse Docker Hub… beside it. If you have images but a filter excludes them all, it says that instead, with Clear Filter. An app that draws the same blank pane for both makes you doubt the filter you just set.

Clone this wiki locally