在 Linux Docker 容器中安装 Windows 虚拟机

不是,你们加群啊,群主一直以为我没推广呢

还有什么问题,想咨询的,加群:582337768。 这个群不是我的,但是我在里面,但是还是那句话,我也不懂。

arm的化,没研究,好像听说可以 arm虚拟化出x86,您有兴趣,可以自己研究一下。
这边的文档稍作补充,例如内核等
原链接的内容,可能会有些东西没补充,我

1 查看或开启虚拟化

我们需要检查我们的系统是否支持虚拟化。由于我们的容器将运行虚拟机管理程序,因此除非主平台支持虚拟化,否则它将无法工作。

物理机可以通过bios进行开启,虚拟机也需要开启。这个是虚拟化的内容,所以自行百度打开

sudo egrep -c '(vmx|svm)' /proc/cpuinfo

2 安装docker

自行安装。这里给个链接: 阿里云

3 内核可能需要的配置

内核得一致,由于docker是共享内核的操作,然后有些配置需要宿主机上进行操作。而容器内需要读内核,就需要内外两个版本一致。
所以什么操作系统,内核都需要一摸一样,才能在容器内开启虚拟机

# 查看运行内核
cat /proc/version
uname -r
apt-get update
# 安装最新版本
#apt-get install linux-image-generic
# 指定版本安装
apt-get install linux-image-4.15.0-213-generic
cat >> /etc/syscon.conf << EOF
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF

4.1 手动操作: 启动容器

其实就是挂载设备,打开网络权限和系统权限。毕竟你要装虚拟机,网络必须要打开的。

那这个网络是什么呢? 其实就是利用iptables进行 跳转。 例如 nat网络,桥接网络,仅主机网络。 如果不懂,还是继续百度去吧

docker run --privileged -it --name ubuntukvm -p 3389:3389 --device=/dev/kvm --device=/dev/net/tun -v /sys/fs/cgroup:/sys/fs/cgroup:rw --cap -add=NET_ADMIN --cap-add=SYS_ADMIN ubuntu:18.04 /bin/bash

容器内操作

apt-get update -y
apt-get install -y qemu-kvm libvirt-daemon-system libvirt-dev
chown root:kvm /dev/kvm
service libvirtd start
service virtlogd start
# 需要和宿主机内核一致
apt-get install -y linux-image-$(uname -r)
apt-get install curl net-tools jq -y

# 这里可能会失败,所以去github下载最新的dev版本  https://github.com/hashicorp/vagrant

vagrant_latest_version=$(curl -s https://checkpoint-api.hashicorp.com/v1/check/vagrant  | jq -r -M '.current_version')
echo $vagrant_latest_version
curl -O https://releases.hashicorp.com/vagrant/$(echo $vagrant_latest_version)/vagrant_$(echo $vagrant_latest_version)_x86_64.deb

dpkg -i vagrant_$(echo $vagrant_latest_version)_x86_64.deb
vagrant plugin install vagrant-libvirt

mkdir /win10

cd /win10

vagrant init peru/windows-10-enterprise-x64-eval
VAGRANT_DEFAULT_PROVIDER=libvirt vagrant up

vagrant rdp

# 下面开始搞网络了,反正挺恶心的

iptables-save > $HOME/firewall.txt
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT

# 我觉得下面的这些操作,挺烦的,直接上简单的
#iptables -I FORWARD  -j ACCEPT # 这个是我个人的操作,下面是根据文档。然而下面的使用的是 -A的操作,真实网络请求都走不到这里

iptables -A FORWARD -i eth0 -o virbr1 -p tcp --syn --dport 3389 -m conntrack --ctstate NEW -j ACCEPT
iptables -A FORWARD -i eth0 -o virbr1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -i virbr1 -o eth0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# 这个是开启外网访问虚拟机
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 3389 -j DNAT --to-destination 192.168.121.68
# 下面开启虚拟机请求外网,其中IP地址自己改一下
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables -t nat -A POSTROUTING -o virbr1 -p tcp --dport 3389 -d 192.168.121.68 -j SNAT --to-source 192.168.121.1

# 下面的内容,自己看内容吧   https://www.zsythink.net/archives/1684
iptables -D FORWARD -o virbr1 -j REJECT --reject-with icmp-port-unreachable
iptables -D FORWARD -i virbr1 -j REJECT --reject-with icmp-port-unreachable
iptables -D FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable
iptables -D FORWARD -i virbr0 -j REJECT --reject-with icmp-port-unreachable

4.2 dockerfile操作: 编写dockerfile进行操作

先复制过来,晚些时候在继续弄

cat > Dockerfile << \EOF
FROM ubuntu:18.04
RUN apt-get update -y
RUN apt-get install -y qemu-kvm libvirt-daemon-system libvirt-dev
# 这个内核需要和宿主机一致
RUN apt-get install -y linux-image-$(uname -r)
RUN apt-get install -y curl net-tools jq
RUN apt-get autoclean
RUN apt-get autoremove
RUN curl -O https://releases.hashicorp.com/vagrant/$(curl -s https://checkpoint-api.hashicorp.com/v1/check/vagrant  | jq -r -M '.current_version')/vagrant_$(curl -s https://checkpoint-api.hashicorp.com/v1/check/vagrant  | jq -r -M '.current_version')_x86_64.deb
RUN dpkg -i vagrant_$(curl -s https://checkpoint-api.hashicorp.com/v1/check/vagrant  | jq -r -M '.current_version')_x86_64.deb
RUN vagrant plugin install vagrant-libvirt
RUN vagrant box add --provider libvirt peru/windows-10-enterprise-x64-eval
RUN vagrant init peru/windows-10-enterprise-x64-eval
COPY Vagrantfile /Vagrantfile
COPY startup.sh /
ENTRYPOINT ["/startup.sh"]
EOF

Vagrantfile: 主要是配置一下cpu和内存

# -*- mode: ruby -*-
# vi: set ft=ruby :

# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility). Please don't change it unless you know what
# you're doing.
Vagrant.configure("2") do |config|
  # The most common configuration options are documented and commented below.
  # For a complete reference, please see the online documentation at
  # https://docs.vagrantup.com.

  # Every Vagrant development environment requires a box. You can search for
  # boxes at https://vagrantcloud.com/search.
  config.vm.box = "mybox"
  # Disable automatic box update checking. If you disable this, then
  # boxes will only be checked for updates when the user runs
  # `vagrant box outdated`. This is not recommended.
  # config.vm.box_check_update = false

  # Create a forwarded port mapping which allows access to a specific port
  # within the machine from a port on the host machine. In the example below,
  # accessing "localhost:8080" will access port 80 on the guest machine.
  # NOTE: This will enable public access to the opened port
  # config.vm.network "forwarded_port", guest: 80, host: 8080

  # Create a forwarded port mapping which allows access to a specific port
  # within the machine from a port on the host machine and only allow access
  # via 127.0.0.1 to disable public access
  # config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1"

  # Create a private network, which allows host-only access to the machine
  # using a specific IP.
  # config.vm.network "private_network", ip: "192.168.33.10"

  # Create a public network, which generally matched to bridged network.
  # Bridged networks make the machine appear as another physical device on
  # your network.
  # config.vm.network "public_network"

  # Share an additional folder to the guest VM. The first argument is
  # the path on the host to the actual folder. The second argument is
  # the path on the guest to mount the folder. And the optional third
  # argument is a set of non-required options.
  # config.vm.synced_folder "../data", "/vagrant_data"

  # Disable the default share of the current code directory. Doing this
  # provides improved isolation between the vagrant box and your host
  # by making sure your Vagrantfile isn't accessable to the vagrant box.
  # If you use this you may want to enable additional shared subfolders as
  # shown above.
  # config.vm.synced_folder ".", "/vagrant", disabled: true

  # Provider-specific configuration so you can fine-tune various
  # backing providers for Vagrant. These expose provider-specific options.
  # Example for VirtualBox:
  #
  config.vm.provider :libvirt do |libvirt|
  #   # Display the VirtualBox GUI when booting the machine
  #   vb.gui = true
  #
  #   # Customize the amount of memory on the VM:
    libvirt.memory = "10240"
    libvirt.cpus = 4
    # libvirt.storage :file, :size => '5G', :type => 'raw', :bus => 'scsi'
  end
  #
  # View the documentation for the provider you are using for more
  # information on available options.

  # Enable provisioning with a shell script. Additional provisioners such as
  # Ansible, Chef, Docker, Puppet and Salt are also available. Please see the
  # documentation for more information about their specific syntax and use.
  # config.vm.provision "shell", inline: <<-SHELL
  #   apt-get update
  #   apt-get install -y apache2
  # SHELL
end

startup.sh

#!/bin/bash
set -eou pipefail

chown root:kvm /dev/kvm
service libvirtd start
service virtlogd start

if [ -n $CPU ]; then sed -i "s/libvirt.cpus = 4/libvirt.cpus = $CPU/g" /Vagrantfile; fi
if [ -n $MEM ]; then sed -i "s/libvirt.memory = \"10240\"/libvirt.memory = \"$MEM\"/g" /Vagrantfile; fi

VAGRANT_DEFAULT_PROVIDER=libvirt vagrant up

# 此处Vagrantfile未设置hostname,所以默认为ip地址
# todo: 此处只支持一台虚拟机。多台后续完善
ip=`vagrant ssh-config | grep HostName | awk -F " " '{print $2}'`
inet=`echo ${ip} | sed 's/\([0-9]\+\.[0-9]\+\.[0-9]\+\)\..*/\1.1/'`
echo NAT Info: ${ip} ${inet}

iptables-save > $HOME/firewall.txt
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT

iptables -I FORWARD -j ACCEPT
iptables -A FORWARD -i eth0 -o virbr1 -p tcp --syn --dport 3389 -m conntrack --ctstate NEW -j ACCEPT
iptables -A FORWARD -i eth0 -o virbr1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -i virbr1 -o eth0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# 外网访问虚拟机
iptables -t nat -I PREROUTING -i eth0 -p tcp --dport 3389 -j DNAT --to-destination ${ip}
# 虚拟机添加连接外网
# 这个就是允许服务器访问IP外网。就是访问自己以外的IP地址   snat模式
iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE
iptables -t nat -I POSTROUTING -o virbr1 -p tcp --dport 3389 -d ${ip} -j SNAT --to-source ${inet}

iptables -D FORWARD -o virbr1 -j REJECT --reject-with icmp-port-unreachable
iptables -D FORWARD -i virbr1 -j REJECT --reject-with icmp-port-unreachable
iptables -D FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable
iptables -D FORWARD -i virbr0 -j REJECT --reject-with icmp-port-unreachable

bash 
exec "$@"

5 远程连接

账号: vagrant
密码: vagrant

参考文档:

posted @ 2023-09-15 09:58  汉克书  阅读(1112)  评论(0编辑  收藏  举报