如何为Linux设置Docker和Windows子系统:爱情故事。 ?

Do you sometimes feel you’re a beautiful princess turned by an evil wizard into a frog? Like you don’t belong? I do. I’m a UNIX guy scared to leave the cozy command line. My terminal is my castle. But there are times when I’m forced to use Microsoft Windows and I have learned a few tricks on how to cope with that.

有时您会觉得自己是一位美丽的公主,被邪恶的巫师变成了青蛙吗? 像你不属于? 我做。 我是一个UNIX人,不敢离开舒适的命令行。 我的终点站是我的城堡。 但是有些时候我不得不使用Microsoft Windows,并且我已经学会了一些技巧来应对这种情况。

For my daily terminal needs, I have installed Windows Subsystem for Linux along with the Ubuntu distribution. On top of that, I have a Linuxbrew installation which helps me manage any third-party apps I may need. This combination works surprisingly well! I have a nifty symbolic link to access all my “external” (that is Windows-hosted) data: ln -s ~/external /mnt/c/Users/DoomHammer and most of the needs are fulfilled this way. That is, unless I need to use Docker.

为了满足日常的终端需求,我已经安装了Windows Subsystem for Linux和Ubuntu发行版。 最重要的是,我安装了Linuxbrew,可以帮助我管理可能需要的任何第三方应用程序。 这种组合效果很好! 我有一个漂亮的符号链接来访问我的所有“外部”(Windows托管)数据: ln -s ~/external /mnt/c/Users/DoomHammer ,大多数需求都通过这种方式得到满足。 也就是说,除非我需要使用Docker。

Docker有何特别之处? (What’s so Special About Docker?)

Unlike most applications I typically use every day, Docker is a system application. This means its rooted deep into the system and requires an actual daemon to run on the host machine. And by the host machine, I mean native Microsoft Windows in that case.

与我通常每天使用的大多数应用程序不同,Docker是一个系统应用程序。 这意味着它已深入系统,并需要一个实际的守护程序才能在主机上运行。 在这种情况下,主机是指本机Microsoft Windows。

Does it mean you can’t use Docker from inside WSL? Not necessarily. But you need to flex your muscles a bit more to get there. First of all, you need to install Docker for Windows. There’s Docker Enterprise Editions for Windows Server 2016 (and up) and there’s Community Edition for Windows 10 Professional or Enterprise. And I was stuck at Windows 10 Home Edition.

这是否意味着您不能从WSL内部使用Docker? 不必要。 但是您需要多弯曲一些肌肉才能到达那里。 首先,您需要安装Docker for Windows。 有适用于Windows Server 2016(及更高版本)的Docker企业版以及适用于Windows 10专业版或企业版的社区版。 我被困在Windows 10家庭版上。

在Windows 10 Home上获取Docker (Getting Docker on Windows 10 Home)

It seems getting Docker to run on Windows 10 Home Edition is a bit more tricky. Docker Community Edition requires Hyper-V support which is unavailable on Home Edition. This means I needed to dig out Docker Toolbox, an older distribution which relied on Docker Machine and Virtualbox. But after installation, Virtualbox greeted me with a prompt saying it’s impossible to run virtualization.

让Docker在Windows 10家庭版上运行似乎有些棘手。 Docker Community Edition需要Hyper-V支持,而Home Edition则不提供。 这意味着我需要挖掘Docker Toolbox ,这是一个较早的发行版,依赖于Docker Machine和Virtualbox。 但是在安装后,Virtualbox提示我说不可能运行虚拟化。

As it turned out, I had the virtualization setting turned off in BIOS. Apparently for security reasons. I turned it on, opened Virtualbox again and… the same. This made me worried a bit. After a bit of Web crawling, I found the advice to check systeminfo. Well, it clearly showed *some* hypervisor is running. But not Virtualbox and most certainly not Hyper-V, right?

