"sudo systemctl enable docker" not available: Automatically run Docker at boot on WSL2 (using a "sysvinit" / "init" command or a workaround)

Viewed 21542

I am using Ubuntu on WSL2 (not on Docker Desktop).

According to How to fix docker ‘Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?’ on Ubuntu, I can automatically start the docker daemon at boot using

sudo systemctl enable docker

instead of just starting it again at every boot with

sudo systemctl start docker

with both commands avoiding "Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?".

When using any of the two, I get

Synchronizing state of docker.service with SysV service script with /lib/systemd/systemd-sysv-install. Executing: /lib/systemd/systemd-sysv-install enable docker

and a test run shows, that docker is not yet running:

docker run hello-world 

docker: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?. See 'docker run --help'.

Some steps before, I also got a different message at this point:

System has not been booted with systemd as init system (PID 1). Can't operate.Failed to connect to bus: Host is down"

which brought me to Fixing "System has not been booted with systemd as init system" Error:

Reason: Your Linux system is not using systemd How to know which init system you are using? You may use this command to know the process name associated with PID 1 (the first process that runs on your system):

ps -p 1 -o comm=

It should show systemd or sysv (or something like that) in the output.

ps -p 1 -o comm= gave me init.

According to this and this table

enter image description here

Systemd command
    Sysvinit command

systemctl start service_name
    service service_name start

systemctl stop service_name
    service service_name stop

systemctl restart service_name
    service service_name restart

systemctl status service_name
    service service_name status

systemctl enable service_name
    chkconfig service_name on

systemctl disable service_name
    chkconfig service_name off

I can choose service docker start to run docker, which works. But I cannot find something like "systemd"'s sudo systemctl enable docker for "sysvinit". I would expect it to be like:

sudo service docker enable

But that "enable" is not available for "sysvinit" / "init".

While sudo service docker start works like sudo systemctl start docker, there is no such command that uses "enable". At the moment, I need to run sudo service docker start whenever I start WSL2.

The question:

What is the command that reaches sudo systemctl enable docker using sudo service docker ..., or if that does not exist, what is a workaround here to automatically start docker when opening Ubuntu on WSL2?

2 Answers

Short answer to "what is a workaround here to automatically start docker when opening Ubuntu on WSL2?

  • Option 1: On Windows 11, add the necessary commands to the [boot] section in /etc/wsl.conf:

    [boot]
    command="service docker start"
    

    Note that under the latest Preview releases, there appears to be an issue that causes anything started via this boot.command to terminate when no services that were started via an actual command-line are still running. In other words, if you need Docker (or any other service) to continue to run after you exit your WSL2 session, you'll probably need to use Option 2 (or uninstall the Preview).

  • Option 2: On Windows 10, run the necessary commands in your user startup scripts (e.g. .profile). Do it with a check to see if the service is running first, like:

    wsl.exe -u root -e sh -c "service docker status || service docker start"
    

    This is a better alternative than my previous answer (option 3, below) since it doesn't require modification to sudoers. This takes advantage of the fact that the wsl.exe command can be run from inside WSL, using the -u root option to run the commands as root without a password.

    Note: If for some reason this command fails, your default WSL distribution may be different than you expect. Check the output of wsl.exe -l -v. You can change the default distro using wsl.exe --setdefault <distro_name> or adjust the commandline above to specify the distro with -d <distro_name>.

  • Option 3: (old answer, here for posterity): visudo or add rules to /etc/sudoers.d to allow your user to run the commands without a password:

    username ALL = (root) NOPASSWD: /usr/sbin/service docker *
    

    Then edit your .profile to add:

    sudo service docker status || sudo service docker start
    

More Details:

As you've discovered, WSL does not include any systemd support, nor really any direct support for starting a service on boot.

For starters, the WSL subsystem doesn't launch at Windows boot, but only when the user launches a login session anyway. So without any real "system start", the init.d or systemd startup doesn't make as much sense.

Further, users may have multiple WSL instances/distributions running, and if you are doing that (as I am), then you really don't want all services from all instances running on every boot (although, updated answer, Windows 11 does now give us this option).

For Docker, though, are you running Docker Desktop with WSL2 integration, or just installed directly into a WSL2 instance? For Docker Desktop, I ran across this in another question yesterday on how to start Docker Desktop daemon at Windows boot.

You can also have the WSL2 instance start via Windows Task Manager when the user logs in, and run the script via something like wsl -u root service docker start in the Task Manager.

Note that the same doesn't seem to work at Windows boot, however, (only login) because Windows seems to terminate any WSL instance that isn't tied to an active user after a few seconds (even if a service is running in the background). You can work around this with the PowerShell Invoke-WmiMethod, something like ...

powershell.exe Invoke-WmiMethod -Class Win32_Process -Name Create -ArgumentList 'wsl', although I haven't tested this all that thoroughly.

This worked for WSL ubuntu.

Before service --status-all [ - ] ssh

service ssh start

service --status-all [ + ] ssh

Related