2

这篇文章需要接着《使用docker搭建laravel开发环境》一文中提到的问题的解答:

Windows下开启了Hyper-v后安卓模拟器及VMware均不能用了?

这个问题的前提是使用Docker for Windows时带来的,官方曾表态:

Docker Machine的驱动程序模型没有完全映射到Docker for Windows,因为Docker for Windows更加集成且紧密耦合(例如,我们有一个依赖于hyper-v的网络代理)。这是在灵活性与一致性以及紧密集成之间的一个令人不愉快的折中,这让我们试图解决Toolbox的VPN持久化和其他常见问题。

The driver model from Docker Machine doesn’t map cleanly to Docker for Windows because Docker for Windows is more integrated and tightly coupled (eg. we have a networking proxy that relies on hyper-v sockets). This is an unpleasant tradeoff between flexibility vs. consistency and tight integration that lets us try to tackle VPN durability and other common problems with Toolbox.

原文地址

大概意思是你洗洗睡,再好好想想到底用不用Docker for Windows。事实上我电脑还要打游戏的啊,用上Hyper-V不是逼我要好好学习好好工作吗?不过官方良心,还提供了一个方法临时解决这个问题:

关闭你的Hyper-V,然后重启完你的游戏去吧。

这令我每次都要在用上docker与玩游戏之间不断重启电脑。我也曾考虑用上老方法:虚拟机!但是考虑使用docker还要退回老方法能接受?这里尝试使用Docker for Windows较为旧的解决方案Docker Toolbox

安装 Docker Toolbox

喜欢阅读官方教程文档请移步

进入上面官方教程当你按下 Get Docker Toolbox for Windows 按钮下载完后安装,这里就细说明安装的问题。

使用

安装完桌面出现以下图标,每次开机均需要运行一次Docker QuickStart Terminal就可以使用docker了。

1

运行 hello world测试一下,成功运行如下:

docker run busybox echo hello world

Unable to find image 'busybox:latest' locally
511136ea3c5a: Pull complete
df7546f9f060: Pull complete
ea13149945cb: Pull complete
4986bf8c1536: Pull complete
hello world

比较多的问题

能使用vmware代替virtualbox吗?

答案:能!

由于使用Docker Toolbox使用virtualbox承载底层OS层服务,virtualbox毕竟是虚拟机技术在这里属于可替换的部分,还记得这篇文章的出现的原因吗?正是因为使用了同是虚拟化技术Hyper-V引申出来的。所以答案是能!

怎样换?这需要说说docker-machine的具体功能。

Machine lets you create Docker hosts on your computer, on cloud providers, and inside your own data center. It creates servers, installs Docker on them, then configures the Docker client to talk to them.

大概意思是docker的服务基于machine上的,然后可以理解为容器都是运行在machine上。说完原理,接下来做一下实操。

安装vmware支持

下载docker-machine-driver-vmwareworkstation.exe,然后放到Docker Toolbox目录下:

# C:\Program Files\Docker Toolbox
ls -1

boot2docker.iso
docker.exe*
docker-compose.exe*
docker-machine.exe*
docker-machine-driver-vmwareworkstation.exe*
docker-quickstart-terminal.ico
installers/
start.sh*
unins000.dat
unins000.exe*

并且把以下代码覆盖到目录下的start.sh文件里:

#!/bin/bash

export PATH="$PATH:/mnt/c/Program Files (x86)/VMware/VMware Workstation"

trap '[ "$?" -eq 0 ] || read -p "Looks like something went wrong in step ´$STEP´... Press any key to continue..."' EXIT

VM=${DOCKER_MACHINE_NAME-default}
DOCKER_MACHINE=./docker-machine.exe

BLUE='\033[1;34m'
GREEN='\033[0;32m'
NC='\033[0m'


if [ ! -f "${DOCKER_MACHINE}" ]; then
  echo "Docker Machine is not installed. Please re-run the Toolbox Installer and try again."
  exit 1
fi

vmrun.exe list | grep "${VM}" &> /dev/null
VM_EXISTS_CODE=$?

set -e

STEP="Checking if machine $VM exists"
if [ $VM_EXISTS_CODE -eq 1 ]; then
  "${DOCKER_MACHINE}" rm -f "${VM}" &> /dev/null || :
  rm -rf ~/.docker/machine/machines/"${VM}"
  #set proxy variables if they exists
  if [ -n ${HTTP_PROXY+x} ]; then
    PROXY_ENV="$PROXY_ENV --engine-env HTTP_PROXY=$HTTP_PROXY"
  fi
  if [ -n ${HTTPS_PROXY+x} ]; then
    PROXY_ENV="$PROXY_ENV --engine-env HTTPS_PROXY=$HTTPS_PROXY"
  fi
  if [ -n ${NO_PROXY+x} ]; then
    PROXY_ENV="$PROXY_ENV --engine-env NO_PROXY=$NO_PROXY"
  fi  
  "${DOCKER_MACHINE}" create -d vmwareworkstation $PROXY_ENV "${VM}"
