容器具有自己的Network Namespace.
eht0是这个Network Namespace里的网络接口。而宿主机上也有自己的 eth0,宿主机上的 eth0 对应着真正的物理网卡,可以和外面通讯
要让容器 Network Namespace 中的数据包最终发送到物理网卡上,需要以下两步:
将数据包从容器的 Network Namespace 发送到 Host Network Namespace 上 数据包从宿主机的eth0发送出去 要想让容器从自己的Network Namespace连接到Host Namespace,一般来说就只有两类设备接口,一是veth,另外是macvlan/ipvlan.
veth是一个虚拟的网络设备,一般是成对建立,而且这对设备是相互连接的。当每个设备在不同的 Network Namespaces 的时候,Namespace 之间就可以用这对 veth 设备来进行网络通讯了。
到这里,解决了第一步,下一步需要将数据包从宿主机的eth0发送出去。
Docker 程序在节点上安装完之后,就会自动建立了一个 docker0 的 bridge interface。所以我们只需要把第一步中建立的 veth_host 这个设备,接入到 docker0 这个 bridge 上。
容器和docker0组成了一个子网,docker0上的IP就是这个子网的网关IP。
然后docekr0通过nat或route的方式,经过eth0将数据包向外发送。
Reference https://time.geekbang.org/column/article/323325
http://icyfenix.cn/immutable-infrastructure/network/linux-vnet.html
https://morven.life/posts/networking-4-docker-sigle-host/
https://network.51cto.com/article/708901.html
1. 分层的镜像 在我们启动一个容器之前,通常需要下载这个容器对应的镜像,以这个镜像为基础启动容器。镜像中包含了对应的程序的二进制文件与其所依赖的文件,程序在启动后看到的rootfs只是这个镜像中存在的文件。这样,我们就可以为容器中的进程提供一个干净的文件系统。
创建一个镜像(image)的最简单方法是使用Dockerfile。
FROMscratchCOPY hello /CMD ["/hello"]scratch是docker为我们提供的一个空镜像,我们可以在此基础上构建任何我们想要的镜像。
在书写Dockerfile时,想必你听说过这么一句话,不要在Dockerfile中创建太多层.
在Dockerfile中,每一个指令都会创建一个新的“层”,这里的层,指的是UnionFS中的一个文件目录。当我们创建了过多的层,会导致镜像体积变大,除此之外,Union FS 也会有最大层数限制。
因此对于如下的Dockerfile文件写法,应尽量避免:
FROMdebian:stretchRUN apt-get updateRUN apt-get install -y gcc libc6-dev make wgetRUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"RUN mkdir -p /usr/src/redisRUN tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1RUN make -C /usr/src/redisRUN make -C /usr/src/redis install可优化为如下写法
FROMdebian:stretchRUN set -x; buildDeps='gcc libc6-dev make wget' \ && apt-get update \ && apt-get install -y $buildDeps \ && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \ && mkdir -p /usr/src/redis \ && tar -xzf redis....