OpenVZ6: https://wiki.openvz.org/Docker_inside_CT OpenVZ7: https://wiki.openvz.org/Docker_inside_CT_vz7 Docker是一种近年来流行的容器技术，可以快速的部署服务，免去配置运行环境的烦恼。但是可惜的是，Docker对Linux系统高版本的内核特性有一定的依赖，尽管官方在较新的OpenVZ6中提供了对Docker的支持，但是一方面这种支持仅限于较老版本的Docker(<=1.10)，且存在一定的兼容性问题；另一方面许多VPS服务提供商出于稳定性考虑并不愿意升级系统版本或为用户配置Docker支持。 但是在OpenVZ7中，官方对Docker提供了完整支持（虽然目前仍然是实验性特性，建议不要用于生产环境中），只需要挂载veth和overlay这两个内核模块即可。之后在OpenVZ虚拟机中，可以直接按照Docker官方提供的安装脚本或安装指南进行安装和部署。 另外作为Bonus，在开启了这两个模块支持后，OpenVZ虚拟机中也可以利用lxc来进行再次虚拟化。 常见问题： 如果在使用脚本或按照只能安装Docker时提示Docker运行失败，可能是宿主机未进行响应设置，可以通过工单的方式和服务提供商沟通要求添加Docker支持。
LXC 是 Linux Container 的缩写，类似虚拟化技术中的 OpenVZ，是一种半虚拟化技术，可以提供一个和宿主机相对隔绝的沙盒环境。在容器中安装的各种软件不会影响到宿主机，同时也可以通过配置容器的资源限制，来保证容器中运行的软件不会占用过多资源。 前言 LXC 的安装 网络配置 宿主机的网络配置 为容器配置NAT网络 创建容器 配置容器 限制容器的 CPU 和内存占用 限制容器的磁盘大小 通过 iptables 进行端口转发 LXC 常用命令 一个用于创建 LXC 容器的 Python 脚本 前言 与 Docker 不同，LXC 和 OpenVZ 会保留用户操作的状态，而 Docker 则是提供一个无状态的预部署的容器，只有映射出来的文件才会得到保存。 许多优秀的管理面板提供了管理 LXC/OpenVZ 容器的功能，比如 Proxmox 等，但是由于管理面板的内存占用较高（纯净的 Debian9.4 镜像安装 Proxmox 后占用约 660MB 的内存），不适合小内存的机器，因此我选择 lxc 提供的使用命令行工具来对容器进行管理。 本文将主要包括如下内容： 创建 LXC 容器 限制 LXC 容器可用的资源（CPU，内存，磁盘等） 配置 LXC 容器的网络，且为 LXC 容器提供端口映射。 本文介绍的内容主要适用于如下两种情况： 内存较小的机器上无面板使用 lxc 虚拟化以节省内存消耗 面板出现 bug 时使用命令行工具排查错误 注：本文根据 Debian9.4 环境撰写，其余发行版那请自行调整相关命令。 LXC 的安装 对于比较新的 Debian 系统来说，安装 lxc 就是一句话 apt install lxc 网络配置 宿主机的网络配置 首先对宿主机进行网络配置，配置的目标是创建一个网桥及相关的 iptables 命令，实现 NAT 功能。 首先配置网桥，需要在网络配置文件（/etc/network/interfaces）中添加如下内容即可 重要：记得检查你的网络接口是否为eth0，如果不是则需要修改配置文件的最后两行。 auto vmbr0 iface vmbr0 inet static address 192.168.45.1 netmask 255.255.255.0 bridge_ports none bridge_stp off bridge_fd 0 post-up echo 1 > /proc/sys/net/ipv4/ip_forward post-up iptables -t nat -A POSTROUTING -s '192.168.45.0/24' -o eth0 -j MASQUERADE post-down iptables -t nat -D POSTROUTING -s '192.168.45.0/24' -o eth0 -j MASQUERADE 其次配置 /etc/default/lxc-net 文件（没有的话创建一个）。 USE_LXC_BRIDGE="true" LXC_BRIDGE="vmbr0" LXC_ADDR="192.168.45.1" LXC_NETMASK="255.255.255.0" LXC_NETWORK="192.168.45.0/24" LXC_DHCP_RANGE="192.168.45.150,192.168.45.200" LXC_DHCP_MAX="51" LXC_DHCP_CONFILE="" LXC_DOMAIN="" 重启lxc-net及网络服务。 systemctl restart lxc-net.service systemctl restart networking.service reboot # 或者直接重启系统 为容器配置NAT网络 首先修改配置文件让容器通过刚才创建的 NAT 网络连接互联网。 如果准备让所有的容器都使用该网络配置，可以修改默认的配置文件 /etc/lxc/default.conf，如果只打算修改个别容器的配置，可以在 /var/lib/lxc/<容器名>/config 找到个别容器的配置文件。 ## Network lxc.network.type = veth lxc.network.flags = up lxc.network.link = vmbr0 ## xx代表随机生成，每次重启都会有所变化 lxc.network.hwaddr = 00:16:3e:xx:xx:xx # 如果个别容器，可以指定 IP 地址及网关 lxc.network.ipv4 = 192.168.45.101/24 lxc.network.ipv4.gateway = 192.168.45.1 另外需要注意的是，部分容器模板是不包含任何 DNS 设定的，需要手动在容器内 /etc/resolv.conf 中指定 DNS 服务器： nameserver 8.8.8.8 nameserver 8.8.4.4 创建容器 创建容器用的是 lxc-create 命令，最常见的创建方式包含两个参数： # 使用 模板创建名为 <name> 的容器 lxc-create -t -n <name> 如果你有提前编写完成的配置文件，可以通过 -f 参数指定 # 使用 模板及 <config_file> 配置文件，创建名为 <name> 的容器 lxc-create -t -f <config_file> -n <name> 不同的模板拥有不同的参数，可以通过如下命令查询： # 查看 模板的更多参数 lxc-create -t -h lxc-create 创建的容器需要通过 lxc-start -n <name> 启动。 自动启动需要在容器的配置文件里面加入指定参数： lxc.start.auto = 1 配置容器 接下来要做的是修改容器的配置文件，LXC 容器的配置文件在 /var/lib/lxc/<容器名>/config。 限制容器的 CPU 和内存占用 创建容器之后，默认容器可以使用全部的资源，需要修改容器的配置文件才能限制容器的资源使用。对配置文件的修改本质上是通过 cgroups 来限制容器的使用，具体的参数可以参考 cgroups 的参数。 Arch Wiki 提供了一个 cgroups 的详细介绍 一个典型的资源限制配置文件包含如下内容： # 可使用内存量 lxc.cgroup.memory.limit_in_bytes = 512M # 突发内存量 = 可用内存 + swap # 该选项需对 grub 参数进行设置 # 可以参考 https://github.com/yudai/cf_nise_installer/issues/124 # 执行如下命令即可 # sudo echo "GRUB_CMDLINE_LINUX=\"cgroup_enable=memory swapaccount=1\"" >> /etc/default/grub # sudo /usr/sbin/update-grub lxc.cgroup.memory.memsw.limit_in_bytes = 1G # CPU 核心数量 # 可以通过具体的数字精确指定占用的 CPU 核心编号 # 示例代表可以使用 1 2 3 4 号 CPU 核心。 lxc.cgroup.cpuset.cpus = 1,2-4 # CPU 资源占用比例 lxc.cgroup.cpu.shares = 1024 除了修改配置文件，也可以通过命令行直接指定 cgroup 参数，如： # 仅允许名为 lxc_name 容器使用 CPU 的核心 1 lxc-cgroup -n lxc_name cpuset.cpus "1" 限制容器的磁盘大小 具体可以参考 man lxc-create 中 -B 参数的部分，在这里简单的提供一个命令对虚拟机进行限制。 注： loop 并不是最佳的参数，更好的方法是使用 lvm，但是这对磁盘分区有要求。 # 限制磁盘大小 5GB lxc-create -n <name> -t -B loop --fssize 5G 通过 iptables 进行端口转发 具体可以参考 这篇教程，只需要将转发的目标 IP 设置为容器的子网 IP 即可。 这里提供一个脚本来辅助设置端口转发。 # 保存为 nat.sh #!/bin/bash dev="ens3" # 修改成网络接口的名字 user_ip="192.168.45.$1" # iptables -t nat -A POSTROUTING -d ${user_ip} -j SNAT --to-source ${main_ip} iptables -t nat -A PREROUTING -i $dev -p tcp -m tcp --dport ${1}22 -j DNAT --to-destination ${user_ip}:22 iptables -t nat -A PREROUTING -i $dev -p tcp -m tcp --dport ${1}00:${1}20 -j DNAT --to-destination ${user_ip} iptables -t nat -A PREROUTING -i $dev -p udp -m udp --dport ${1}00:${1}20 -j DNAT --to-destination ${user_ip} echo -e "done." 使用脚本时需要根据上文中提到的内容对脚本进行微调， bash nat.sh 101 未曾修改脚本的情况下，这个命令代表将 192.168.45.101 的 22 端口转发到主机的 10122 端口，并把 192.168.45.101 的 10100~10120 端口转发到主机的 10100~10120 端口。 配置完成后可以通过 ssh <宿主机IP> -p 10122 来访问容器的22端口。 注：容器需处于启动状态，且安装 openssh-server 并监听 22 端口。 LXC 常用命令 # 创建容器 lxc-create -t -n <name> # 启动容器 lxc-start -n <name> # 停止容器 lxc-stop -n <name> # 进入容器 lxc-attach -n <name> # 查看所有容器，可通过参数指定只查看特定状态的容器 lxc-ls # 查看容器信息 lxc-info -n <name> # 查看容器中的进程 lxc-ps -n <name> 一个用于创建 LXC 容器的 Python 脚本 TODO