Skip to content

FlociContainer socket bind breaks on rootless Podman — :z relabel of root-owned socket fails with EPERM #223

Description

@jimisola

Describe the bug

FlociContainer's constructor unconditionally binds the host Docker/Podman socket:

// Allow creation of child container instances (e.g. for ECS or RDS service)
withFileSystemBind(DockerClientFactory.instance().getRemoteDockerUnixSocketPath(), DOCKER_SOCKET_PATH);

On rootless Podman (macOS Podman machine, SELinux enforcing), the container fails to start:

InternalServerErrorException: Status 500: failed to change selinux label: insufficient
permissions, possibly due to a file owned by another user (current user: uid 501):
lsetxattr(label=system_u:object_r:container_file_t:s0) /var/run/docker.sock: operation not permitted

Root cause

At runtime the socket bind carries the SELinux :z relabel flag (verified — CreateContainerCmd shows secMode=z). Rootless Podman then tries to relabel the root-owned socket via lsetxattr, which fails with EPERM (a rootless user cannot relabel a root-owned file).

Note: Floci does not request :z — the socket uses the 2-arg withFileSystemBindSelinuxContext.NONE. The :z is added by the Testcontainers bind-assembly layer. But the relabel only fails because the socket is bound at all, and for S3 (and other non-container services) the socket is unnecessary — per the docs: "Lambda, ElastiCache, and RDS require access to the Docker socket. If you don't use these services, you can omit that volume."

Reproduction (pure podman run, no Java):

Command Result
podman run --rm -v /var/run/docker.sock:/var/run/docker.sock alpine true works
same + :z or :Z fails: lsetxattr … operation not permitted
same + --security-opt label=disable works

Environment

  • testcontainers-floci 2.9.0, Testcontainers 2.0.5
  • Podman 6.0 rootless, macOS (Apple Silicon), Podman machine = Fedora CoreOS, SELinux enforcing

Current workaround (strip the bind, since S3 doesn't need it):

new FlociContainer()
    .withCreateContainerCmdModifier(cmd -> {
        HostConfig h = cmd.getHostConfig();
        if (h != null && h.getBinds() != null) {
            h.withBinds(Arrays.stream(h.getBinds())
                .filter(b -> !b.getPath().contains("docker.sock"))
                .toArray(Bind[]::new));
        }
    });

Proposed fix

Make the socket bind conditional — bind only when a Docker-dependent service (Lambda/RDS/ECS/ElastiCache/OpenSearch/MSK) is actually enabled. Or expose an explicit withoutDockerSocket() opt-out. Happy to send a PR if you point me at the preferred approach.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions