@@ -301,6 +301,76 @@ remove_warm_container() {
301301 fi
302302}
303303
304+ container_launch_mount_arg () {
305+ printf ' type=bind,src=%s,dst=/usr/local/bin/dclaude-container-launch,readonly\n' \
306+ " $TOOL_HOME /scripts/container-launch.sh"
307+ }
308+
309+ remove_container_launch_mount () {
310+ local mount_arg
311+ local i
312+ local -a filtered_args=()
313+
314+ mount_arg=" $( container_launch_mount_arg) "
315+
316+ i=0
317+ while [ " $i " -lt " ${# DOCKER_ARGS[@]} " ]; do
318+ if [ " ${DOCKER_ARGS[$i]} " = " --mount" ] \
319+ && [ $(( i + 1 )) -lt " ${# DOCKER_ARGS[@]} " ] \
320+ && [ " ${DOCKER_ARGS[$((i + 1))]} " = " $mount_arg " ]; then
321+ i=$(( i + 2 ))
322+ continue
323+ fi
324+
325+ filtered_args+=(" ${DOCKER_ARGS[$i]} " )
326+ i=$(( i + 1 ))
327+ done
328+
329+ DOCKER_ARGS=(" ${filtered_args[@]} " )
330+ }
331+
332+ should_retry_without_container_launch_mount () {
333+ local stderr_path=" $1 "
334+ local container_launch_path=" $TOOL_HOME /scripts/container-launch.sh"
335+
336+ grep -Eq ' invalid mount config for type "bind"|Mounts denied' " $stderr_path " \
337+ && grep -Fq " $container_launch_path " " $stderr_path "
338+ }
339+
340+ start_warm_container () {
341+ local stderr_file
342+ local status
343+
344+ stderr_file=" $( mktemp) "
345+
346+ if docker " ${DOCKER_ARGS[@]} " \
347+ " $DCLAUDE_IMAGE_NAME " \
348+ tail -f /dev/null > /dev/null 2> " $stderr_file " ; then
349+ rm -f " $stderr_file "
350+ return 0
351+ fi
352+
353+ status=$?
354+
355+ if should_retry_without_container_launch_mount " $stderr_file " ; then
356+ echo " warning: docker rejected bind mounting $TOOL_HOME /scripts/container-launch.sh; using the launcher baked into the image instead" >&2
357+ remove_container_launch_mount
358+
359+ if docker " ${DOCKER_ARGS[@]} " \
360+ " $DCLAUDE_IMAGE_NAME " \
361+ tail -f /dev/null > /dev/null 2> " $stderr_file " ; then
362+ rm -f " $stderr_file "
363+ return 0
364+ fi
365+
366+ status=$?
367+ fi
368+
369+ cat " $stderr_file " >&2
370+ rm -f " $stderr_file "
371+ return " $status "
372+ }
373+
304374create_warm_container () {
305375 local tool=" $1 "
306376
@@ -328,9 +398,10 @@ create_warm_container() {
328398 append_ssh_mounts
329399 fi
330400
331- docker " ${DOCKER_ARGS[@]} " \
332- " $DCLAUDE_IMAGE_NAME " \
333- tail -f /dev/null > /dev/null
401+ if ! start_warm_container; then
402+ remove_warm_container
403+ die " failed to create warm container $WARM_CONTAINER_NAME "
404+ fi
334405
335406 if ! docker exec \
336407 --user " $HOST_UID :$HOST_GID " \
@@ -779,26 +850,15 @@ validate_wrapper_args() {
779850
780851append_common_mounts () {
781852 local mount_path
782- local container_launch_path=" $TOOL_HOME /scripts/container-launch.sh"
783853
784854 DOCKER_ARGS+=(
785855 --mount " type=bind,src=$TARGET_REPO_ROOT ,dst=$TARGET_REPO_ROOT "
856+ --mount " $( container_launch_mount_arg) "
786857 --mount " type=bind,src=$HOST_HOME /.cache/dclaude/cx,dst=$HOST_HOME /.cache/cx"
787858 --mount " type=bind,src=$HOST_HOME /.cache/pip,dst=$HOST_HOME /.cache/pip"
788859 --mount " type=bind,src=$HOST_HOME /.cache/uv,dst=$HOST_HOME /.cache/uv"
789860 )
790861
791- case " $TOOL_HOME " in
792- * /Cellar/* )
793- ;;
794- * )
795- [ -f " $container_launch_path " ] || die " missing container launch script at $container_launch_path "
796- DOCKER_ARGS+=(
797- --mount " type=bind,src=$container_launch_path ,dst=/usr/local/bin/dclaude-container-launch,readonly"
798- )
799- ;;
800- esac
801-
802862 if (( ${# CONFIGURED_HOME_MOUNTS[@]} > 0 )) ; then
803863 for mount_path in " ${CONFIGURED_HOME_MOUNTS[@]} " ; do
804864 DOCKER_ARGS+=(
0 commit comments