Skip to content
Open
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
25 changes: 25 additions & 0 deletions distrobox
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,31 @@ distrobox_path="$(dirname "${0}")"
distrobox_command="${1}"
shift

# On macOS with Docker Desktop, only paths under $HOME are shared with the
# Docker Linux VM via VirtioFS. Scripts installed to /usr/local/bin (e.g.
# via Homebrew) are not accessible, so Docker creates an empty directory
# placeholder in the VM, causing "exec: /usr/bin/entrypoint: is a directory".
#
# Maintain a managed cache in ~/.local/share/distrobox/ (always under $HOME,
# always VirtioFS-shared). Copy each script only when the installed version
# is newer than the cached copy, so upgrades are picked up automatically.
if [ "$(uname -s)" = "Darwin" ]; then
_dd_data_dir="${XDG_DATA_HOME:-"${HOME}/.local/share"}/distrobox"
mkdir -p "${_dd_data_dir}"
for _dd_script in distrobox-init distrobox-export distrobox-host-exec; do
_dd_src="${distrobox_path}/${_dd_script}"
[ ! -f "${_dd_src}" ] && _dd_src="$(command -v "${_dd_script}" 2> /dev/null || true)"
if [ -f "${_dd_src}" ]; then
_dd_dst="${_dd_data_dir}/${_dd_script}"
if [ ! -f "${_dd_dst}" ] || [ "${_dd_src}" -nt "${_dd_dst}" ]; then
cp -f "${_dd_src}" "${_dd_dst}"
chmod +x "${_dd_dst}"
fi
fi
done
unset _dd_script _dd_src _dd_dst _dd_data_dir
fi

# Simple wrapper to the distrobox utilities.
# We just detect the 1st argument and launch the matching distrobox utility.
case "${distrobox_command}" in
Expand Down
20 changes: 20 additions & 0 deletions distrobox-create
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,26 @@ distrobox_hostexec_path="$(cd "$(dirname "${0}")" && pwd)/distrobox-host-exec"
[ ! -e "${distrobox_export_path}" ] && distrobox_export_path="$(command -v distrobox-export)"
[ ! -e "${distrobox_genentry_path}" ] && distrobox_genentry_path="$(command -v distrobox-generate-entry)"
[ ! -e "${distrobox_hostexec_path}" ] && distrobox_hostexec_path="$(command -v distrobox-host-exec)"
# On macOS with Docker Desktop, prefer the managed cache under
# ~/.local/share/distrobox/ (always VirtioFS-shared) over the installed
# paths. The main distrobox entry point keeps the cache up-to-date; when
# distrobox-create is invoked directly the cache may also exist from a prior
# run via the main entry point.
if [ "$(uname -s)" = "Darwin" ]; then
_dd_data_dir="${XDG_DATA_HOME:-"${HOME}/.local/share"}/distrobox"
for _dd_script in distrobox-init distrobox-export distrobox-host-exec; do
_dd_cached="${_dd_data_dir}/${_dd_script}"
if [ -f "${_dd_cached}" ]; then
case "${_dd_script}" in
distrobox-init) distrobox_entrypoint_path="${_dd_cached}" ;;
distrobox-export) distrobox_export_path="${_dd_cached}" ;;
distrobox-host-exec) distrobox_hostexec_path="${_dd_cached}" ;;
*) ;;
esac
fi
done
unset _dd_script _dd_cached _dd_data_dir
fi
# If the user runs this script as root in a login shell, set rootful=1.
# There's no need for them to pass the --root flag option in such cases.
[ "${container_user_uid}" -eq 0 ] && rootful=1 || rootful=0
Expand Down
39 changes: 39 additions & 0 deletions distrobox-enter
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,45 @@ if [ "${container_status}" != "running" ]; then
# Here, we save the timestamp before launching the start command, so we can
# be sure we're working with this very same session of logs later.
log_timestamp="$(date -u +%FT%T).000000000+00:00"
# On macOS with Docker Desktop + VirtioFS, only paths under $HOME and a
# few system directories (/private, /Volumes) are shared with the Docker
# VM. If distrobox-init lives outside those paths (e.g. /usr/local/bin
# from Homebrew), Docker cannot find the bind-mount source in the VM and
# creates an empty directory placeholder instead, causing the container
# to fail with "exec: /usr/bin/entrypoint: is a directory".
#
# Detect this by reading the stored bind-mount source from
# .HostConfig.Binds (the container config, not .Mounts which is empty
# for stopped containers) and checking whether it is accessible as a
# file. If it is not, copy the current distrobox-init to
# ~/.local/share/distrobox/ (always under $HOME, always shared) and
# write it to the stored source path so the bind-mount resolves to a
# file when the container starts.
entrypoint_source="$(${container_manager} inspect --type container \
--format '{{range .HostConfig.Binds}}{{printf "%s\n" .}}{{end}}' \
"${container_name}" 2> /dev/null |
grep ':/usr/bin/entrypoint' | cut -d: -f1)"
# On macOS with Docker Desktop, .HostConfig.Binds may store paths with a
# /host_mnt prefix (Docker Desktop's VirtioFS mount prefix in the Linux VM).
# Strip the prefix to get the actual macOS path for the file-existence check.
entrypoint_source_check="${entrypoint_source}"
if [ "$(uname -s)" = "Darwin" ]; then
entrypoint_source_check="${entrypoint_source_check#/host_mnt}"
fi
if [ -n "${entrypoint_source}" ] && [ ! -f "${entrypoint_source_check}" ]; then
distrobox_entrypoint_path="$(cd "$(dirname "${0}")" && pwd)/distrobox-init"
[ ! -f "${distrobox_entrypoint_path}" ] &&
distrobox_entrypoint_path="$(command -v distrobox-init 2> /dev/null)"
if [ -f "${distrobox_entrypoint_path}" ]; then
# Remove Docker's empty-directory placeholder (if present) and
# replace it with the actual script so the bind-mount works.
[ -d "${entrypoint_source}" ] && rmdir "${entrypoint_source}" 2> /dev/null
mkdir -p "$(dirname "${entrypoint_source}")"
cp "${distrobox_entrypoint_path}" "${entrypoint_source}"
chmod +x "${entrypoint_source}"
fi
fi
unset entrypoint_source entrypoint_source_check
${container_manager} start "${container_name}" > /dev/null
#
# Check if the container is going in error status earlier than the
Expand Down