fi

STEP="Checking status on $VM"
VM_STATUS="$(${DOCKER_MACHINE} status ${VM} 2>&1)"
if [ "${VM_STATUS}" != "Running" ]; then
  "${DOCKER_MACHINE}" start "${VM}"
  yes | "${DOCKER_MACHINE}" regenerate-certs "${VM}"
fi

STEP="Setting env"
eval "$(${DOCKER_MACHINE} env --shell=bash ${VM})"

STEP="Finalize"
clear
cat << EOF


                        ##         .
                  ## ## ##        ==
               ## ## ## ## ##    ===
           /"""""""""""""""""\___/ ===
      ~~~ {~~ ~~~~ ~~~ ~~~~ ~~~ ~ /  ===- ~~~
           \______ o           __/
             \    \         __/
              \____\_______/

EOF
echo -e "${BLUE}docker${NC} is configured to use the ${GREEN}${VM}${NC} machine with IP ${GREEN}$(${DOCKER_MACHINE} ip ${VM})${NC}"
echo "For help getting started, check out the docs at https://docs.docker.com"
echo
cd

docker () {
  MSYS_NO_PATHCONV=1 docker.exe "$@"
}
export -f docker

if [ $# -eq 0 ]; then
  echo "Start interactive shell"
  exec "$BASH" --login -i
else
  echo "Start shell with command"
  exec "$BASH" -c "$*"
fi

然后再次运行Docker Quickstart Terminal

docker-machine ls

NAME      ACTIVE   DRIVER              STATE     URL                          SWARM   DOCKER        ERRORS
default   *        vmwareworkstation   Running   tcp://192.168.163.130:2376           v18.02.0-ce

能看到DRIVER已替换为vmwareworkstation,然后就可以安心使用了。

一个需要注意的地方:使用vmware支持的不能使用Kitematic,打开将会重置你的整个服务然后将会还原为virtualbox

在任何地方使用docker

在使用上还存在些问题,像我在实际工作中需要在VSCode控制docker。目前这个方案会导致必须在Docker Quickstart Terminal的命令窗口下才能使用,这样严重影响使用体验。

如果你其他地方使用docker命令会得到以下反馈:

docker ps

error during connect: Get http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.35/containers/json: open //./pipe/docker_engine: The system cannot find the file specified. In the default daemon configuration on Windows, the docker client must be run elevated to connect. This error may also indicate that the docker daemon is not running.

经过多番查找得出解决办法:

在当前命令行注入DOCKER相关变量,让docker命令获得配置内容均可使用

步骤如下:

  1. 开机运行Docker Quickstart Terminal
  2. 打开命令行窗口然后运行以下代码:

    eval "$(docker-machine env default)"
  3. 就可以使用了

    docker ps
    
    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

如果还不行在当前命令行窗口输入以下代码,看是否为当前可用:

docker-machine env default

export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://192.168.163.130:2376"
export DOCKER_CERT_PATH="C:\Users\infzm-pc\.docker\machine\machines\default"
export DOCKER_MACHINE_NAME="default"
export COMPOSE_CONVERT_WINDOWS_PATHS="true"
# Run this command to configure your shell:
# eval $("C:\Program Files\Docker Toolbox\docker-machine.exe" env default)

如不可用请根据具体情况修改--shell参数,可选:bash, fish, cmd, powershell, tcsh

# 在git shell中
eval "$(docker-machine env --shell bash default)"

# 在cmd中
eval "$(docker-machine env --shell cmd default)"

出现一些异常

如你在初次使用或者pull镜像时出现以下错误,建议你pull镜像或者build之类的较为繁琐的内容还是于Docker Quickstart Terminal命令行窗口下运行。

Traceback (most recent call last):
  File "docker-compose", line 6, in <module>
  File "compose\cli\main.py", line 71, in main
  File "compose\cli\main.py", line 124, in perform_command
  File "compose\cli\main.py", line 959, in up
  File "compose\project.py", line 452, in up
  File "compose\service.py", line 324, in ensure_image_exists
  File "compose\service.py", line 972, in build
  File "compose\progress_stream.py", line 23, in stream_output
  File "compose\progress_stream.py", line 90, in print_output_event
  File "codecs.py", line 370, in write
  File "site-packages\colorama\ansitowin32.py", line 40, in write
  File "site-packages\colorama\ansitowin32.py", line 141, in write
  File "site-packages\colorama\ansitowin32.py", line 169, in write_and_convert
  File "site-packages\colorama\ansitowin32.py", line 174, in write_plain_text
IOError: [Errno 0] Error
Failed to execute script docker-compose

备注

在替换成vmware虚拟服务时start.sh插件提供的源代码会存在找不到machine的问题导致每次重启(宿主机)均从新安装一遍VM,导致本地镜像与容器全没了。目前贴的这份代码是已修复的,具体看pecigonzalo/docker-machine-vmwareworkstation/issues/31


帕奇式
924 声望71 粉丝

设计和管理是毕生的课题👨‍💻