事实证明,我在BIOS中关闭了虚拟化设置。 显然是出于安全原因。 我将其打开,再次打开Virtualbox,然后…相同。 这让我有点担心。 经过一些Web爬网之后,我发现了检查systeminfo的建议。 好吧,它清楚地表明*某些*虚拟机监控程序正在运行。 但是不是Virtualbox,当然也不是Hyper-V,对吗?

To my surprise, it was Hyper-V all along. It seems Home Edition lacks the userland tools to actually use Hyper-V but it doesn’t mean that the Hypervisor itself wasn’t running. Thankfully, turning it off was just a bcdedit /set hypervisorlaunchtype off away. After I rebooted the machine Virtualbox was eager to work. Cool, score for me!

令我惊讶的是,一直以来都是Hyper-V。 看来Home Edition缺少实际使用 Hyper-V的用户界面工具,但这并不意味着Hypervisor本身并未运行。 值得庆幸的是,关闭它只是关闭了bcdedit /set hypervisorlaunchtype off 。 重新启动计算机后,Virtualbox渴望工作。 太酷了,为我得分!

Docker和WSL,永远最好的朋友? (Docker and WSL, Best Friends Forever?)

Having a working Virtualbox I opened Docker Quickstart Terminal. On the first run, it creates a Docker Machine (that’s why it needs Virtualbox) to act as a host for all the containers. I typed docker run --rm hello-world and watched the progress bar as Docker downloaded the appropriate image for me. Another score!

在具有可用的Virtualbox的情况下,我打开了Docker Quickstart Terminal。 在第一次运行时,它会创建一个Docker Machine(这就是为什么需要Virtualbox)充当所有容器的主机的原因。 我输入了docker run --rm hello-world并看着进度条,因为Docker为我下载了适当的映像。 另一个分数!

Now, instead of the cmd.exe I’d like to use Docker from the comfort of my WSL. How do I do that? Fortunately, WSL has access to native Windows binaries. This means I can run docker-machine.exe ls to see the machine created by Docker Toolbox. It should be right there named simply default. If the state is anything else than “Running” you can start it with docker-machine.exe start. Each time you want to run Docher Machine remember that unlike in cmd.exe the extension (.exe) is mandatory.

现在,我想从WSL的舒适性出发而不是cmd.exe 。 我怎么做? 幸运的是,WSL可以访问本机Windows二进制文件。 这意味着我可以运行docker-machine.exe ls来查看由Docker Toolbox创建的机器。 它应该在那里命名为简单的default 。 如果状态不是“正在运行”,则可以使用docker-machine.exe start来启动它。 每次要运行Docher Machine时,请记住,与cmd.exe不同,扩展名( .exe )是强制性的。

Normally we would call docker-machine.exe env to set the environment variables.

通常我们会调用docker-machine.exe env来设置环境变量。

Unfortunately it outputs the variables in a format understood by cmd.exe, not by any Bourne-compatible shell like bash or zsh. But we can change this behavior with docker-machine.exe env --shell sh.

不幸的是,它以cmd.exe理解的格式输出变量,而不是像Bash或zsh这样的任何与Bourne兼容的shell都可以理解。 但是我们可以使用docker-machine.exe env --shell sh更改此行为。

Hmm, almost there. But there’s one thing left hanging. The certificate path is written as a Windows path. How to translate into something WSL understands? For some time now, WSL features a nice utility called wslpath. Thanks to this tool we can call export DOCKER_CERT_PATH=$(wslpath $DOCKER_CERT_PATH) and we're almost ready.

嗯,快到了。 但是还有一件事悬而未决。 证书路径被写为Windows路径。 如何将WSL理解为某种东西? 一段时间以来 ,WSL都有一个不错的实用程序wslpath 。 由于这个工具,我们可以称之为export DOCKER_CERT_PATH=$(wslpath $DOCKER_CERT_PATH)和我们差不多准备好了。

We still need the userland tools. So, using your favorite package manager install both the Docker Engine and Docker Compose. For me this means brew install docker docker-compose. After that a docker run --rm hello-world should yield exactly the same results as it did in a Docker Toolbox terminal. Congratulations!

我们仍然需要userland工具。 因此,使用您喜欢的软件包管理器安装Docker Engine和Docker Compose。 对我来说,这意味着brew install docker docker-compose 。 之后, docker run --rm hello-world应该会产生与Docker Toolbox终端完全相同的结果。 恭喜你!

这就是全部? (Is That All?)

No, of course not. You may quickly notice that bind-mount does not work correctly. That’s because the Docker daemon expects proper Windows paths, and WSL paths sadly cannot be translated automatically. But there are a few hacks we can use to improve the situation.

不,当然不是。 您可能会很快注意到,bind-mount无法正常工作。 这是因为Docker守护程序需要正确的Windows路径,而不幸的是WSL路径无法自动转换。 但是,我们可以使用一些技巧来改善这种情况。

Now, which hack you need depends of the version you are running. Hitting Win+R and typing winver you should see a dialog that says something around the lines:

现在,您需要哪种黑客取决于您所运行的版本。 击中Win + R并键入winver您应该会看到一个对话框,内容如下:

Microsoft Windows

微软Windows

If it’s actually 18.03 or newer you can edit /etc/wsl.conf to look like this:

如果实际是18.03或更高版本,则可以编辑/etc/wsl.conf ,如下所示:

[automount]
root = /
options = "metadata"

It means WSL would mount the C: drive under /c/ instead of the usual /mnt/c. Why is this important? Well, it’s important because that’s what Docker daemon expects of Windows paths. By the way: after you save the file, you need to re-login for the changes to take effect.

这意味着WSL将C:驱动器安装在/c/而不是通常的/mnt/c 。 为什么这很重要? 好吧,这很重要,因为这就是Docker守护进程对Windows路径的期望。 顺便说一句:保存文件后,您需要重新登录以使更改生效。

Warning! If you happen to use wsl-terminal this change will break it. Use the next method in such a case.

警告 ! 如果您碰巧使用wsl-terminal,则此更改将使其无效 。 在这种情况下,请使用下一个方法。

Another approach if you don’t want to re-login or if you’re stuck with an older version is to bind mount one mountpoint to the other like this:

如果您不想重新登录或使用旧版本,另一种方法是将一个安装点绑定到另一个安装点,如下所示:

sudo mkdir /c
sudo mount --bind /mnt/c /c

Quicker, but only available as long as you are logged in. You’ll have to repeat this the next time you reboot your machine or add it to your shell runtime configuration (like ~/.bashrc or ~/.zshrc). That’s because /etc/fstab does not work as expected on WSL.

更快,但仅在您登录后才可用。下次重新启动计算机或将其添加到Shell运行时配置(如~/.bashrc~/.zshrc )时,必须重复此操作。 这是因为/etc/fstab在WSL上无法按预期工作。

As you may have noticed, this means you are now able to run Docker with mounts, but only if your volumes are within the Windows filesystem. Since command line docker expects absolute paths this should be no big deal, but with Docker Compose you have to be extra careful. It allows to use relative paths and this way everything that starts with ./ won’t work.

您可能已经注意到,这意味着您现在可以使用挂载运行Docker,但前提是您的卷位于Windows文件系统中。 由于命令行docker期望绝对路径,这应该没什么大不了的,但是使用Docker Compose时,您必须格外小心。 它允许使用相对路径,这样以./开头的所有内容将不起作用。

If you absolutely insist on mounting WSL’s filesystem with Docker you can try replacing all those ./ with /c/Users/$USERNAME/AppData/Local/lxss along with the project’s $PWD. In this case $USERNAME does not mean your WSL username, but you Windows one.

如果你绝对坚持安装WSL与泊坞文件系统,你可以尝试更换所有.//c/Users/$USERNAME/AppData/Local/lxss与项目一起$PWD 。 在这种情况下, $USERNAME并不表示您的WSL用户名,而是Windows。

I thought it’d be clever to write a wrapper around Docker Compose to make it change the working directory into this lxss but unfortunately WSL has no rights to access it. And rightfully so, I think!

我认为为Docker Compose编写包装程序以使其将工作目录更改为此lxss但不幸的是WSL无权访问它。 我认为是正确的!

最后一堵墙 (One Last Wall)

We can run Docker and we can bind data directories. What else can we want? Maybe working port-forwarding? Unlike with Native solutions, using Docker through Docker Machine requires to call every service on $(docker-machine ip):$PORT instead of the usual localhost:$PORT. There is a way around it, albeit not a very elegant one:

我们可以运行Docker,并且可以绑定数据目录。 我们还想要什么? 也许正在进行港口转运? 与本机解决方案不同,通过Docker Machine使用Docker需要在$(docker-machine ip):$PORT而不是通常的localhost:$PORT上调用每个服务。 尽管不是很优雅,但是有一种解决方法:

#!/bin/sh

# This script uses Virtualbox Port Forwarding to make all Docker services
# available on Windows host under `localhost`

VBXMGMT=/c/Program\ Files/Oracle/VirtualBox/VBoxManage.exe

# List all the running container ids
docker ps -q | while read -r i; do
  # List all the ports bound by this container
  for port in $(docker port "$i" | cut -d'-' -f1); do
    port_num=$(echo "${port}" | cut -d'/' -f1)
    port_type=$(echo "${port}" | cut -d'/' -f2)
    echo "Create rule natpf1 for ${port_type} port ${port_num}"
    "$VBXMGMT" controlvm "default" natpf1 "${port_type}-port${port_num},${port_type},,${port_num},,${port_num}"
  done
done

I believe you can write a wrapper around Docker to perform this dance each time you run a new container. I admit I haven’t tested it that way, as most of the time I’m satisfied with forwarding a single port.

我相信您可以在运行新容器时围绕Docker编写包装程序来执行此操作。 我承认我还没有那样做过测试,因为大多数时候我对转发单个端口感到满意。

I hope this will make your work with Docker on WSL much more pleasant. It certainly did this for me!

我希望这会使您在WSL上使用Docker的工作更加愉快。 它确实为我做到了!

参考书目 (Bibliography)

I wouldn’t have written this article if it wasn’t for the fine people who shared their knowledge. Every time I stumbled over some obstacle I could search for the existing solutions. Below, a list of articles and posts that helped me write this guide:

如果不是共享知识的优秀人士,我就不会写这篇文章。 每当我遇到障碍时,我都可以搜索现有的解决方案。 下面是帮助我撰写本指南的文章和帖子列表:

Setting Up Docker for Windows and WSL to Work FlawlesslyWith a couple of tweaks the WSL (Windows Subsystem for Linux, also known as Bash for Windows) can be used with Docker…nickjanetakis.comHow to access linux/Ubuntu files from Windows 10 WSL?Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute…superuser.comPort forwarding in docker-machine?You can still access the VBoxmanage.exe command from the VirtualBox used by docker machine: VBoxManage controlvm…stackoverflow.com

设置适用于Windows和WSL的Docker使其正常运行 通过一些调整,WSL(适用于Linux的Windows子系统,也称为Windows的Bash)可以与Docker一起使用... nickjanetakis.com 如何从Windows 10 WSL访问linux / Ubuntu文件? 超级用户是计算机爱好者和超级用户的问答网站。 加入他们; 只需要一分钟... superuser.com 在docker-machine中进行端口转发? 您仍然可以从docker机器使用的VirtualBox中访问VBoxmanage.exe命令:VBoxManage controlvm… stackoverflow.com

翻译自: https://www.freecodecamp.org/news/how-to-set-up-docker-and-windows-subsystem-for-linux-a-love-story-35c856968991/

你可能感兴趣的:(linux,java,python,docker,windows)