Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .changeset/issue-102-passthrough-missing-socket-warning.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
bump: patch
---

dind-box: warn when host-image passthrough is opted into but no host socket is
mounted (issue #102).

Running `box-dind` with passthrough enabled (the default `public` mode) **and**
an explicit allowlist (`DIND_HOST_PASSTHROUGH_IMAGES=...`) but **without** the
host Docker socket bind-mounted used to be a silent no-op: the entrypoint copied
nothing, printed nothing, and the first nested `docker run` re-pulled the full
image from the registry with no hint why. Downstream this re-pulled a 30+ GB
image because of a forgotten `-v` flag (`link-assistant/hive-mind#1914`).

A non-empty `DIND_HOST_PASSTHROUGH_IMAGES` is an unambiguous opt-in signal, so
`passthrough_host_images` now emits a single actionable warning in exactly that
case — enabled passthrough + allowlist set + no socket mounted — naming the
missing `-v /var/run/docker.sock:${DIND_HOST_DOCKER_SOCK}:ro` mount. The
present-but-unreachable socket already warned and still does; plain `box-dind`
containers that never set an allowlist stay silent so the default mode is not
spammed. Covered by new cases in `experiments/preload-unit-test.sh` and
documented in `docs/dind/USAGE.md`.
8 changes: 8 additions & 0 deletions docs/dind/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,14 @@ gate, `public` mode still refuses a locally-built or private image even when it
matches a pattern — the allowlist only ever *narrows* the eligible set, it never
widens it past the security filter.

Setting `DIND_HOST_PASSTHROUGH_IMAGES` is an unambiguous "I expect these images
passed through" signal. So if it is set but **no host socket is mounted**, the
entrypoint no longer stays silent — it emits a single warning naming the
missing `-v /var/run/docker.sock:/var/run/host-docker.sock:ro` mount, because
the nested daemon will otherwise re-pull from the registry on the first
`docker run` with no hint as to why (issue #102). Plain `box-dind` containers
that never set an allowlist still see no extra noise when no socket is mounted.

## Commit Cycles

`DIND_SKIP_DAEMON=1` is useful for setup containers where you want to install or
Expand Down
27 changes: 27 additions & 0 deletions experiments/preload-unit-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,33 @@ DIND_HOST_PASSTHROUGH=public DIND_HOST_DOCKER_SOCK="$WORK/absent.sock" \
check "no host save attempted without a socket" bash -c '! test -s "$DOCKER_SAVED"'
check "no warning emitted when socket simply absent" bash -c '! test -s "$WORK/err.log"'

echo "== Case 8b: explicit allowlist + absent socket warns about the missing mount (issue #102) =="
reset_state
# The operator named the images they expect passed through, but forgot the
# host-socket mount. That opt-in signal turns the otherwise-silent no-op into a
# single actionable warning.
DIND_HOST_PASSTHROUGH=public DIND_HOST_DOCKER_SOCK="$WORK/absent.sock" \
DIND_HOST_PASSTHROUGH_IMAGES="hello-world" \
DIND_PRELOAD_TARBALL="" DIND_PRELOAD_IMAGES="" DOCKER_INFO_OK=1 \
preload_into_daemon 2>"$WORK/err.log"
check "no host save attempted without a socket" bash -c '! test -s "$DOCKER_SAVED"'
check "warning names DIND_HOST_PASSTHROUGH_IMAGES" grep -q "DIND_HOST_PASSTHROUGH_IMAGES is set" "$WORK/err.log"
check "warning suggests the -v mount remediation" grep -q -- "-v /var/run/docker.sock:" "$WORK/err.log"

echo "== Case 8c: present-but-unreachable socket still wins over the allowlist warning =="
reset_state
# When a socket file exists but is unreachable, the original (more specific)
# "not accessible" warning fires — even with an allowlist set — and the generic
# missing-mount hint does not.
touch "$WORK/dead.sock"
DIND_HOST_PASSTHROUGH=public DIND_HOST_DOCKER_SOCK="$WORK/dead.sock" \
DIND_HOST_PASSTHROUGH_IMAGES="hello-world" \
DIND_PRELOAD_TARBALL="" DIND_PRELOAD_IMAGES="" DOCKER_INFO_OK=1 HOST_DOCKER_OK=0 \
preload_into_daemon 2>"$WORK/err.log"
check "unreachable-socket warning fires" grep -q "is not accessible; skipping passthrough" "$WORK/err.log"
check "missing-mount hint suppressed when a socket file exists" bash -c '! grep -q "DIND_HOST_PASSTHROUGH_IMAGES is set" "$WORK/err.log"'
rm -f "$WORK/dead.sock"

echo "== Case 9: public mode copies a Docker Hub image, skips a local one =="
reset_state
# A hub image (has a docker.io RepoDigest) and a locally-built one (no digest):
Expand Down
19 changes: 19 additions & 0 deletions tests/dind/example-preload-images.sh
Original file line number Diff line number Diff line change
Expand Up @@ -228,4 +228,23 @@ if ! docker logs "$images_container" 2>&1 | grep -q "images=${fixture_repo}"; th
fi
log "images-allowlist passthrough copied only the named repo and skipped the rest"

# --- Opt-in allowlist but no host socket mounted (issue #102) ---------------
# Setting DIND_HOST_PASSTHROUGH_IMAGES is an unambiguous "pass these through"
# signal. If the operator forgets the `-v` socket mount, passthrough used to be
# a silent no-op and the first nested `docker run` re-pulled from the registry
# with no hint why. The entrypoint must now surface a single actionable warning
# naming the missing mount. Note: NO -v host-sock mount here, on purpose.
no_sock_container="${DIND_EXAMPLE_ID}-passthrough-no-sock"
log "starting consumer with DIND_HOST_PASSTHROUGH_IMAGES set but NO host socket mounted"
run_dind_container "$no_sock_container" \
-e DIND_HOST_PASSTHROUGH=public \
-e "DIND_HOST_PASSTHROUGH_IMAGES=$fixture_repo"
wait_for_inner_docker "$no_sock_container"
wait_for_preload_complete "$no_sock_container"
if ! docker logs "$no_sock_container" 2>&1 | grep -q "DIND_HOST_PASSTHROUGH_IMAGES is set, but no host docker socket is mounted"; then
docker logs "$no_sock_container" >&2 || true
fail "expected a warning when DIND_HOST_PASSTHROUGH_IMAGES is set but no host socket is mounted"
fi
log "missing-socket warning surfaced the forgotten -v mount instead of failing silently"

log "preload example passed"
10 changes: 8 additions & 2 deletions ubuntu/24.04/dind/dind-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -399,11 +399,17 @@ passthrough_host_images() {
host_passthrough_enabled || return 0

if ! host_docker_available; then
# A socket file exists but is unreachable: surface it. Otherwise the common
# "no host socket mounted" case stays silent so the default mode is free.
if [ -n "$DIND_HOST_DOCKER_SOCK" ] && [ -e "$DIND_HOST_DOCKER_SOCK" ]; then
# A socket file exists but is unreachable: surface it.
warn "host docker socket at ${DIND_HOST_DOCKER_SOCK} is not accessible; skipping passthrough"
elif [ -n "$DIND_HOST_PASSTHROUGH_IMAGES" ]; then
# Operator opted in via an allowlist but no host socket is mounted: the
# nested daemon will NOT be seeded and the first nested 'docker run' will
# re-pull from the registry. Surface it instead of failing silently. (issue #102)
warn "host-image passthrough is enabled and DIND_HOST_PASSTHROUGH_IMAGES is set, but no host docker socket is mounted at ${DIND_HOST_DOCKER_SOCK}; the nested daemon will NOT be seeded from the host (first 'docker run' will pull from the registry). Mount it with: -v /var/run/docker.sock:${DIND_HOST_DOCKER_SOCK}:ro"
fi
# Otherwise (no opt-in signal) the common "no host socket mounted" case stays
# silent so plain box-dind containers are not spammed.
return 0
fi

Expand Down