Skip to content

[Bug]: --mount type=tmpfs creates a mount with an empty source field, breaking df and mount #2109

Description

@egernst

I have done the following

  • I have searched the existing issues
  • If possible, I've reproduced the issue using the 'main' branch of this project

Steps to reproduce

Environment: container CLI 1.2.2.0 (commit 0190097), macOS 26.

Reproduction

Mount a tmpfs with --mount and ask df about it:

% container run --rm --mount type=tmpfs,target=/tmpfsmount1,size=512M alpine df -h /tmpfsmount1
Filesystem                Size      Used Available Use% Mounted on
df: tmpfs: No such file or directory

Problem description

The mount is also absent from a plain df -h with no path argument. Doing the same thing with the --tmpfs flag works as expected:

% container run --rm --tmpfs /tmpfsmount1 alpine df -h
...
tmpfs                   556.1M         0    556.1M   0% /tmpfsmount1

The inconsistency is visible directly in /proc/mounts. Note the leading space on the first line — field 1, the device/source, is empty:

% container run --rm --mount type=tmpfs,target=/tmpfsmount1,size=512M alpine grep tmpfsmount1 /proc/mounts
 /tmpfsmount1 tmpfs rw,relatime,size=524288k 0 0

% container run --rm --tmpfs /tmpfsmount1 alpine grep tmpfsmount1 /proc/mounts
tmpfs /tmpfsmount1 tmpfs rw,relatime 0 0

Any tool that parses /proc/mounts positionally shifts every field left by one, so mount also misreports the entry, printing the target as the source and the options as the filesystem type:

% container run --rm --mount type=tmpfs,target=/tmpfsmount1,size=512M alpine mount | grep tmpfsmount1
/tmpfsmount1 on tmpfs type rw,relatime,size=524288k (0)

The mount itself is correct — size=524288k is the requested 512 MiB, and it's writable. Only its representation in the mount table is wrong. stat -f /tmpfsmount1 reports the right values, since it doesn't go through /proc/mounts.

Root cause

Two code paths construct tmpfs mounts, and only one of them sets a source.

Filesystem.init() defaults source to the empty string (Sources/ContainerResource/Container/Filesystem.swift:74), while the Filesystem.tmpfs(destination:options:) factory sets source: "tmpfs" (Filesystem.swift:128). The --tmpfs flag goes through the factory, which is why it's correct.

Parser.mount instead starts from var fs = Filesystem() and, in its type=tmpfs branch, assigns type, destination, and options but never source (Sources/Services/ContainerAPIService/Client/Parser.swift:419), so the empty default survives into the guest.

Tests/ContainerAPIClientTests/ParserTest.swift already has tmpfs parsing cases from #2103 that a regression test asserting the source field could hang off.

Environment

- OS: 26
- Container: 1.2.2

Code of Conduct

  • I agree to follow this project's Code of Conduct

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions