• 请不要在回答技术问题时复制粘贴 AI 生成的内容
ly50247
V2EX  ›  程序员

用 WSL 运行 Docker 镜像

  •  2
     
  •   ly50247 · Apr 28, 2019 · 9948 views
    This topic created in 2750 days ago, the information mentioned may be changed or developed.

    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/
    
    

    实现方式

    1. 首先,从 Docker Hub 下载镜像,有现成脚本,download-frozen-image-v2.sh。
    2. 然后,准备用于安装 WSL 实例的最小镜像(可以从 https://github.com/0xbadfca11/miniwsl/releases 下载)。
    3. 最后,自己编写各种自动化的脚本,我是用 zsh 写的,先贴在下边,如果感兴趣的人较多我再放到 GitHub 上,不然就不折腾了。
    #!/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
    

    因为是从我自己环境拷贝出来的,运行可能会有问题,喜欢折腾的朋友可以玩玩。

    25 replies  •  2019-04-29 10:01:35 +08:00
    mimimiZ
    mimimiZ
    Apr 28, 2019
    1
    ummm 楼主为什么要在 WSL 里面用 docker 直接在 win 上面用不是也可以... 只是好奇,我是在 mac 上直接使用 docker for mac 的 所以觉得 docker for win 应该也差不多。
    ly50247
    ly50247
    OP
    Apr 28, 2019
    2
    @mimimiZ 直接在 Windows 下运行需要用虚拟机,而且体积较大,不想安装。
    mimimiZ
    mimimiZ
    Apr 28, 2019 via iPhone
    3
    @ly50247 原来如此 明白了!
    v2dead
    v2dead
    Apr 28, 2019
    4
    楼主思路清奇,这个想法相当给劲啊。不过有 volume 卷和端口映射应该会有点问题。
    xzc19970719
    xzc19970719
    Apr 28, 2019
    5
    。。。强
    gosansam
    gosansam
    Apr 28, 2019
    6
    难得一见教程贴 顶了
    KuroNekoFan
    KuroNekoFan
    Apr 28, 2019 via iPhone
    7
    直接用 docker-desktop 可能简单点……
    Rwing
    Rwing
    Apr 28, 2019
    8
    ly50247
    ly50247
    OP
    Apr 28, 2019 via iPhone
    9
    @v2dead 端口映射也可以通过脚本来处理,但比较麻烦,需要适配不同程序。更高级的功能就很难实现了。不过如果有人专门开发的话还是能实现不少功能,虽然意义不是很大,也难说一定不会有好事者。我想更可能的是利用 Docker Hub 的镜像自己实现一套适用于 WSL 的系统,专门用来开发,毕竟很多人都只是用 Docker 的最基本功能。
    ly50247
    ly50247
    OP
    Apr 28, 2019 via iPhone
    10
    @Rwing 我记得之前试过不行,一会再试试吧。
    ly50247
    ly50247
    OP
    Apr 28, 2019
    11
    @Rwing 搜了一下好像确实能用,但据说高于 17.09 的就不行了,而且功能不全,不想折腾它了。另外其实我没有什么用 Docker 的需求,主要是去下它的镜像玩玩,不想一直起个服务。
    hantsy
    hantsy
    Apr 28, 2019
    12
    Docker for win 一直不想用,第一它还是基于 Hyper-V 虚拟机的,第二与 VirtualBox 等互不相容,可是我要用 VirtualBox,所以直到现在我还是用 DockerToolbox (也就是使用 VirtualBox 的版本)。

    用 Docker 还是要用 Linux。
    ly50247
    ly50247
    OP
    Apr 28, 2019
    13
    @hantsy 我也因为装了 VirtualBox 而一直没尝试 Hyper-V,虽然用了 WSL 后就很少用 VrtualBox 了,但没有还是不方便。也许哪天有兴趣了再折腾下,把 VirtualBox 换成 Hyper-V。

    另外我也写了几个 VirtualBox 的 alias:

    alias vm='/init </dev/null /mnt/c/Program\ Files/Oracle/VirtualBox/VBoxManage.exe'
    alias vmlist='vm list vms; echo --RUNNING--; vm list runningvms'
    alias vmup='vm startvm archlinux --type headless'
    alias vmdown='vm controlvm archlinux savestate'
    alias vmpause='vm controlvm archlinux pause'
    alias vmresume='vm controlvm archlinux resume'
    alias vmhalt='vm controlvm archlinux poweroff'

    vw() {
    [[ $1 == "-r" ]] && {
    ssh -tq $USER@$HOST $*[2,-1]
    return
    }

    local args
    (($# >= 1)) && args="zsh -ic '$*'"

    ssh -tq $USER@$HOST $args
    }
    beginor
    beginor
    Apr 28, 2019
    14
    Docker for Win 最大的痛点是卷映射时, 不支持文件锁定, 导致很多服务(尤其是数据库)无法运行。
    tt0411
    tt0411
    Apr 28, 2019
    15
    回归 Windows 指日可待
    Imr
    Imr
    Apr 28, 2019 via iPhone
    16
    和虚拟机运行一个 coreos 做 server 端比,优势在哪,感觉像是从一个坑跳进另一个坑
    bellchu
    bellchu
    Apr 28, 2019
    17
    Docker 对内核环境有要求,WSL 的内核非全部 feature 都 enable 状态,再加上 WSL 的 low io,我觉得没啥意义。
    ly50247
    ly50247
    OP
    Apr 28, 2019
    18
    @Imr 不需要运行 Server,直接用就可以,节省资源。
    xdlucky
    xdlucky
    Apr 28, 2019 via iPad
    19
    还是装虚拟机吧,虚拟机多好玩啊
    0Y89tX3MgR4I
    0Y89tX3MgR4I
    Apr 28, 2019 via Android
    20
    nice !最近正好有这个需求,不过看下来感觉还是太折腾了,我个人还是宁愿找个 Linux 环境。不过还是支持楼主整理一下放到 GitHub 上
    ly50247
    ly50247
    OP
    Apr 28, 2019 via iPhone
    21
    @0Y89tX3MgR4I 之后我想了下,其实这已经和 chroot 没太大区别了,只多个进程隔离,而 chroot 已经能满足我需求了,所以我打算改用 chroot 重新适配了。
    mmdsun
    mmdsun
    Apr 29, 2019 via Android
    22
    支持。
    hantsy
    hantsy
    Apr 29, 2019
    23
    @ly50247 我觉得在 Windows 比较好的运行 Docker 的方式,就是用 Vagrant,或者直接在虚拟机系统里面运行,但这些操作起来比较繁琐。目前这个 HyperV 的 Docker for Win 和 VirtualBox 版本的 DockerToolbox (使用 Boot2Docker )的 Docker 都是会存在 Volume 映射问题。

    开发时用 Docker (我现在是开发用到的什么服务都是喜欢跑 Docker,数据库,HTTP 服务等)还好,但是如果是本地太多的 Docker, 想做一些 DevOps/Pipeline,Windows 下要命,玩过一次 Docker Swarm 就不想搞了。
    specita
    specita
    Apr 29, 2019
    24
    厉害了,我就是没折腾成功跑去搞了个 linux 机子 orz.
    ly50247
    ly50247
    OP
    Apr 29, 2019
    25
    @hantsy 如果已经有在虚拟机的 Linux,直接在里边运行是最方便的,其他的多少都需要折腾下。

    另外我认为开发场景很多时候都是在滥用 Docker。昨天我搜镜像时竟然看到了一个 thrift 的,安装后运行就是 thrift 命令。这种场景应该完全不需要用 Docker,把文件准备好后放到 /opt,或者最多用下 chroot 就可以了。但好的方面是 Docker 镜像很丰富,可以用来搭环境。如果是测试环境,基本没必要用 Windows 了。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   1735 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 49ms · UTC 12:29 · PVG 20:29 · LAX 04:29 · JFK 07:29
    ♥ Do have faith in what you're doing.