1、Linux 容器

虚拟机的快照是一种带环境安装的解决方案,但是每个虚拟机需要包含完整的操作系统,资源占用比较笨重、启动较慢,因此发展了另一种虚拟化技术:容器。

1.1 容器是什么?

容器不是模拟一个完整的操作系统,而是对进程进行隔离,其中使用的技术就是 Linux namespace。对于一个容器内的进程,他接触的资源就像是独享的一样,实际在底层是进行隔离的,而且由于是进程级别的,启动更快、占用资源更少、本身体积也小。

Docker 就是将应用程序和程序的依赖打包到同一个文件中,就是 build image,运行时就会生成一个 Docker 的容器,程序在这个虚拟容器中运行就像在物理机或虚拟机中运行一样。

容器和虚拟机都是虚拟化技术实现,这里不得不谈一下他们的区别:最大的区别就是容器没有 Guest OS(客户虚拟机)这一层,而且可以发现也没有 Hypervisor 这一层,取而代之的是 Docker 这个封装调用,但是 Docker 只是将 Linux 内核进行封装调用,实际的虚拟支持还是由 Linux 来提供的,这也就意味着相对于 Hypervisor 而言更加的轻量。但是 Guest OS 的存在能为应用提供一个更加隔离和安全的环境,不会因为程序的漏洞而对宿主机造成任何威胁。

1.2 四大网络模式

从网络的角度看容器,就是 network namespace+ 容器的组网方案了,容器具有完全独立的网络栈,与宿主机隔离。网络方案分为单个部分:单机的容器间通信、跨主机的容器间通信、容器与主机间通信。

Docker 在启动时可以使用 --network 指定容器的网络模式,有下面四种可以指定:bridge、host、container、none。在 Docker 安装完成之后就会默认创建三个网络,bridge、host 和 none,可以通过 docker network ls 查看到。

  • Bridge:Docker 在安装之后会有一个 docker0 的 Linux 网桥被创建,是默认的网络模式,在不指定网络模式的情况下,创建的容器会自动分配 ns 并且连接到该网桥上面。默认情况下 docker0 的 IP 地址为 172.17.0.1(可配置),而接到此网桥上面的容器 IP 范围是 172.17.0.0/24。并且默认网关都是 docker0,即要访问非本机容器网段都需要通过此网桥进行转发,而同主机上的容器则使用广播进行通信。bridge 模式为 Docker 容器创建独立的网络栈,保证容器内的进程使用独立的网络环境,是容器和容器、容器和宿主机之间实现网络隔离。

  • Host:连接到 host 网络的容器不会独立 namespace 而是同宿主机共用一个 network namespace,包括 IP 和端口都使用宿主机的。共用的方式很方便但是也有缺点:一是容器没有隔离独立的网络栈,容器造成网络的争,容器的崩溃也有可能使主机崩溃;二是会造成端口的冲突,就不能再开两个 80 端口来启动容器了。

  • Container:使用 --network=container:name or id 指定一个已经存在的容器共享网络命名空间,但是其他的如文件系统、进程列表还是隔离的,两个容器可以使用回环网卡设备通信。

  • None:这种模式容器拥有自己的 network namesoace,但是没有任何的网络配置,也就是完全封闭的内部网络。

2、奇淫巧技

简单介绍 Docker 中的网络配置,网路端口映射、容器互联、DNS 配置等知识,默认使用 bridge 作为组网模式。

2.1 查看端口 IP

一般查看有两种方式,从宿主机外部看和从容器内部看。

docker inspect -f  "{{ .NetworkSetting.IPAddress }}" <containerNameOrId>
# docker inspect <containerNameOrId> | grep '"IPAddress"' | head -n 1

从外部就是利用 inspect 命令查看容器的详细信息来过滤我们的 IP 数据。从内部看就比较简单了,通过 exec 或者 attach 进入到容器中,再使用 ip、ifconfig 来查看即可。

一般情况下 IP 地址的分配是从 127.17.0.1/16 开始的,依次往下进行分配。

2.2 端口映射

使用 Docker run 的时候添加 -P / -p 参数,可以指定映射端口,前者默认生成 49000/49900 映射到容器内部开放端口,后者需要通过 hostport:containerport 的方式指定。

映射原理都是在本地 iptable 的 net 表中添加响应的规则,将访问本机端口的网包进行一次 DNAT 转换成容器的端口,可以通过 iptables 得到验证。

docker port <container> <port> # 查看容器端口在主机上面的映射