Skip to content

Instantly share code, notes, and snippets.

@BretFisher
Last active September 18, 2024 18:51
Show Gist options
  • Save BretFisher/5e1a0c7bcca4c735e716abf62afad389 to your computer and use it in GitHub Desktop.
Save BretFisher/5e1a0c7bcca4c735e716abf62afad389 to your computer and use it in GitHub Desktop.
Getting a Shell in the Docker Desktop Mac VM

2021 Update: Easiest option is Justin's repo and image

Just run this from your Mac terminal and it'll drop you in a container with full permissions on the Docker VM. This also works for Docker for Windows for getting in Moby Linux VM (doesn't work for Windows Containers).

docker run -it --rm --privileged --pid=host justincormack/nsenter1

more info: https://github.com/justincormack/nsenter1


Option 1 (hard way): use netcat

nc -U ~/Library/Containers/com.docker.docker/Data/debug-shell.sock

Exit the shell with exit.

Option 2 (easier): Use nsenter in priviledged container

docker run -it --privileged --pid=host debian nsenter -t 1 -m -u -n -i sh

Phil Estes (Docker Maintainer) says:

it’s running a container (using the debian image. nothing special about it other than it apparently has nsenter installed), with pid=host (so you are in the process space of the mini VM running Docker4Mac), and then nsenter says “whatever is pid 1, use that as context, and enter all the namespaces of that, and run a shell there"

Option 3 (easist): run nsenter from a pre-built image. From Justin Cormack (Docker Maintainer)

docker run -it --rm --privileged --pid=host justincormack/nsenter1

@tatsushid
Copy link

I can use the debug shell normally in this way

  1. Open debug-shell.sock by socat command with pty endpoint
  2. Open the pty with screen command
$ socat -d -d ~/Library/Containers/com.docker.docker/Data/debug-shell.sock pty,rawer # it should show "PTY is /dev/ttys0xx" like line.
$ screen /dev/ttys0xx

@deeTEEcee
Copy link

deeTEEcee commented Dec 3, 2020

thanks for this. i went through a deep rabbit hole due to broken, dead containers and really felt like it was important to delete them and was finally able to do that with this available.

EDIT: TIL about colima I might give that a shot as an alternative to Docker Desktop to see if that works better for me.

@arreusch
Copy link

arreusch commented Jan 7, 2021

Just like to poke around. Put this in a shell script.

TTY_TMP=$(mktemp)
$(socat -d -d ~/Library/Containers/com.docker.docker/Data/debug-shell.sock pty,rawer 2>&1 | grep -Eo --line-buffered "/dev/tty\w+" > ${TTY_TMP} ) &
sleep 2
TTY=$(tail -n 1 "${TTY_TMP}")
picocom $TTY 2>/dev/null

@hastiAu
Copy link

hastiAu commented Jan 7, 2021

I have an image for sql on mac
then i create a volume :dbdata
now I want to mount it with this command:
docker run -v /var/folders:/var/opt/mssql/data mcr.microsoft.com/mssql/server:2019-latest

but i see this error :
SQL Server 2019 will run as non-root by default.
This container is running as user mssql.

how do i do ?

@51enra
Copy link

51enra commented Jan 22, 2021

Regarding the "2021 Update":
It's no longer necessary to use Justin Cormack's modification; the outstanding issue he mentions seems to be resolved. The first option he gives in his repo works just fine:
docker run -it --rm --privileged --pid=host alpine:edge nsenter -t 1 -m -u -n -i sh

@KishoreNamala
Copy link

how do we exit out of the terminal opened by the screen command ? I keep getting a new shell prompt in docker desktop

@emandret
Copy link

emandret commented Jan 8, 2022

The shell obtained by opening debug-shell.sock is very limited as it's a busybox executable. You can try to access the regular VM console with: socat ~/Library/Containers/com.docker.docker/Data/vms/0/console.sock -,rawer (exit by closing the terminal window as the prompt is configured to auto login).

@bcoughlan
Copy link

Here's an example of how to install packages on the VM (htop in this case):

docker run -it --rm --privileged --pid=host justincormack/nsenter
$ mount -o remount,rw /
$ mkdir /var/cache/apk
$ apk add htop

