31

I want to have Docker for Mac start on boot, not on login. How do I do this? I'd like to create a LaunchDaemon, I just don't know what program to start.

All the examples I see seem to use docker-machine to define a VM, but the documentation now says that docker-machine is now not the way to go if you want to use the default VM created when Docker is installed, as Docker for Mac doesn't use docker-machine to create the VM.

The reason is that I want to start Docker to run Jenkins and Nexus containers on boot, as the server is going to be used as a CI server. The Docker GUI has the preference option of starting on login, which is not the same thing as on boot.

I am running OSX Sierra.

miken32
  • 42,008
  • 16
  • 111
  • 154
John
  • 10,837
  • 17
  • 78
  • 141
  • Hi, I'm facing exact same needs (to run Jenkins on boot without login) and same issues, have you figured out any way of doing it without creating docker machine? Thanks! – ZhouX Jun 14 '18 at 02:57

2 Answers2

33

TL;DR Running Docker for Mac as a standalone service is not supported.

Instead run Docker in a VirtualBox VM, either by creating a plain VM or using docker-machine. Then set the Virtualbox VM up to run at boot.

This is the LaunchAgent I use for Virtualbox:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>KeepAlive</key>
    <true/>
    <key>Label</key>
    <string>vm.dockervm</string>
    <key>ProgramArguments</key>
    <array>
      <string>/usr/local/bin/VBoxHeadless</string>
      <string>-s</string>
      <string>dockervm_default_1667177741</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>UserName</key>
    <string>me</string>
    <key>WorkingDirectory</key>
    <string>/Users/me</string>
    <key>StandardErrorPath</key>
    <string>/Users/me/log/vm/dockervm.log</string>
    <key>StandardOutPath</key>
    <string>/Users/me/log/vm/dockervm.log</string>
  </dict>
</plist>

Loaded with:

launchctl load /Users/matt/Library/LaunchAgents/vm.dockervm.plist

The attempted Docker for Mac setup...

The Docker for Mac application creates a launchd service:

○→ launchctl list | grep -i docker
-   0   com.docker.helper
78105   0   com.docker.docker.52512

The service has the following details:

○→ launchctl list com.docker.docker.52512
{
    "LimitLoadToSessionType" = "Aqua";
    "Label" = "com.docker.docker.52512";
    "TimeOut" = 30;
    "OnDemand" = true;
    "LastExitStatus" = 0;
    "PID" = 78105;
    "Program" = "/Applications/Docker.app/Contents/MacOS/Docker";
    "ProgramArguments" = (
        "/Applications/Docker.app/Contents/MacOS/Docker";
    );
    "PerJobMachServices" = {
        "com.apple.tsm.portname" = mach-port-object;
        "com.apple.CFPasteboardClient" = mach-port-object;
        "com.apple.coredrag" = mach-port-object;
        "com.apple.axserver" = mach-port-object;
    };
};

And has the following process tree:

○→ pstree -p 78105
-+= 00001 root /sbin/launchd
 \-+= 78105 matt /Applications/Docker.app/Contents/MacOS/Docker
   \-+= 78118 matt /Applications/Docker.app/Contents/MacOS/com.docker.osx.hyperkit.linux -watchdog fd:0 -max-restarts 5 -restart-seconds 30
     |--- 78119 matt /Applications/Docker.app/Contents/MacOS/com.docker.osx.hyperkit.linux -watchdog fd:0 -max-restarts 5 -restart-seconds 30
     |--= 78120 matt com.docker.db --url fd://3 --git /Users/matt/Library/Containers/com.docker.docker/Data/database
     |--= 78121 matt com.docker.osxfs --address fd:3 --connect /Users/matt/Library/Containers/com.docker.docker/Data/@connect --control fd:4 --volume-control
     |--= 78122 matt com.docker.slirp --db /Users/matt/Library/Containers/com.docker.docker/Data/s40 --ethernet fd:3 --port fd:4 --introspection fd:5 --diagn
     |-+= 78123 matt com.docker.osx.hyperkit.linux
     | \--- 78125 matt /Applications/Docker.app/Contents/MacOS/com.docker.osx.hyperkit.linux
     \-+= 78124 matt com.docker.driver.amd64-linux -db /Users/matt/Library/Containers/com.docker.docker/Data/s40 -osxfs-volume /Users/matt/Library/Containers
       |--- 78126 matt /Applications/Docker.app/Contents/MacOS/com.docker.driver.amd64-linux -db /Users/matt/Library/Containers/com.docker.docker/Data/s40 -o
       \--- 78130 matt /Applications/Docker.app/Contents/MacOS/com.docker.hyperkit -A -m 2048M -c 3 -u -s 0:0,hostbridge -s 31,lpc -s 2:0,virtio-vpnkit,uuid=

The first problem is /Applications/Docker.app/Contents/MacOS/Docker is the GUI app that sits in your tray rather than the VM, so that's going to be hard to run at boot time. The first descendant /Applications/Docker.app/Contents/MacOS/com.docker.osx.hyperkit.linux looks more like something that manages the VM so we'll start there.

Get the full command of the hyperkit process

○→ ps -fp 78105
  UID   PID  PPID   C STIME   TTY           TIME CMD
  501 78105 82644   0  2:08am ??         0:00.03 /Applications/Docker.app/Contents/MacOS/com.docker.osx.hyperkit.linux -watchdog fd:0 -max-restarts 5 -restart-seconds 30

Get the working directory of the process

○→ sudo lsof -p 78105 | grep cwd
com.docke 78105 matt  cwd      DIR                1,4       748 63186601 /Users/matt/Library/Containers/com.docker.docker/Data

Create a launchd plist file /Library/LaunchDaemons/com.you.docker.plist containing the details

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
    <string>com.you.docker</string>
  <key>ProgramArguments</key>
    <array>
      <string>/Applications/Docker.app/Contents/MacOS/com.docker.osx.hyperkit.linux</string>
      <string>-watchdog</string>
      <string>fd:0</string>
      <string>-max-restarts</string>
      <string>5</string>
      <string>-restart-seconds</string>
      <string>30</string>
    </array>
  <key>UserName</key>
    <string>youruser</string>
  <key>WorkingDirectory</key>
    <string>/Users/youruser/Library/Containers/com.docker.docker/Data</string>
  <key>RunAtLoad</key>
    <true/>
</dict>
</plist>

Which you can load with

sudo launchctl load -w /Library/LaunchDaemons/com.you.docker.plist

Then... nothing. Check the logs

○→ tail /var/log/system.log
Mar  7 02:23:26 mac Docker[87728]: Acquired task manager lock
Mar  7 02:23:26 mac Docker[87728]: Maximum number of file descriptors is 10240
Mar  7 02:23:26 mac Docker[87728]: Failed to read watchdog handshake
Mar  7 02:23:26 mac com.apple.xpc.launchd[1] (com.you.docker[87728]): Service exited with abnormal code: 1

You'll notice the command we are running specifies an option -watchdog fd:0 which will be the stdin of the hyperkit process so there is probably something missing.

If I run Docker normally again and look at what FD 0 is for the hyperkit process when it's working

○→ sudo lsof -p 88360
COMMAND     PID USER   FD     TYPE             DEVICE  SIZE/OFF     NODE NAME
com.docke 88360 matt    0     PIPE 0xff80ce577ca2ed91     16384          ->0xff80ce5776aa8d51

Then looking at PIPE 0xff80ce577ca2ed91 across the system you'll see the main Docker process has the pipe open for many processes.

○→ sudo lsof | grep 0xff80ce577ca2ed91
COMMAND     PID             USER   FD      TYPE             DEVICE    SIZE/OFF     NODE NAME
Docker    88349             matt   13      PIPE 0xff80ce5776aa8d51       16384          ->0xff80ce577ca2ed91
com.docke 88360             matt    0      PIPE 0xff80ce577ca2ed91       16384          ->0xff80ce5776aa8d51
com.docke 88362             matt    0      PIPE 0xff80ce577ca2ed91       16384          ->0xff80ce5776aa8d51
com.docke 88363             matt    0      PIPE 0xff80ce577ca2ed91       16384          ->0xff80ce5776aa8d51
com.docke 88364             matt    0      PIPE 0xff80ce577ca2ed91       16384          ->0xff80ce5776aa8d51
com.docke 88365             matt    0      PIPE 0xff80ce577ca2ed91       16384          ->0xff80ce5776aa8d51
com.docke 88366             matt    0      PIPE 0xff80ce577ca2ed91       16384          ->0xff80ce5776aa8d51

Trying to load the service again without the -watchdog fd:0 options results in the same error.

So it looks like the main Docker app does some setup that is required to run the VM. I haven't been able to find the source code for whatever deals with the watchdog option so not sure what it expects.

Maybe raise an issue or feature request on https://github.com/docker/for-mac to get the details of running the VM standalone from the App.

Matt
  • 68,711
  • 7
  • 155
  • 158
  • 3
    Wow, this is why I love SO. Thanks for a great answer, you're absolutely right, `docker-machine` is the way to go. – John Mar 07 '17 at 21:26
  • 2
    @John can you unmark this as the answer? I attempted this yesterday, got to the end of the tutorial to find it inconclusive. Or, Matt can you update the answer to make it more clear that it is not possible? – Isaac Nov 21 '18 at 19:37
  • The daemon module is managed in a separate project. I created an issue here: https://github.com/moby/moby/issues/40239 Please vote. – Blago Nov 24 '19 at 07:31
  • 1
    @Isaac I've added some bold to the first paragraph – Matt Dec 04 '19 at 00:53
  • 1
    Doing it with a virtualbox VM does the performance suffer any compared with using docker desktop? I think that too uses a virtual machine but I guess what I'm wondering is if the two virtual machines (Docker desktop's and VirtualBox running docker) have equivalent performance. – fivestones Jun 12 '23 at 18:27
  • @fivestones I haven't noticed any issues, but never done a direct comparison. One benefit is virtualbox uses a lot less host CPU to run the VM. – Matt Jun 19 '23 at 11:11
1

Just Start the Docker Desktop application, if you've installed docker previously. the docker daemon works post that. Tried this after an hour of research and looking up at different platforms. Worked for me.

  • You can set the app to auto launch on login, but how do you you set the account to auto login on boot? – Denis Howe Feb 10 '23 at 11:12
  • 1
    @DenisHowe You can configure auto login on boot here: `System Preferences > Users & Groups > Automatically log in as: ` – Nick Sweeting Apr 08 '23 at 20:54
  • For me, with the desktop version: Launch Docker as as app (I use spotlight) then click on its menu in the status bar, select Preferences, then enable "Start Docker Desktop when you log in" – Michael Behrens Apr 13 '23 at 14:12