Skip to content

Uninstalling Docker Desktop Leaves Dangling Symlinks in /usr/local/bin

Dragging Docker.app to the Trash removes the application but not the CLI shims it installed. What's left is a set of dangling symlinks pointing into a bundle that no longer exists:

$ docker --version
bash: /usr/local/bin/docker: No such file or directory

Note the error names a path that is in PATH — this is not "command not found". The symlink resolves, its target doesn't.

The Short Answer

# See what's actually broken (dangling symlinks only):
find /usr/local/bin -type l ! -exec test -e {} \; -print

# Remove Docker Desktop's shims (root-owned, needs sudo):
sudo rm -f /usr/local/bin/docker /usr/local/bin/docker-compose \
           /usr/local/bin/docker-credential-desktop \
           /usr/local/bin/docker-credential-ecr-login \
           /usr/local/bin/docker-credential-osxkeychain \
           /usr/local/bin/kubectl /usr/local/bin/kubectl.docker

# Leftover config (contexts, buildx state, credential helper settings):
rm -rf ~/.docker

Check ~/.docker/config.json before deleting if you ever logged into a registry or defined remote contexts — see below.

Don't Forget kubectl

Docker Desktop installs kubectl and kubectl.docker into the same directory. These are easy to miss because they aren't obviously Docker-named, and a broken kubectl will look like an unrelated Kubernetes problem later:

$ ls -l /usr/local/bin/kubectl
lrwxr-xr-x  1 root  wheel  55 Aug  4 20:50 /usr/local/bin/kubectl -> /Applications/Docker.app/Contents/Resources/bin/kubectl

If you use kubectl from Homebrew, removing the Docker shim is required for the real one to take precedence anyway.

Check ~/.docker Before Deleting It

Usually disposable, occasionally not. Two things worth a look:

cat ~/.docker/config.json                                  # registry logins
find ~/.docker/contexts -name meta.json -exec cat {} \;    # remote contexts
  • auths — if non-empty, you have stored registry credentials. Deleting is still fine (you'll re-authenticate), but know that you are discarding them.
  • contexts — a context pointing at a remote Docker host (over SSH or TCP) is real configuration worth keeping if you'll use docker again from another install. A lone desktop-linux context pointing at a local socket is dead weight once the app is gone.

Why sudo Is Needed — and Why It May Fail in an Agent Shell

The symlinks are root:wheel in a root-owned directory, so removal needs sudo. In a non-interactive shell — an AI coding agent, a CI job, an ssh host 'cmd' invocation — sudo cannot prompt:

sudo: a terminal is required to read the password; either use the -S option
to read from standard input or configure an askpass helper

Prefixing the command to run it in the calling terminal usually doesn't help either, because that shell is typically not a TTY. On macOS, the reliable workaround is to let the system present a GUI authentication dialog:

osascript -e 'do shell script "rm -f /usr/local/bin/docker /usr/local/bin/kubectl" with administrator privileges'

You authenticate in the standard macOS prompt; no password passes through the shell.

Verifying You're Actually Clean

ls -l /usr/local/bin/        # nothing pointing into /Applications/Docker.app
ls -d /Applications/Docker.app ~/.docker 2>&1
which -a docker docker-compose kubectl
brew list --cask | grep -i docker
brew list --formula | grep -iE "docker|colima|podman|lima"

A clean machine returns no Docker entries from any of these. If you removed Docker in favour of another runtime, remember the replacement (colima, podman, OrbStack, Rancher Desktop) provides its own docker shim — install it after clearing the dangling ones, or the stale symlink can shadow it.