手装 dockerd 到 wsl Ubuntu

最后发布时间 : 2026-11-11 22:42:44 浏览量 :

一、先回答“Windows 有没有现成的”

没有。 Microsoft 只提供空的 Ubuntu 发行版(wsl --install -d Ubuntu),不提供预装 dockerd 的版本。Docker 官方提供的是 Docker Desktop(走 Docker Desktop 自己的 WSL 发行版 docker-desktop,不是你自己的 Ubuntu)。

所以要得到“Ubuntu + dockerd”有两条路:

路线说明是否需要 Docker Desktop
A. 手装 dockerd 到 Ubuntuwsl --install -d Ubuntu 后 apt 装 docker-ce,自己配 TCP不需要
B. 复用 Docker Desktop 的 docker-desktop 发行版该发行版里已有 dockerd,但不建议直接连(它由 Desktop 管理)需要

你目标是“Ubuntu 里运行 dockerd”,就是路线 A。下面全是可在 PowerShell(管理员)里手动执行的命令。


二、阶段 1:检查 WSL 与已装发行版

wsl --status
wsl --version
wsl -l -v

wsl -l -v 输出示例:

  NAME            STATE           VERSION
* Ubuntu          Running         2
  docker-desktop  Stopped         2

注意 STATE 列:Running / Stopped / Installing。


三、阶段 2:安装 Ubuntu(若不存在)

wsl --install -d Ubuntu --no-launch
  • --no-launch 避免它立刻弹出“创建用户名密码”的交互窗口(后续我们用 root 操作)。
  • 若提示需要重启或开启虚拟化,按提示重启后再执行 wsl --set-default-version 2。

首次启动并设置用户(如已 --no-launch,需要显式启动一次完成初始化):

wsl -d Ubuntu -u root -- sh -lc "echo initialized"

四、阶段 3:在 Ubuntu 内安装 docker-ce

一条命令搞定(用 root,避免 sudo 密码问题):

wsl -d Ubuntu -u root -- bash -lc @'
set -e
export DEBIAN_FRONTEND=noninteractive
apt-get update
apt-get install -y ca-certificates curl gnupg iptables
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" > /etc/apt/sources.list.d/docker.list
apt-get update
apt-get install -y docker-ce docker-ce-cli containerd.io
'@

PowerShell 里 @'...'@ 是 here-string,可安全包含 $ 和多行。千万别用双引号包裹,否则 $(...) 会被 PowerShell 提前展开。


五、阶段 4:配置 dockerd 监听 TCP

关键点:WSL Ubuntu 默认不一定启用 systemd(旧版没有)。先确认:

wsl -d Ubuntu -u root -- bash -lc "ps -p 1 -o comm=; systemctl is-system-running 2>/dev/null || echo no-systemd"
  • 输出 systemd 或 running/degraded → 走 路线 1(systemd)
  • 输出 init 或 no-systemd → 走 路线 2(手动起进程)

路线 1:有 systemd

写 daemon.json(同时保留 unix socket 和 tcp):

wsl -d Ubuntu -u root -- bash -lc @'
mkdir -p /etc/docker
cat > /etc/docker/daemon.json <<"EOF"
{
  "hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2375"]
}
EOF
mkdir -p /etc/systemd/system/docker.service.d
cat > /etc/systemd/system/docker.service.d/override.conf <<"EOF"
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd
EOF
systemctl daemon-reload
systemctl enable docker
systemctl restart docker
'@

为什么必须加 override.conf:Ubuntu 的 docker.service 默认带 -H fd://,而 daemon.json 里一旦出现 hosts 就会与命令行参数冲突报错 can't create unix socket ... hosts and -H cannot be combined。清空 ExecStart 再重写,才让 daemon.json 生效。

路线 2:无 systemd

手动前台起(先测能不能通):

wsl -d Ubuntu -u root -- bash -lc @'
mkdir -p /etc/docker
cat > /etc/docker/daemon.json <<"EOF"
{
  "hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2375"]
}
EOF
nohup dockerd > /var/log/dockerd.log 2>&1 &
sleep 3
tail -n 20 /var/log/dockerd.log
'@

注意:这条命令结束后,WSL 实例若没有其他常驻进程,几秒后会休眠,dockerd 也随之被杀。手动测试时没关系,但要长期保持,得让上一条命令保持不返回,或另开一个 wsl 会话挂着。


六、阶段 5:验证(在 WSL 内)

# 进程
wsl -d Ubuntu -u root -- bash -lc "pgrep -x dockerd && echo PROCESS_OK"

# TCP 监听
wsl -d Ubuntu -u root -- bash -lc "ss -tln | grep 2375"

# 本地 docker 可用
wsl -d Ubuntu -u root -- bash -lc "docker version --format '{{.Server.Version}}'"

# 取 WSL IP
wsl -d Ubuntu -u root -- bash -lc "hostname -I | awk '{print \$1}'"

最后一条的输出(如 172.24.123.45)就是 NAT 模式下 Windows 要连的地址。


七、阶段 6:从 Windows 侧验证连通

先确认网络模式:

Get-Content "$env:USERPROFILE\.wslconfig" -ErrorAction SilentlyContinue
  • 无此文件或没写 networkingMode=mirrored → NAT 模式,用 hostname -I 的 IP:
$ip = (wsl -d Ubuntu -u root -- bash -lc "hostname -I | awk '{print `$1}'").Trim()
Test-NetConnection -ComputerName $ip -Port 2375
  • 写了 networkingMode=mirrored(Win11 22H2+) → 直接用 127.0.0.1:
Test-NetConnection -ComputerName 127.0.0.1 -Port 2375

通了之后再试 Docker API:

$env:DOCKER_HOST = "tcp://<上面的可用地址>:2375"
docker version          # 有 Server 段即成功

若本机没装 docker CLI,用 PowerShell 直接打 API:

Invoke-RestMethod -Uri "http://<地址>:2375/version"

八、常见报错对照表

报错原因处理
hosts and -H cannot be combineddocker.service 的 -H fd:// 与 daemon.json 冲突加 override.conf 清空 ExecStart
Cannot connect to the Docker daemon at unix:///var/run/docker.sockdockerd 没起 / 实例休眠了重跑启动命令,并保持常驻
Test-NetConnection 2375 失败,但 WSL 内 ss 能看到用了 127.0.0.1 但处于 NAT 模式改用 hostname -I 的 IP
iptables: No chain/target/match by that nameWSL 内核缺模块 / 缺 iptables 包apt-get install -y iptables,重启 dockerd
dockerd 启动即退出daemon.json 语法错误dockerd --validate --config-file /etc/docker/daemon.json
wsl -l -q 输出乱码UTF-16LE仅在 Go 代码里需转码;PowerShell 里正常显示

九、测试完成的清理/重置

# 只停实例(保留数据)
wsl --terminate Ubuntu

# 彻底卸载发行版
wsl --unregister Ubuntu

建议按这个顺序手动跑一遍:阶段1 → 2 → 3 → 4(先路线1,不行再路线2)→ 5 → 6。等你在自己机器上确认哪条路线和哪个地址可用,我再把这些命令按 Inspect() + Ensure() 的结构落成 Go 代码。