在 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
参考文档: