Win 10 的 WSL 功能基本完善了,但一直运行不了 Docker (只能运行 Docker Client,Server 需要用虚拟机)。不过因为 WSL 中可以安装多个实例,并且可以同时运行,互不干扰,所以可以将 Docker 镜像下载下来,创建新的 WSL 实例,这样虽然不能实现 Docker 的很多功能,但作为本地开发和日常使用基本也够用了,感兴趣的朋友可以试下。
先看下效果(都是终端界面,不截图了):
% wsldl busybox (从 Docker Hub 下载镜像,安装为 WSL 实例,生成启动脚本等)
Downloading 'library/busybox:latest@latest' (1 layers)...
#################################################################### 100.0$
#################################################################### 100.0$
Download of images into '/home/goreliu/tmp/docker/busybox' complete.
Use something like the following to load the result into a Docker daemon:
tar -cC '/home/goreliu/tmp/docker/busybox' . | docker load
bin/
bin/[
bin/[[
bin/acpid
bin/add-shell
...
var/spool/
var/spool/mail/
var/www/
% wsll (列出所有 WSL 实例)
适用于 Linux 的 Windows 子系统:
Mine (默认)
thrift
empty
debian
rootfs
alpine
hello-world
memcached
busybox
% wsldr busybox (通过 docker 镜像中的 Entrypoint 和 Cmd 启动)
/mnt/c/tmp/docker #
% wsld busybox (直接进入 shell )
/mnt/c/tmp/docker #
% wsldr hello-world (运行个 hello-world,这个我之前已安装)
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
#!/bin/zsh
# 这个文件需要在 .zshrc 里 source
# 文件位置:
# c:/tmp 对应 ~/tmp
# WSL 实例安装到 c:/tmp/wsl/
# Docker 文件放置在 c:/tmp/docker/ 中,WSL 实例安装后可以删除
export WS='/mnt/c/Windows/System32'
alias wsl="/init $WS/wsl.exe"
# 运行指定 WSL 实例
alias wsld="/init $WS/wsl.exe -d"
# 列出 WSL 实例
alias wsll="/init $WS/wsl.exe -l"
# 列出在运行的 WSL 实例
alias wsllr="/init $WS/wsl.exe -l --running"
# 杀掉在运行的 WSL 实例
alias wslt="/init $WS/wsl.exe -t"
# 用于创建新的 WSL 实例,需要自己指定镜像文件
# 用法: wsln 实例名称
alias wsln='wsli c:/mine/app/miniwsl/rootfs.tgz'
# 安装 WSL 实例
wsli() {
(($# > 0)) || {
echo "Usage: $0 tarfile [name]"
return 1
}
[[ -n $2 && -e ~/tmp/wsl/$2 ]] && {
echo $2 exist
return 1
}
local name=${${1%%.*}:t}
[[ -n $2 ]] && name=$2
local filename=$1
[[ ${1:e} == xz ]] && xz -d $1 && filename=${1%.*}
/init $WS/wsl.exe --import $name c:/tmp/wsl/$name $1
}
# 删除 WSL 实例,包括其中的所有文件
wslu() {
[[ ! -n $1 || $1 == Mine ]] && return 1
/init $WS/wsl.exe --unregister $1 && rm -rvf ~/tmp/wsl/$1
}
# 从 Docker Hub 下载镜像文件,并安装为 WSL 实例
wsldl() {
[[ -n $1 ]] || return 1
local name=$1
local all=${name}:latest
[[ $1 == *:* ]] && {
name=${1/:/_}
all=$1
}
download-frozen-image-v2.sh ~/tmp/docker/$name $all
cd ~/tmp/docker/$name && wsldocker $name
}
# 将 Docker Hub 的配置文件转换成初始化脚本,由 wsldl 调用,也可手动运行
wsldocker() {
local name=$1
[[ -f repositories ]] || return 1
[[ -n $1 ]] || name=$(jq -r 'keys[0]' repositories)
wsli c:/mine/app/miniwsl/rootfs.tgz $name || return 1
wsldinit
for i ($(jq -r '.[0].Layers[]' manifest.json)) {
/init $WS/wsl.exe -d $name tar -xvf $i -C/
}
}
# 运行 Docker 镜像的初始化脚本
wsldr() {
[[ -n $1 ]] || return 1
[[ -f ~/tmp/wsl/$1/user ]] || {
echo ~/tmp/wsl/$1/user not found
return 1
}
/init $WS/wsl.exe -d $1 -u "$(cat ~/tmp/wsl/$1/user)" /myinit
}
还有一个用来处理 Docker 镜像配置文件的脚本 wsldinit:
#!/bin/zsh
[[ -f repositories ]] || {
echo repositories not found
return 1
}
name=$(jq -r 'keys[0]' repositories)
[[ -d ~/tmp/wsl/$name ]] || {
echo ~/tmp/wsl/$name not found
return 1
}
userfile=~/tmp/wsl/$name/user
runfile=~/tmp/wsl/$name/myinit
[[ -f manifest.json ]] || {
echo manifest.json not found
return 1
}
json=$(jq -r '.[0].Config' manifest.json)
User=$(jq -r '.config.User' $json)
if [[ -n $User ]] {
echo $User > $userfile
} else {
echo root > $userfile
}
echo '#!/bin/sh\n' > $runfile
cat $json | jq -r '.config.Env[]' | sed 's/^/export /g' >> $runfile
echo >> $runfile
WorkingDir=$(jq -r '.config.WorkingDir' $json)
[[ -n "$WorkingDir" ]] && {
echo cd \"$WorkingDir\" >> $runfile
}
echo -n "\nexec " >> $runfile
Entrypoint=$(jq '.config.Entrypoint[]' $json 2>/dev/null | tr '\n' ' ')
[[ -n "$Entrypoint" ]] && {
echo -n $Entrypoint >> $runfile
}
Cmd=$(jq '.config.Cmd[]' $json | tr '\n' ' ')
[[ -n "$Cmd" ]] && {
echo $Cmd >> $runfile
}
/init /mnt/c/Windows/System32/wsl.exe -t $name
cp $runfile ${runfile:h}/rootfs/
/init /mnt/c/Windows/System32/wsl.exe -d $name chmod 755 /myinit
因为是从我自己环境拷贝出来的,运行可能会有问题,喜欢折腾的朋友可以玩玩。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.