不使用 Docker Desktop 在 Windows(WSL)上安装 Docker
更新于 2022 年 4 月 10 日,包含最新的 Alpine 使用说明、Debian/Ubuntu 软件包签名调整(不再使用 apt-key),以及在 Debian 中处理 iptables 的更佳指南。此外,还提供了有关 TCP 访问的更多建议。并进一步强调了
/mnt/wsl/shared-docker
套接字目录的可选性。
Windows Subsystem for Linux 2 搭载了真正的 Linux 内核,支持真正的 Linux 容器和 Docker。Docker 可以在 WSL 2 上运行,并且无需使用强大但笨重的 Docker Desktop(如果不想使用的话)。然而,由于 WSL 和 Docker 的复杂性,Docker 的启动和运行需要一些细心的维护。本文将尝试探索这一过程以及其中的各种选项。
与本文篇幅所暗示的相反,让 Docker 在 WSL 上运行起来相当简单。简而言之:
- 不要使用诸如 systemd 之类的 init 系统来启动 Docker 守护进程,而是通过
dockerd
手动调用来启动它。 - 如果希望在 WSL 实例之间共享 Docker 守护程序,请将其配置为使用存储在共享目录中的套接字
/mnt/wsl
。 - 如果需要不使用 sudo 的共享和特权访问,请将
docker
组配置为在所有 WSL 实例中具有相同的组 ID - 为了简单起见,不要启动基于 Windows 的 Docker 客户端,而是
docker
在 WSL 内部启动。
当然,下面还有更多细微差别和决策。滚动到底部查看配套 Github 仓库的详细信息。
您确定不想要 Docker Desktop 吗?
在继续之前,让我们先了解一下 Docker Desktop 的强大之处。如果您想让 Docker 在 Windows 和 WSL 2 上运行,安装 Docker Desktop可能是最佳选择。借助Docker Desktop 的 WSL 2 后端,Docker 可以相当优雅地与 Windows 集成,并且 Docker 客户端可以通过 Powershell 或 Linux 启动。了解 Docker Desktop 的底层原理也是一件既有趣又有益的事情。非常巧妙。
如果您来这里是为了寻找如何轻松运行 Docker,或者您想要开箱即用的 Windows 容器(仍然很少见),那么 Docker Desktop 就是您的好朋友,您现在就可以安装它。
但是,如果你和我一样,觉得 Docker Desktop 增加的所有复杂性都是不必要的,你不需要 Windows 容器,或者你只是厌倦了系统托盘中那条“鲸鱼”耗时太长……那么,或许你应该dockerd
在你选择的 WSL 发行版中运行 docker daemon(),这样就好了。你来对地方了。
请注意,Docker Desktop 仅对个人或小型公司免费。如果您将其用于工作,并且公司规模或收入超过一定水平,请考虑付费订阅。当然,如果您使用 Docker 时没有使用 Docker Desktop(如本文所述),则不适用此规定。点击此处,查看有关 Docker 订阅模式的更多详情。
你尝试过 Podman 吗?
不过,在我们开始之前,先问一下:您知道Podman吗?Podman 无守护进程(无需后台服务)、现代(开箱即用的 cgroups v2)、支持无根 (rootless),并且可以作为 Docker 的直接替代品。无需担心套接字和端口,很多麻烦事就迎刃而解了。
我曾经写过关于如何在 WSL 2 上运行 Podman 的文章。欢迎尝试一下,或许你永远不会后悔。没错,VSCode 确实可以与 Podman 兼容。
然而……有时候,你只需要 Docker 就能工作。也许你使用的某些工具无法处理 Podman,或者你只是想测试一下 WSL 的性能。如果是这样,请继续阅读。
确保 WSL 是版本 2
请注意,这些步骤需要 WSL 2(而非 WSL 1)。WSL 2 使用支持 Linux 容器的实际 Linux 内核。WSL 1 在 Windows 内核上运行 Linux 方面非常出色,但当然缺少一些功能,例如容器。微软在文档中提供了更详细的比较。
您肯定需要 WSL 2 来运行 Docker 服务。
该命令wsl --set-default-version 2
有效吗?这会将默认版本设置为 WSL 2,如果您仍在使用第一个版本,则会失败。
要运行 WSL 2,需要 Windows 1903 或更高版本,并运行 Build 18362 或更高版本。要查看您正在运行的版本,请winver
在 Powershell 或 CMD 中运行,或者直接按下 Win 键和 R (⊞-r) 打开“运行”对话框,然后输入winver
。希望您能看到类似“版本 21H2。操作系统版本 19044.1586”的内容。
安装 Linux 发行版
如果您尚未拥有所选发行版的 WSL 实例,下一步是从 Microsoft Store 中选择一个。如果您不喜欢 Windows Store,还有其他选择。
对于 WSL 2 来说,自定义安装也是一个不错的选择。例如,安装并配置 Fedora或任何其他可以获取 tar 格式的 rootfs 的发行版,然后wsl --import rootfs.tar
。
本指南包含在Debian、Ubuntu、Alpine和Fedora中启动 dockerd 的说明。如果您认为还有其他值得考虑的 WSL 发行版,请在评论中告诉我。
配置非root用户
安装您选择的发行版后,请启动它并设置非 root 用户(如果您尚未设置)。Debian 和 Ubuntu 会在首次启动时自动配置,如果您从商店安装 Alpine,Alpine 也应该如此。如果命令whoami
返回“root”,则您需要添加一个非 root 用户。对于 Alpine 或 Fedora,请使用adduser myusername
创建新用户。在 Alpine 上,这将提示您输入新密码。在 Fedora 上,您还需要passwd myusername
并输入您想要使用的密码。(如果您的 Fedora 没有passwd
,则需要先dnf install passwd cracklib-dicts
)。
在 Microsoft Store 中下载的更高版本的 Alpine 中,虽然在安装过程中会创建一个非 root 用户,但该用户最初是没有密码的。您可以使用以下命令在任何发行版上进行仔细检查:
cat /etc/shadow | grep myusername | cut -d: -f2
(如果您不是 root,则可能需要su
先执行此操作)。
如果结果为“!”,则表示该用户未设置密码。如果结果是一个随机哈希字符串,则表示一切正常。如果需要设置密码,可以使用passwd myusername
(当然,以上所有方法中,请使用您的用户名代替“myusername”)。
为非 root 用户配置管理员 (sudo) 访问权限
如果您使用的是 Windows 应用商店中的 Debian 或 Ubuntu,并在首次启动时设置了默认用户,那么 sudo 应该已经为默认用户配置好了。您可以跳过此步骤,继续下面的更新软件包和测试网络连接。
当以您设置的用户身份登录时(su myusername
如果您仍然是 root 用户,请尝试),是否可以sudo -v
不出现错误?
如果没有,请首先确保已安装 sudo。在 Alpine 上,sudo 为 ;apk add sudo
在 Fedora 上, sudo 为dnf install sudo
。如果由于网络连接失败,请参见下文。您可以按照那里的说明来更正 DNS,但当然,请删除这些命令中出现的sudo
,因为您还没有安装,而且您仍然应该是 root 用户。
你的用户是“sudoer”吗?尝试以下操作,看看他们是否属于sudo
或wheel
组:
grep -E 'sudo|wheel' /etc/group
在具有sudo
组的发行版(例如 Ubuntu 和 Debian)上,您应该会看到类似的内容sudo:x:27:myusername
;在具有wheel
组的发行版(例如 Fedora 和 Alpine)上,您应该会看到类似的内容wheel:27:myusername
。
如果组中缺少您的用户名,请记下组名(sudo
或wheel
),并将相关用户添加到该组:
- 高山:
addgroup myusername wheel
- Fedora:
usermod -aG wheel myusername
- 可能没有必要,但在 Ubuntu/Debian 上:
usermod -aG sudo myusername
最后,以 root 身份确保管理员组(无论是sudo
还是wheel
)已启用 sudo:
grep -E '%sudo|%wheel' /etc/sudoers
如果该行存在,但用 注释掉#
,则运行visudo
并确保该行内容如下(使用wheel
或sudo
按照先前确定的方式):
%wheel ALL=(ALL) ALL
然后保存。
完成这些步骤后,再次测试:
su myusername
sudo -v
如果系统提示您输入密码,则一切正常。如果您收到类似“抱歉,用户 myusername 可能无法运行 sudo”的错误,则可能需要从头开始重新执行这些步骤。
设置默认用户
如果您从商店获取了 Linux 发行版,则可以跳过此步骤,因为默认用户已经设置好了。
但是,如果启动 WSL 时您仍然是 root 用户,则将新用户设置为默认用户。
假设您拥有 Windows 版本 18980 或更高版本:只需向/etc/wsl.conf
.
如果您还没有该文件或[user]
其中的某个部分,那么类似这样的操作将会很有效:
printf "\n[user]\ndefault = myusername\n" | sudo tee -a /etc/wsl.conf
但是,如果您使用的是 Windows 10 Build 18980 之前的版本,则需要编辑注册表来设置默认用户。执行此操作之前,我们需要两条信息:用户 ID 和 WSL 发行版名称。您可能已经知道这些信息。如果不知道,您可以使用以下命令获取用户 ID,id -u myusername
并使用以下命令(在 Powershell 中)检查您的 WSL 发行版列表。wsl -l
然后,在 Powershell 中使用以下命令,但使用您的 WSL 发行版名称代替“Alpine”,并使用您的用户 ID 代替“1000”:
Get-ItemProperty Registry::HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Lxss\*\ DistributionName | Where-Object -Property DistributionName -eq Alpine | Set-ItemProperty -Name DefaultUid -Value 1000
无论使用哪种方法,请先退出 WSL 再重新登录进行测试。确认whoami
用户名正确。成功。
更新/升级包并测试网络连接
让我们用以下方法之一让一切变得崭新而闪亮:
- Debian/Ubuntu:
sudo apt update && sudo apt upgrade
- Fedora:
sudo dnf upgrade
- 高山:
sudo apk upgrade -U
网络问题?
升级软件包也可以作为网络测试。由于各种原因, WSL 2可能会出现网络连接问题,根据我的经验,调整 DNS 设置通常可以解决这些问题。如果升级命令成功,您可以跳过此部分。但是,如果上述命令无法访问软件包服务器,则可能是您的网络、防火墙或反恶意软件存在问题。我建议执行以下操作:
echo -e "[network]\ngenerateResolvConf = false" | sudo tee -a /etc/wsl.conf
sudo unlink /etc/resolv.conf
echo nameserver 1.1.1.1 | sudo tee /etc/resolv.conf
第一行告诉 WSL 停止自动配置该/etc/resolv.conf
文件。然后我们删除/取消链接旧文件,并创建一个新文件。
使用这个新配置的 DNS 解析器(在本例中,它直接指向 Cloudflare 的 DNS 服务器),您可以再次尝试升级软件包。成功了吗?太棒了。
准备 Docker 安装
值得庆幸的是,目前已经有官方指南可以在各种 Linux 发行版上安装 Docker。我根据这些指南编写了以下说明,并根据实际测试经验进行了一些调整。
清除残留物
如果这不是全新安装,并且您可能之前已经尝试过 docker,那么请首先清除所有残留的 docker 安装:
- Fedora:
sudo dnf remove moby-engine docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-selinux docker-engine-selinux docker-engine
- Debian/Ubuntu:
sudo apt remove docker docker-engine docker.io containerd runc
- Alpine(可能没有必要,但以防万一):
sudo apk del docker-cli docker-ce docker-openrc docker-compose docker
安装依赖项
然后,安装先决条件:
- Debian/Ubuntu:
sudo apt install --no-install-recommends apt-transport-https ca-certificates curl gnupg2
- Fedora:
sudo dnf install dnf-plugins-core
- Alpine:无需任何依赖项。依赖项稍后将自动安装。
Debian:切换到旧版 iptables
Docker利用 iptables 实现网络隔离。Debian使用了更现代的 nftables,但这意味着 Docker 无法自动调整 Linux 防火墙。因此,您可能希望将 Debian 配置为默认使用旧版 iptables:
update-alternatives --config iptables
并选择iptables-legacy。
如果你更倾向于使用 nftables,并且想手动为 Docker 配置 nftables,那就去做吧。不过,我估计大多数人会想切换到旧版 iptables。
Debian/Ubuntu 软件包存储库配置
在 Debian 或 Ubuntu 上,首先临时设置一些特定于操作系统的变量:
. /etc/os-release
然后,确保apt
信任该 repo:
curl -fsSL https://download.docker.com/linux/${ID}/gpg | sudo tee /etc/apt/trusted.gpg.d/docker.asc
ID
将是“ubuntu”或“debian”,具体取决于 中的内容/etc/os-release
。
然后添加并更新 repo 信息,以便apt
将来使用:
echo "deb [arch=amd64] https://download.docker.com/linux/${ID} ${VERSION_CODENAME} stable" | sudo tee /etc/apt/sources.list.d/docker.list
sudo apt update
Fedora 软件包存储库配置
在 Fedora 上,首先添加 Docker 的 repo:
sudo dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo
安装 Docker
现在我们可以安装官方的 Docker Engine 和客户端工具:
- Debian/Ubuntu:
sudo apt install docker-ce docker-ce-cli containerd.io
- Fedora:
sudo dnf install docker-ce docker-ce-cli containerd.io
- Alpine(从 Edge 安装最新版本):
sudo apk add docker --repository=http://dl-cdn.alpinelinux.org/alpine/edge/community
将用户添加到docker
组
Docker 守护进程是 Docker 需要在后台运行的服务。服务 ( dockerd
) 和客户端 ( docker
) 通过套接字和/或网络端口进行通信。通过套接字进行通信需要特权访问权限。获取此访问权限有两种方法:
- 以 root 身份运行
docker
(即sudo docker
) - 通过组成员身份,授予特定用户对 Docker 套接字的特权访问权限
换句话说,除非您sudo
每次都想使用或 root 访问权限,否则请将您的用户添加到名为的 Docker 组docker
:
- Fedora/Ubuntu/Debian:
sudo usermod -aG docker $USER
- 高山:
sudo addgroup $USER docker
然后关闭该 WSL 窗口,并再次启动 WSL。docker
运行命令groups
列出组成员身份时,您应该会看到以下内容。
docker
共享dockerd:为组选择一个通用的ID
如果您只打算使用一个 WSL 发行版,则下一步并非必需。但是,如果您希望在 WSL 发行版之间共享 Docker 套接字,则所有发行版都需要共享一个通用的组 ID docker
。默认情况下,每个发行版可能都有不同的 ID,因此需要创建一个新的 ID。
首先,我们来选择一个。它可以是任何未被使用的组 ID。选择一个大于 1000且小于 65534 的数字。要查看哪些已分配的组 ID 为 1000 或以上:
getent group | cut -d: -f3 | grep -E '^[0-9]{4}' | sort -g
不知道该用哪个号码?我建议你用36257。(用电话键盘输入DOCKR就行……)这个号码可能还没被用过,不过还是查一下吧:
getent group | grep 36257 || echo "Yes, that ID is free"
如果上述命令返回一行/etc/group
(不包含docker
),请选择另一个号码并重试。如果返回“是,该 ID 是免费的”,则您可以继续,并执行以下命令:
sudo sed -i -e 's/^\(docker:x\):[^:]\+/\1:36257/' /etc/group
或者,如果groupmod
可用(在 Fedora、Ubuntu 和 Debian 上有,但在 Alpine 上没有,除非你sudo apk add shadow
),这样做更安全:
sudo groupmod -g 36257 docker
一旦组 ID 更改,请关闭终端窗口并重新启动 WSL 发行版。
docker
请注意,如果您想让其访问共享 Docker 套接字,则需要在您当前拥有的或将来安装的任何 WSL 发行版上运行涉及该组的上述步骤。
(可选)准备共享目录
与上一步一样,如果您只打算使用一个 WSL 发行版,则下一步并非必需。但是,如果您希望在 WSL 发行版之间共享 Docker 套接字,则需要一个所有人都可以访问的共享目录。
让我们首先为 docker 套接字创建一个共享目录,并设置权限以便 docker 组可以对其进行写入。
DOCKER_DIR=/mnt/wsl/shared-docker
mkdir -pm o=,ug=rwx "$DOCKER_DIR"
chgrp docker "$DOCKER_DIR"
配置dockerd
使用共享目录
同样,如果您选择不使用共享目录作为 Docker 套接字,则可以跳过此步骤。但是,您可能希望输入其他设置daemon.json
,因此您可能需要熟悉此主题。
我建议使用配置文件/etc/docker/daemon.json
来设置 dockerd 启动参数。如果该/etc/docker
目录尚不存在,请使用 创建它,sudo mkdir /etc/docker/
以便包含配置文件。然后,将以下内容放入 中/etc/docker/daemon.json
,即可将 docker 主机设置为共享套接字:
{
"hosts": ["unix:///mnt/wsl/shared-docker/docker.sock"]
}
发射dockerd
大多数 Linux 发行版使用 systemd 或其他 init 系统,但 WSL 有自己的 init 系统。我们无需费力使用现有的 init 系统,而是dockerd
直接启动:
sudo dockerd
应该会出现几行信息、与 相关的警告等,最后cgroup blkio
会显示类似 的内容。如果是这样,则表示您成功了。API listen on /mnt/wsl/shared-docker/docker.sock
打开另一个 wsl 终端。
当且仅当您选择使用/mnt/wsl/shared-docker
如上所述的共享 docker 套接字时,首先设置DOCKER_HOST
环境变量:
export DOCKER_HOST="unix:///mnt/wsl/shared-docker/docker.sock"
然后,尝试一下 docker cli:
docker run --rm hello-world
您应该会看到“Hello from Docker!”消息。
启动脚本dockerd
如果需要自动启动,可以将以下几行放在.bashrc
或中.profile
,也可以放在单独的 shell 脚本中。例如,您可能希望创建一个脚本,~/bin/docker-service
以便docker-service
仅在需要时手动运行。
DOCKER_DISTRO="Debian"
DOCKER_DIR=/mnt/wsl/shared-docker
DOCKER_SOCK="$DOCKER_DIR/docker.sock"
export DOCKER_HOST="unix://$DOCKER_SOCK"
if [ ! -S "$DOCKER_SOCK" ]; then
mkdir -pm o=,ug=rwx "$DOCKER_DIR"
chgrp docker "$DOCKER_DIR"
/mnt/c/Windows/System32/wsl.exe -d $DOCKER_DISTRO sh -c "nohup sudo -b dockerd < /dev/null > $DOCKER_DIR/dockerd.log 2>&1"
fi
如果您使用默认的 docker 套接字位置而/var/run/docker.sock
不是上面详述的共享套接字目录/mnt/wsl/shared-docker
,那么脚本可能如下所示:
DOCKER_DISTRO="Debian"
DOCKER_LOG_DIR=$HOME/docker_logs
mkdir -pm o=,ug=rwx "$DOCKER_LOG_DIR"
/mnt/c/Windows/System32/wsl.exe -d $DOCKER_DISTRO sh -c "nohup sudo -b dockerd < /dev/null > $DOCKER_LOG_DIR/dockerd.log 2>&1"
当然,你可以选择任何你想要的位置来存放 docker 日志。它只需要位于一个有权限的地方,以便你的用户可以写入它。
请注意,DOCKER_DISTRO
应将 设置为您想要运行的发行版dockerd
。如果不确定名称,只需wsl -l -q
从 Powershell 运行即可查看您的 WSL 发行版列表。选择正确的发行版并将其设置为DOCKER_DISTRO
。
上面的脚本执行以下操作:
- 设置环境变量
$DOCKER_HOST
以指向共享套接字。这不是必需的,dockerd
但它允许运行时docker
无需-H unix:///mnt/wsl/shared-docker/docker.sock
每次都指定。 - 检查
docker.sock
文件是否已存在且为套接字。如果存在,则不执行任何操作。如果不存在,则脚本执行剩余步骤,如下所示。 - 为套接字和
dockerd
日志创建共享的 docker 目录,并适当设置权限 dockerd
从指定的发行版运行。这很重要,因为它允许任何dockerd
尚未运行的WSL 发行版启动。- 启动时
dockerd
,将其输出和错误传送到共享日志文件。 - 启动后
dockerd
,它会在后台运行,因此您无需像之前那样专门打开一个终端窗口来处理该进程。该sudo -b
标志提供了此功能,我们使用nohup
它运行,使其独立于终端运行,并使用显式的空输入来nohup
避免出现额外的警告。标准输出和错误都会写入日志文件,因此需要2>&1
重定向。
无需密码即可启动dockerd
如果将上述脚本放置在.bashrc
(大多数 Linux 发行版)或.profile
(以 Ash/Dash 作为默认 shell 的 Alpine 等发行版)或其他 shell 初始化脚本中,则会产生一个不良的副作用:几乎每次启动新的终端窗口时,系统都可能会提示您输入密码。
要解决这个问题,您可以选择sudo
授予 的无密码访问权限dockerd
,只要用户是该docker
组的成员即可。为此,请输入sudo visudo
并添加以下行(如果您visudo
使用vi
或vim
,则请务必按“ i
”开始编辑,并在完成编辑后按 ESC 键):
%docker ALL=(ALL) NOPASSWD: /usr/bin/dockerd
保存并退出(:wq
如果编辑器是vi
,则按“ ”;如果是 ,则按 Ctrl-x nano
),然后您可以测试它是否sudo dockerd
提示输入密码。为了安心,您可以再检查一遍:类似 的操作sudo -k ls -a /root
仍然需要密码,除非您最近输入过密码。
确保$DOCKER_HOST
始终设置
如果之前使用脚本启动dockerd
,那么$DOCKER_HOST
将会被设置,并且将来的调用docker
将不需要笨重的-H unix:///mnt/wsl/shared-docker/docker.sock
如果该脚本已存在于你的.bashrc
或 中.profile
,则无需执行以下步骤。但是,如果你以某种方式手动调用,并且你选择了共享的 docker 套接字目录,dockerd
则可能需要在你的.bashrc
或中使用以下内容:.profile
DOCKER_SOCK="/mnt/wsl/shared-docker/docker.sock"
test -S "$DOCKER_SOCK" && export DOCKER_HOST="unix://$DOCKER_SOCK"
上述代码会检查是否存在 docker 套接字/mnt/wsl/shared-docker/docker.sock
,如果存在,则$DOCKER_HOST
相应地设置环境变量。如果您想要更通用的“如果这是 wsl,则主动设置套接字”,那么您可能更喜欢下面的代码,它只检查目录是否存在/mnt/wsl
,如果存在,则设置 docker 套接字:
[ -d /mnt/wsl ] && export DOCKER_HOST="unix:///mnt/wsl/shared-docker/docker.sock"
docker
从 Windows运行
如果配置如上所述,我建议始终从 WSL 运行 docker。要运行容器吗?请从 WSL 窗口运行。(请参阅我关于使用 Windows 终端的文章,了解如何便捷地使用 WSL 和 Powershell。)
这不仅适用于终端。例如,VSCode 在 WSL 2 中支持 docker。
但是,如果您想要在 Powershell 窗口中运行 docker 的便利性和实用性,我有几个建议。
一种是dockerd
通过 TCP 端口公开,或者更好的方法是,在 WSL 中设置一个 SSH 服务器并以此方式连接。docker context
这种方法可能会对你有帮助。这些方法将在后续文章中探讨,但我鼓励读者们去探索。提示:你试过scoop.sh吗?设置完成后,scoop install docker docker-compose
它会提供一些你熟悉的工具,然后在 WSL 端提供一个 SSH 服务器,例如 Dropbear 或 OpenSSH……
我推荐一种简化的方法:一个 Powershell 函数,它调用 WSLdocker
并传递任何参数。此函数可以放在你的 Powershell 配置文件中,通常位于~\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
$DOCKER_DISTRO = "fedora"
function docker {
wsl -d $DOCKER_DISTRO docker -H unix:///mnt/wsl/shared-docker/docker.sock @Args
}
再次,wsl -l -q
如果您不确定使用哪一个,请尝试查看 WSL 发行版列表。
确保 Docker 守护进程正在运行,然后启动一个新的 Powershell 窗口,并hello-world
再次尝试该容器。成功了吗?
您也可以创建一个包含相应命令的批处理文件。例如,将其命名为docker.bat
,然后将其放置在C:\Windows\system32
或 中包含的其他位置%PATH%
。以下内容可在这样的脚本中运行:
@echo off
set DOCKER_DISTRO=fedora
wsl -d %DOCKER_DISTRO% docker -H unix:///mnt/wsl/shared-docker/docker.sock %*
您可以更进一步,确保dockerd
每次启动 Powershell 时都在运行。假设dockerd
上面详述的启动脚本保存在 WSL 中的一个文件中,并且$HOME/bin/docker-service
是可执行文件(try chmod a+x $HOME/bin/docker-service
),那么 Powershell 配置文件中的以下行将dockerd
自动启动:
wsl -d $distro ~/bin/docker-service
不确定你的 Powershell 配置文件在哪里?尝试$profile
在 Powershell 窗口中输入。
如果您不想依赖特定的 WSL shell 脚本,您可以实现 Powershell 函数来启动 dockerd,例如:
function Docker-Service {
Param ([string]$distro)
$DOCKER_DIR = "/mnt/wsl/shared-docker"
$DOCKER_SOCK = "$DOCKER_DIR/docker.sock"
wsl -d "$distro" sh -c "[ -S '$DOCKER_SOCK' ]"
if ($LASTEXITCODE) {
wsl -d "$distro" sh -c "mkdir -pm o=,ug=rwx $DOCKER_DIR ; chgrp docker $DOCKER_DIR"
wsl -d "$distro" sh -c "nohup sudo -b dockerd < /dev/null > $DOCKER_DIR/dockerd.log 2>&1"
}
}
此函数接受一个参数:发行版名称。
在上述所有内容中,原理都是相同的:您正在使用WSL 互操作性启动 Linux 可执行文件。
关于绑定挂载的说明:留在 Linux 文件系统上
使用 docker,可以将主机系统的目录或文件挂载到容器中。以下方法通常有效,但在从 Windows 启动 WSL docker 时不建议这样做:
echo "<h1>Hello, World</h1>" > index.html
docker run -p "8080:80" -v "$PWD:/usr/share/nginx/html:ro" nginx
不要随意执行上述操作,从 Powershell 启动 WSL docker 时,有两条建议:
- 出于性能考虑,请仅在 Linux 文件系统内进行绑定挂载。要在 Powershell 中访问 Linux 目录,请尝试以下操作:
cd (wsl wslpath -m ~/path/to/my/dir)
- 不要
$PWD
获取当前目录,尝试'$(wslpath -a .)'
一下,是的,单引号有助于转义。
一个例子:
cd (wsl wslpath -m ~)
mkdir html
cd html
echo "<h1>Hello, World</h1>" > index.html
docker run -p "8080:80" -v '$(wslpath -a .):/usr/share/nginx/html:ro' nginx
然后将浏览器指向http://localhost:8080,结果就完美了。(根据你的网络配置,你可能需要通过 http://[WSL IP Address]:8080 访问,可以使用ifconfig
或 来获取ip addr
)
尝试wsl wslpath
从 Powershell 或wslpath
Linux 中查看选项。至少可以说,这是一个非常有用的工具。
示例脚本
完成本文中的步骤后,您现在应该拥有一个可以正常工作、可能自动启动dockerd
、共享的 Docker 套接字以及方便配置的docker
命令。
上面的一些代码示例已放在配套的 Github 仓库的脚本中。我总结了可用的文件如下:
- docker-service.sh是一个 Unix shell 脚本,用于启动
dockerd
- docker-service.ps1
dockerd
包含一个可在 WSL 中启动的 Powershell 函数 - docker.bat是一个 Windows 批处理文件,用于
docker
从 CMD启动 WSL - docker.ps1包含一个 Powershell 函数,用于
docker
从 Powershell 启动 WSL(如果放在你的配置文件中)
毫无疑问,可以通过一些方法进行调整,使其更加实用和可靠;欢迎在评论中发表意见。
有兴趣进一步了解 WSL 2 吗?
我在 WSL 上写的其他文章:
文章来源:https://dev.to/bowmanjd/install-docker-on-windows-wsl-without-docker-desktop-34m9