Skip to content

Instantly share code, notes, and snippets.

@strarsis
Last active September 4, 2023 07:29
Show Gist options
  • Star 36 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save strarsis/44ded0d254066d9cb125ebbb04650d6c to your computer and use it in GitHub Desktop.
Save strarsis/44ded0d254066d9cb125ebbb04650d6c to your computer and use it in GitHub Desktop.
Notes about Docker on WSL (Windows 10 Home / Docker Toolbox) (Virtualbox instead Hyper-V)

Edit (September 2020):

Therefore you may want to skip this guide and rather install WSL 2 and use Docker for Desktop with it!


Old instructions

for using Docker with WSL (without Hypervisor and Hyper-V VM instead): Docker on WSL (Windows 10 Home / Docker Toolbox) (Virtualbox instead Hyper-V)

Docker on WSL communicates with Docker on Windows from Docker Toolbox.

Install VirtualBox and Docker Toolbox on Windows.

Docker on Windows uses VM for Linux based docker containers. Create new docker machine (VM):

> docker-machine.exe create default

Start the default docker machine:

> docker-machine.exe start default

Find out (Docker daemon) IP of default docker-machine and use that IP for Docker client:

> docker-machine.exe ip

In case of error:

open C:\Users\<user>\.docker\machine\machines\default\config.json: The system cannot find the file specified.

Remove folder in C:\Users<user>.docker\machine\machines manually.

Then try again:

> docker-machine.exe rm default
[y]
> docker-machine.exe create default

After setting up environment variables for Docker client:

> docker info

In case of error:

could not read CA certificate "/home/build/.docker/ca.pem": open /home/build/.docker/ca.pem: no such file or directory

Remove folder in C:\Users<user>.docker\machine\machines manually.

Then try again:

> docker-machine.exe rm default
[y]
> docker-machine.exe create default

Extra fix if necessary:

> docker-machine.exe regenerate-certs default
[y]

Note: In Windows, docker client has to run as admin, otherwise this error will occur:

open //./pipe/docker_engine: The system cannot find the file specified. In the default daemon configuration on Windows

If already running as admin, try this fix

> docker-machine env

Copy + paste/run the printed for loop (without commenting out REM) for configuring.

Important: The @FOR loop without the REM!

C:\Users\<user>>docker-machine env
SET DOCKER_TLS_VERIFY=1
SET DOCKER_HOST=tcp://192.168.99.100:2376
SET DOCKER_CERT_PATH=C:\Users\<user>\.docker\machine\machines\default
SET DOCKER_MACHINE_NAME=default
SET COMPOSE_CONVERT_WINDOWS_PATHS=true
REM Run this command to configure your shell:
REM     @FOR /f "tokens=*" %i IN ('docker-machine env') DO @%i

From that output, copy + paste and execute the whole thing in cmd. Then copy the @FOR line without REM and also paste and execute in cmd:

> @FOR /f "tokens=*" %i IN ('docker-machine env') DO @%i
> docker-machine ls
> docker-machine start default

Network/other issues with virtual machine Open VirtualBox GUI and stop + remove the default machine manually, then try again. Extra tip: Update VirtualBox + VirtualBox Extensions to latest version.

Test:

> docker run hello-world

This should download + run the hello-world docker container.

On WSL, install Docker CE(for Ubuntu (=WSL basically)).

docker info will now show an error (can't connect to daemon).

Edit: docker-env wrapper script that translates Windows style ENV to *nix (WSL) style export: https://gist.github.com/mmarchini/bc9df7b82127fea13612edf8bffdf96f

$ mkdir -p ~/.bin/
$ cd ~/.bin/
$ wget -O docker-env https://gist.githubusercontent.com/mmarchini/bc9df7b82127fea13612edf8bffdf96f/raw/33f14362f98fa168c17ad6b04a053c2066e071f0/docker-env
$ chmod +x ./docker-env

Test the script:

$ ./docker-env

.bashrc on WSL:

# Docker (Docker Toolbox on Windows)
source <(~/.bin/docker-env)
alias docker-machine="docker-machine.exe"
#alias docker="docker.exe" # Native docker client is used instead, less issues with environment variables
docker-machine.exe start default && # autostart docker-machine
# docker-compose path compatibility
export COMPOSE_CONVERT_WINDOWS_PATHS=1

Tip: Load the new bash script in existing terminal using source ~/.bashrc to avoid restarting the terminal.

Share certs from Docker Toolbox on Windows with Docker client on WSL:

$ mkdir -p ~/.docker
$ ln -s /mnt/c/Users/<user>/.docker/machine/certs/ca.pem ~/.docker/ca.pem
$ ln -s /mnt/c/Users/<user>/.docker/machine/certs/ca-key.pem ~/.docker/ca-key.pem
$ ln -s /mnt/c/Users/<user>/.docker/machine/certs/cert.pem ~/.docker/cert.pem
$ ln -s /mnt/c/Users/<user>/.docker/machine/certs/key.pem ~/.docker/key.pem

Note: All of these files have to be made available/symlinked!

Install docker-compose(for Linux) natively on WSL.

* There is also docker-compose shipped with Docker Toolbox (alias docker-compose to docker-compose.exe) – but it may be older and not the same style as the natively installed Docker client.

Paths in docker-compose in Bash on Windows/WSL:

ERROR: for <container>  Cannot start service php: oci runtime error: container_linux.go:262: starting container process caused "chdir to cwd (\"<target container path>\") set in config.json failed: no such file or directory"

See microsoft/WSL#1854

Proposed solutions:

.env file with this content:

COMPOSE_CONVERT_WINDOWS_PATHS=1

export as environment variable:

export COMPOSE_CONVERT_WINDOWS_PATHS=1

or in .bashrc:

COMPOSE_CONVERT_WINDOWS_PATHS=1

But this doesn't resolve the issue for me... Edit: Apparently it works now, I installed the latest Windows 10 updates (and got a newer WSL version).

@strarsis
Copy link
Author

I found a different approach (from different user) that looks simpler, maybe you want to take a look:
https://gist.github.com/jwilson8767/00a46f5ca63327d5bfd802f87b702c8d

@strarsis
Copy link
Author

strarsis commented Jan 16, 2018

For strange errors concerning seeing a folder instead a file, the reason is that the docker-machine is in a VM that can only see the folders that have been mounted into it), see https://github.com/boot2docker/boot2docker/blob/master/README.md#virtualbox-guest-additions.

Example from excerpt in that README:

mount -t vboxsf -o uid=1000,gid=50 disk-d /mnt/d/

Where to add these commands to run on docker-machine startup, see https://github.com/boot2docker/boot2docker/blob/master/doc/FAQ.md#local-customisation-with-persistent-partition
https://github.com/boot2docker/boot2docker/blob/8c3082d16a1491e85c794e5e4a1fa37db3f1fc83/rootfs/rootfs/opt/bootscript.sh#L78
Related: boot2docker/boot2docker#1269
Alternative: https://docs.docker.com/machine/reference/mount/

The config files will not survive recreation of docker-machine, see boot2docker/boot2docker#1269 (comment).

You have to create the shared folder first in VirtualBox GUI, giving it a name .
This name is passed to the mount command inside the docker-machine (SSH) including the target mount directory path.

# SSH into docker-machine for configuration of docker VM
$ docker-machine.exe ssh

# Ensure the mount point folder exists
> sudo mkdir -p /mnt/d/whatever1/whatever2

# Mount into mount point folder
> sudo mount -t vboxsf -o uid=1000,gid=50 <shared folder name> /mnt/d/whatever1/whatever2

Addendum: Apparently the kitematik GUI can be used for viewing all these containers and also mapping folders.
Edit: It doesn't work outside the home user folder (see docker/kitematic#2738).

Related:
https://forums.virtualbox.org/viewtopic.php?f=1&t=15497#p76667
https://forums.virtualbox.org/viewtopic.php?f=3&t=15868

This is a problem with mount if the share is named the same as a folder where you are standing then you get that error.
Rename the share to something different.

Note:
For mysqld/mariadb daemon over VirtualBox (and also partly Docker) some extra options are required,
example docker-compose for the mariadb official image:

  db:
    image: mariadb:10.1
    command: --innodb-flush-method=O_DSYNC --innodb-use-native-aio=OFF --log_bin=ON

The docker containers can be reached on the docker-machine VM (not on the host (where the WSL runs on)),
you can find out its IP using $ docker-machine.exe ip.

Speeding up the shared virtual box folders:
Simple and helpful?: https://forums.virtualbox.org/viewtopic.php?f=7&t=4078&start=30

Running docker-machine VM with more CPU cores (4 in this example, there is also CLI command to get max physical cores available)
and more memory (2048M instead 1024M in this example):

docker-machine.exe create default --virtualbox-cpu-count "4" --virtualbox-memory "2048" 

Alternatively you can just configure the existing default VM in VirtualBox GUI or headless VirtualBox manager over CLI.

@strarsis
Copy link
Author

strarsis commented May 5, 2018

mariadb image has been updated now to use the command line arguments also during database initialization,
see MariaDB/mariadb-docker#38 (comment).

@thaneofcawddor
Copy link

Super new to Docker. I got to the end of your instructions and ran docker run hello-world and it worked. Then, when I restarted my terminal, the same "Cannot connect to the Docker daemon..." error happened. I think I lost you at "Note: All of these files have to be made available/symlinked!" Where did I go astray?

@strarsis
Copy link
Author

@thaneofcawddor: You have to persist the exports in ~/.bashrc so they are always executed at bash startup.

@RichardBronosky
Copy link

RichardBronosky commented Jul 24, 2018

If you are trying to do this in WSL bash, then that export that has C:\... is not going to work. You can convert it to bash like so:

eval $(docker-machine.exe env default --shell bash | sed 's?\\?/?g;s?C:/?/mnt/c/?g')

That uses sed to convert \\ (aka \ in windows) to / and C:/ (because the \ got converted) to /mnt/c/.

Cheers!

Update: I just noticed that I didn't read down to your bit about docker-env. I would still rather put this in my .bashrc

source <(docker-machine.exe env default --shell bash | sed 's?\\?/?g;s?C:/?/mnt/c/?g')

@strarsis
Copy link
Author

strarsis commented Oct 12, 2018

For recent Docker on Windows (but using Hyper-V!), these instructions helped me:
https://davidburela.wordpress.com/2018/06/27/running-docker-on-wsl-windows-subsystem-for-linux/

@strarsis
Copy link
Author

Now I switched to WSL 2 (shell and Docker for Desktop) and I don't need a Hyper-V VM anymore!
Everything still works great.

@strarsis
Copy link
Author

Edit (June 2020):

Therefore you may want to skip this guide and rather install WSL 2 and use Docker for Desktop with it!
Btw., WSL 2 will also support GPU (CUDA and such), too!!

@Dogyunjeong
Copy link

Hi, I am new to wsl2.
I like it a lot. But I am looking for docker-machine provisioning.
Can I just follow your instruction?

@strarsis
Copy link
Author

strarsis commented Jun 23, 2020

@Dogyunjeong: So I downloaded + installed Docker for Desktop Edge (should also run on Windows 10 Home now), then enabled WSL 2 support in the Docker for Desktop settings for the distribution(s) I have installed in WSL 2 (Ubuntu 20.x in my case), no need to install anything in the WSL 2 distribution by the way. docker and docker-compose are ready after enabling the support.

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