@zwass
Copy link

zwass commented Jul 26, 2022

docker run -it --rm --privileged --pid=host alpine:edge nsenter -t 1 -m -u -n -i sh as suggested in justincormack/nsenter seems to work just fine with Docker Desktop 4.10.1 on macOS.

@rimelek
Copy link

rimelek commented Aug 23, 2022

I just want to say thanks to @BretFisher and also everyone who commented, because using these suggested commands helped me to understend Docker Desktop more. I started to use console.sock, because I didn't know what was the difference between that and the debug shell. Then I realized when I intentionally broke my Docker Desktop and started to see logs in the console, but not in the debug shell. :) It was useful while I was working on a new tutorial.

@bwalsh
Copy link

bwalsh commented Dec 29, 2022

Thanks very much. Very useful

@socay1
Copy link

socay1 commented Jan 6, 2023

nc -U ~/Library/Containers/com.docker.docker/Data/debug-shell.sock

It's nice, but commond prompt / # ^[[61;5R

@subhasis68
Copy link

Regarding the "2021 Update": It's no longer necessary to use Justin Cormack's modification; the outstanding issue he mentions seems to be resolved. The first option he gives in his repo works just fine: docker run -it --rm --privileged --pid=host alpine:edge nsenter -t 1 -m -u -n -i sh

@subhasis68
Copy link

docker run -it --rm --privileged --pid=host alpine:edge nsenter -t 1 -m -u -n -i sh ==> This worked like a charm on Macbook Air Ventura 13.0.1 with Docker Desktop Version 4.16.2 (95914). Thanks a lot.

@n-rodriguez
Copy link

n-rodriguez commented Mar 25, 2023

Inspired by : https://github.com/jpetazzo/nsenter

/usr/local/bin/docker-enter :

#!/bin/sh

if [ -z "$1" ]; then
  echo "Usage: `basename "$0"` CONTAINER [COMMAND [ARG]...]"
  echo ""
  echo "Enters the Docker CONTAINER and executes the specified COMMAND."
  echo "If COMMAND is not specified, runs an interactive shell in CONTAINER."
  exit
fi

PID=$(docker inspect --format "{{.State.Pid}}" "$1")
[ -z "$PID" ] && exit 1
shift

# Prepare nsenter flags
OPTS="--target $PID --mount --uts --ipc --net --pid --"

docker run -it --rm --privileged --pid=host alpine:edge nsenter -t 1 -m -u -n -i nsenter $OPTS bash

To use it : docker-enter <container id>

It is different from docker exec -it CONTAINER_NAME /bin/bash as you enter in the container as root ;)

@n-rodriguez
Copy link

@rimelek
Copy link

rimelek commented Mar 25, 2023

@n-rodriguez

It is different from docker exec -it CONTAINER_NAME /bin/bash as you enter in the container as root ;)

You could just use

docker exec --user root -it CONTAINER_NAME /bin/bash

:) But writing a script like yours is a good way to learn how containers work.

@rob-weiss
Copy link

I would like to make persistent changes to the VM, but after I restart the container they are gone. More specifically, I'm trying to change the proxy environment variables inside the VM. Any chance to make these changes persistent?

When making the changes in the first place, I get Read-only file system on save and fixed it like so.

@BretFisher
Copy link
Author

@rob-weiss that doesn't sound like the best way to set proxy ENVs. 1st, you should be setting those in the Docker Desktop settings under Resources. Then, you should change them in your docker CLI config: https://docs.docker.com/network/proxy/

@inieves
Copy link

inieves commented Sep 21, 2023

I am running with userns. It seems that as a result, none of the --privileged solutions work. I receive:
docker: Error response from daemon: privileged mode is incompatible with user namespaces. You must run the container in the host namespace when running privileged mode.

I tried all other solutions in this thread. None work.

Any thoughts on how to get into the underlying VM while in userns mode?

@lrtfm
Copy link

lrtfm commented Apr 18, 2024

Remove the control sequence like ^[[5;5R from the nc solution: (https://x.com/developerguyba/status/1458109231169691654)

stty -echo -icanon && nc -U ~/Library/Containers/com.docker.docker/Data/debug-shell.sock && stty sane

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment