Skip to content

Docker image's entrypoint dbus init fails when run as non-root UID #2543

@leighmcculloch

Description

@leighmcculloch

What version are you using?

stellar/stellar-cli:latest — image digest sha256:cb2fc3116a6ace37a77ca6bb88afb4bee57fc746cd556a4373f2c3ee95d4e917

What did you do?

Ran the official image with the host user's UID/GID so files written to a bind-mounted source directory wouldn't end up root-owned on the host:

docker run --rm \
    --platform linux/amd64 \
    --user 501:20 \
    -v $PWD:/source \
    stellar/stellar-cli:latest \
    contract build

What did you expect to see?

stellar contract build runs against /source and writes the wasm to /source/target/.... No keyring access is needed for contract build, so dbus / gnome-keyring shouldn't matter.

What did you see instead?

dbus[7]: Could not get password database information for UID of current process: Looking up user ID 501: not found
dbus[7]: Failed to start message bus: Memory allocation failure in message bus

…and the container exits non-zero before stellar even runs.

Why this happens

The image's entrypoint.sh launches a session dbus and unlocks gnome-keyring before exec-ing stellar:

#!/bin/bash
set -e

# Start D-Bus session bus
export DBUS_SESSION_BUS_ADDRESS="unix:path=/tmp/dbus-session"
dbus-daemon --session --address="$DBUS_SESSION_BUS_ADDRESS" --fork

# Unlock gnome-keyring with an empty password for non-interactive use
eval "$(echo '' | gnome-keyring-daemon --unlock --components=secrets)"
export GNOME_KEYRING_CONTROL
export SSH_AUTH_SOCK

cd /source
exec "$@"

dbus-daemon looks up the running user's name/home in /etc/passwd on startup. When the container runs as a UID that has no /etc/passwd entry (which is what happens for any --user <host-uid>:<host-gid> invocation on a host whose UID isn't 0/1000/etc.), the lookup fails and dbus refuses to start. set -e then exits the entrypoint before stellar runs.

This breaks any non-root use of the image, including any setup that bind-mounts host directories and wants the resulting files to be host-owned.

Workaround

Override the entrypoint to skip entrypoint.sh entirely:

docker run --rm \
    --platform linux/amd64 \
    --user 501:20 \
    -v $PWD:/source \
    --entrypoint stellar \
    stellar/stellar-cli:latest \
    contract build

This works because contract build doesn't touch the keyring. But it's fragile — every non-root caller has to know to override the entrypoint.

Proposal

Two questions, in order:

  1. Does the keyring really need to be in this image? Containers from this image are typically ephemeral (per-build, per-deploy, per-CI-step). A keyring inside an ephemeral container has no credentials to unlock and nothing useful to store. Anyone who actually wants to keep secrets across stellar invocations is more likely to mount their host keyring or pass secrets via env vars. If keyring is genuinely a non-goal for this image, dropping dbus / gnome-keyring (and entrypoint.sh's setup of them) makes the issue go away and trims the image.

  2. If keyring needs to stay, the entrypoint script should be tolerant of the running UID not being in /etc/passwd. Options:

    • Skip the dbus / keyring init when running as a UID without a passwd entry (so non-keyring commands like contract build still work).
    • Add a passwd entry on the fly (e.g. via nss-wrapper or by appending to /etc/passwd if writable) before launching dbus.
    • Make the dbus failure non-fatal (drop set -e for that block) — keyring-using commands would then fail clearly, but everything else works.

Context

Hit while working on stellar contract build --backend docker (#2525), which runs the official image and bind-mounts the workspace. We worked around it in that PR by overriding the entrypoint, but it'd be cleaner if the image worked under non-root UIDs out of the box.

Metadata

Metadata

Labels

bugSomething isn't working

Type

No type

Projects

Status

Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions