Mac Admin

Changes to Docker Desktop for Mac

Today I discovered a “fun” change to Docker Desktop on macOS that affects the deployment method I’ve used in the past. The result was a minor update (from 2.14.1 to 2.15.0) that broke the installation of the application. In this post, I’ll take a quick look at how I’ve deployed the software in the past, what changed and possible ways to work around it.


What was…

Prior to the release of Docker Desktop v2.15.0, I’d used a variation of the common postinstall scripts in order to perform a number of ‘first launch’ steps required by Docker Desktop. Examples of the typical Docker Desktop post installation scripts can be found below:

These postinstall scripts removed the need by Docker Desktop to request local administration rights by generally performing the below steps:

  1. Symlink any command line tools from within the Docker Desktop application, to /usr/local/bin/
  2. Install a helper tool (com.docker.vmnetd) – partly for opening up system level ports without needing local administrative rights
  3. Install and launch a LaunchDaemon to trigger the helper tool
  4. Often configure a hosts file entry for “kubernetes.docker.internal” pointing to “127.0.0.1”
  5. Triggering a silent launch-and-quit of Docker Desktop with admin rights to carry out other miscellaneous tasks that would require admin rights. This is delivered with the command /Applications/Docker.app/Contents/MacOS/Docker --unattended --install-privileged-components

What happened…

Overnight last night (well, overnight Thursday for those in the UK), the developers at Docker released version 2.15.0 of Docker Desktop. After packaging up and pushing out the new package to test devices, an interesting issue was spotted.

Devices that tried to run the update, seem to have installs get stuck on ‘running postinstall scripts’ from the installer package. If the user tried to open Docker Desktop during this period, the application would either open and not respond to any input, or refuse to open at all.

I grabbed a test device, and re-ran the installation package manually watching the install.log (/var/log/install.log) as it ran through, looking for clues. As any good IT Admin should do, I had the postinstall script echo out as it hit each set of tasks and this helped me realise where things were getting stuck. The installer was deploying its payload fine (the Docker Desktop.app was updated on disk) and managed to get partway through the postinstall script before not progressing. The last log output was the script starting the /Applications/Docker.app/Contents/MacOS/Docker --unattended --install-privileged-components command, but it appeared to go no further.

I killed the Installer process, and manually ran this command in Terminal using sudo from the local administrator account. I was greeted by the following output:

Briefly, and annoyingly too quick to catch a screenshot of, the GUI showed a pop-up message warning that running Docker Desktop as root is not safe and has been stopped (paraphrasing from memory). Shortly after disappearing, another larger error window appeared and disappeared – again too quick to grab a screenshot of or to get any helpful information.

After this point, I launched the Docker Desktop application anyway, and was shown a newer, slight different admin prompt request than what I’d seen in the past:

All of this is no good for people deploying Docker Desktop to users without local admin rights, and so felt like a regression in features and functionality – especially not great for a product that now requires payment for larger companies.

Time to dig into the documentation…


What changed?

After some digging, I came across this section of the documentation:

Versions prior to Docker Desktop 4.15, require root access to be granted on the first run. The first time that Docker Desktop is launched the user receives an admin prompt to grant permissions for a privileged helper service com.docker.vmnetd to be installed. For subsequent runs, no root privileges are required. This approach allowed, following the principle of least privilege, root access to be used only for the operations for which it is absolutely necessary, while still being able to use Docker Desktop as an unprivileged user. All privileged operations are run using the privileged helper process com.docker.vmnetd.

For security reasons, starting with the version 4.15, Docker Desktop for Mac does not require the user to run a permanent privileged process. Whenever elevated privileges are needed for a configuration, Docker Desktop prompts the user with information on the task it needs to perform. Most configurations are applied once, subsequent runs do not prompt for privileged access anymore. The only time Docker Desktop may start the privileged process is for binding privileged ports that are not allowed by default on the host OS.

https://docs.docker.com/desktop/mac/permission-requirements/#permission-requirements

So this does at least confirm an intended change from the Docker developers, one that, to my non-developer experienced mind, makes sense. Annoyingly though, this sort of setup won’t work for organisations who’s users are not local administrators.

The Docker Desktop documentation has a fairly good section on the expected permissions required to use the tool (link) so I thought ‘what better a place to start my digging’. And what I found, turned out to be pretty helpful:

In version 4.11 and later of Docker Desktop for Mac, privileged configurations are applied during the installation with the –user flag on the install command. In this case, the user is not prompted to grant root privileges on the first run of Docker Desktop. Specifically, the –user flag:

  • Uninstalls the previous com.docker.vmnetd if present
  • Sets up symlinks for the user
  • Ensures that localhost is resolved to 127.0.0.1

This approach has the limitation that Docker Desktop can only be run by one user account per machine, namely the one specified in the -–user flag.

https://docs.docker.com/desktop/mac/permission-requirements/#installing-from-the-commandline

This looked promising, so on my test Mac I ran the following commands as the local admin account:

currentUser="$(/usr/sbin/scutil <<< "show State:/Users/ConsoleUser" | /usr/bin/awk '/Name :/ && ! /loginwindow/ { print $3 }')"
sudo "/Applications/Docker.app/Contents/MacOS/install" --user "${currentUser}"

With some basic testing, this looked to have done the trick: Symlinks were configured, and a new LaunchDaemon was created. Most importantly, Docker Desktop 2.15.0 no longer prompted for admin rights on launch or under some basic tests!


A possible fix?

Last thing I tried was to edit the postinstall script my AutoPkg recipes created, removing the --install-privileged-components line, and swapped in the two lines mentioned above.

After running the recipes and installing the outputted packages on a few test devices, this looks to have done the trick.

Now those of you who actually read the snippets I quoted from the Docker Documentation will notice a possible small issue:

This approach has the limitation that Docker Desktop can only be run by one user account per machine, namely the one specified in the -–user flag.

For my needs, this isn’t an issue. However if you utilise Docker Desktop on multi-user devices, I’m afraid you may need to get more creative. The command looks to do a number of things, including the creation of a symlink from /var/run/docker.sock to /Users/<user>/.docker/run/docker.sock as well as a Launch Daemon to do the same thing, with the user home path explicitly specified.

I did try manually creating both the symlink and the LaunchDaemon, even (as far as I know) replicating the outputted items exactly, and Docker Desktop still asked for admin rights on launch and for some reason didn’t like my work.

Perhaps you can have some sort of root-level process running that watches for a user login, and re-runs the ./install --user command but it’s not something I’ve tested, nor have a need to.


Outro

In this post, I have taken some time to collect my thoughts and review my testing of a change with how Docker Desktop’s first-run elements works on macOS. I’m hoping to get back to blogging a bit more regularly now I’m settled in my new role, but it’ll all depend on motivation and time!

A special note to say that I will be speaking at 2023’s MacADUK conference, being held in May in the lovely Brighton, UK. No I’m afraid I won’t be resuming my Adobe sessions but something a bit different. Grab your tickets here! I’ll do my reasonable best to buy anyone a drink there who mentions they got to this point in this post. 😉

As always, if you have any questions, queries or comments, let me know below (or @daz_wallace in Mac Admins Slack) and I’ll try to respond to and delve into as many as I can.


Standard

2 thoughts on “Changes to Docker Desktop for Mac

  1. I have used the following…

    sudo “/Applications/Docker.app/Contents/MacOS/install” –accept-license –user ${loggedInUser}”

    This accepts the Docker Subscription Service Agreement during installation, rather than requiring it to be accepted by the user when the application is first run.

    It works with issues.

    Also, I have previously created an uninstaller which I should share with the community 😉 I will try when I have the bandwidth.

    Like

  2. Pingback: Deploying Docker Desktop 4.15+ with Munki - Kevin M. Cox

Comments are closed.