h
一、 Docker 中的网络功能介绍
默认情况下,容器可以建立到外部网络的连接,但是外部网络无法连接到容器。
Docker 允许通过外部访问容器或容器互联的方式来提供网络服务
外部访问容器:
容器中可以运行一些网络应用,要让外部也可以访问这些应用,可以通过 -P 或 -p 参数来指定端口映射。
构建镜像模板
1) 创建一个sshd_dockerfile工作目录
<code>[root@localhost ~]</code><code># mkdir sshd_dockerfile</code>
<code>[root@localhost ~]</code><code># cd sshd_dockerfile/</code>
<code>[root@localhost sshd_dockerfile]</code><code># touch dockerfile run.sh</code>
<code>[root@localhost sshd_dockerfile]</code><code># ls</code>
<code>dockerfile run.sh</code>
编辑run.sh文件
<code>[root@localhost sshd_dockerfile]</code><code># cat run.sh </code>
<code>#!/bin/bash</code>
<code>/usr/sbin/sshd</code>
<code>/usr/sbin/httpd</code> <code>-DFOREGROUND</code>
在主机上生成ssh秘钥对,并创建authorized_keys文件
<code>[root@localhost sshd_dockerfile]</code><code># ssh-keygen -t rsa</code>
<code>Generating public</code><code>/private</code> <code>rsa key pair.</code>
<code>Enter </code><code>file</code> <code>in</code> <code>which</code> <code>to save the key (</code><code>/root/</code><code>.</code><code>ssh</code><code>/id_rsa</code><code>): </code>
<code>Created directory </code><code>'/root/.ssh'</code><code>.</code>
<code>Enter passphrase (empty </code><code>for</code> <code>no passphrase): </code>
<code>Enter same passphrase again: </code>
<code>[root@localhost sshd_dockerfile]</code><code># cat ~/.ssh/id_rsa.pub > /root/sshd_dockerfile/authorized_keys</code>
<code>[root@localhost sshd_dockerfile]</code><code># cat dockerfile </code>
<code>FROM docker.wang.com</code><code>/centos</code><code>:centos7</code>
<code>MAINTAINER from [email protected]</code>
<code>RUN yum -y </code><code>install</code> <code>openssh-server </code><code>sudo</code> <code>httpd</code>
<code>RUN </code><code>useradd</code> <code>admin</code>
<code>RUN </code><code>echo</code> <code>"admin:admin"</code> <code>| chpasswd</code>
<code>RUN </code><code>echo</code> <code>"admin ALL=(ALL) ALL"</code> <code>>> </code><code>/etc/sudoers</code>
<code>RUN </code><code>ssh</code><code>-keygen -t dsa -f </code><code>/etc/ssh/ssh_host_dsa_key</code>
<code>RUN </code><code>ssh</code><code>-keygen -t rsa -f </code><code>/etc/ssh/ssh_host_rsa_key</code>
<code>RUN </code><code>mkdir</code> <code>-p </code><code>/var/run/sshd</code>
<code>RUN </code><code>mkdir</code> <code>-p </code><code>/home/admin/</code><code>.</code><code>ssh</code>
<code>RUN </code><code>sed</code> <code>-ri </code><code>'s/session required pam_loginuid.so/#session required pam_loginuid.so/g'</code> <code>/etc/pam</code><code>.d</code><code>/sshd</code>
<code>ADD authorized_keys </code><code>/home/admin/</code><code>.</code><code>ssh</code><code>/authorized_keys</code>
<code>RUN </code><code>sed</code> <code>-ri </code><code>'s/#ServerName www.example.com:80/ServerName www.benet.com/g'</code> <code>/etc/httpd/conf/httpd</code><code>.conf</code>
<code>ADD run.sh </code><code>/run</code><code>.sh</code>
<code>RUN </code><code>chmod</code> <code>755 </code><code>/run</code><code>.sh</code>
<code>EXPOSE 22 80 443</code>
<code>CMD [</code><code>"/bin/bash"</code><code>,</code><code>"/run.sh"</code><code>]</code>
二载入centos包
<code>[root@localhost src]</code><code># docker load < centos7.tar</code>
<code>0fe55794a0f7: Loading layer [==================================================>]</code>
1)在sshd_dockerfile目录下,使用docker build命令来创建镜像,注意:在最后还有一个”.”,表示使用当前目录中的dockerfile
<code>[root@localhost sshd_dockerfile]</code><code># docker build -t centos:http .</code>
<code>Sending build context to Docker daemon 4.608 kB</code>
<code>Step 1 : FROM docker.wang.com</code><code>/centos</code><code>:centos7</code>
<code> </code><code>---> 50dae1ee8677</code>
<code>Step 2 : MAINTAINER from [email protected]</code>
<code> </code><code>---> Using cache</code>
<code> </code><code>---> 62fedfca03bd</code>
当使用–P(大写)标记时,Docker 会随机映射一个随机的端口到内部容器开放的网络端口。
注:-P使用时需要指定--expose选项或dockerfile中用expose指令容器要暴露的端口,指定需要对外提供服务的端口
使用 docker ps 可以看到,本地主机的32770被映射到了容器的22端口,本地主机的32769被映射到了容器的80端口,本地主机的32768被映射到了容器的443 端口。
<code>[root@localhost sshd_dockerfile]</code><code># docker run -d -P centos:http</code>
<code>131e12661bc10f0bc441784d64e65038ac0263d6beff1d55bf2cd28d4082c948</code>
<code>[root@localhost sshd_dockerfile]</code><code># docker ps</code>
<code>CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES</code>
<code>131e12661bc1 centos:http </code><code>"/bin/bash /run.sh"</code> <code>22 seconds ago Up 21 seconds 0.0.0.0:32770->22</code><code>/tcp</code><code>, 0.0.0.0:32769->80</code><code>/tcp</code><code>, 0.0.0.0:32768->443</code><code>/tcp</code> <code>trusting_rosalind</code>
此时访问本机的 32770端口即可访问容器内 ssh 应用
<code>[root@localhost sshd_dockerfile]</code><code># ssh [email protected] -p 32770</code>
<code>The authenticity of host </code><code>'[192.168.100.46]:32770 ([192.168.100.46]:32770)'</code> <code>can't be established.</code>
<code>Are you sure you want to </code><code>continue</code> <code>connecting (</code><code>yes</code><code>/no</code><code>)? </code><code>yes</code>
注:192.168.1.102是宿主主机地址。
查看容器运行的httpd进程
<code>[admin@131e12661bc1 ~]$ pgrep httpd</code>
<code>7</code>
<code>8</code>
<code>9</code>
<code>10</code>
<code>11</code>
<code>12</code>
此时访问本机的 32769端口即可访问容器内 web 应用
-p(小写)则可以指定要映射的端口,并且,在一个指定端口上只可以绑定一个容器。支持的格式有ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort
注意:
容器有自己的内部网络和 ip 地址(使用 docker inspect 可以获取所有的变量。)
-p 标记可以多次使用来绑定多个端口
<code>[root@localhost sshd_dockerfile]</code><code># docker run -d -p 10111:22 -p 801:80 centos:http</code>
<code>e0c4edcb03ed524d6d9ebfeac62178761910719e3eac7f6e7058cf0e655e8636</code>
<code>e0c4edcb03ed centos:http </code><code>"/bin/bash /run.sh"</code> <code>16 seconds ago Up 15 seconds 443</code><code>/tcp</code><code>, 0.0.0.0:10111->22</code><code>/tcp</code><code>, 0.0.0.0:801->80</code><code>/tcp</code> <code>grave_albattani</code>
<code>131e12661bc1 centos:http </code><code>"/bin/bash /run.sh"</code> <code>5 minutes ago Up 5 minutes 0.0.0.0:32770->22</code><code>/tcp</code><code>, 0.0.0.0:32769->80</code><code>/tcp</code><code>, 0.0.0.0:32768->443</code><code>/tcp</code> <code>trusting_rosalind</code>
测试访问:
1) ssh测试:
使用xshell工具: 账号密码为 admin
<a href="https://s1.51cto.com/wyfs02/M01/00/5C/wKiom1ma212iJDDPAABVXHdrYXU463.png-wh_500x0-wm_3-wmp_4-s_3251043453.png" target="_blank"></a>
测试web访问
<a href="https://s2.51cto.com/wyfs02/M01/00/5C/wKiom1ma223jHAckAAGAUEtWubY962.png-wh_500x0-wm_3-wmp_4-s_3354350372.png" target="_blank"></a>
映射到指定地址的指定端口
可以使用 ip:hostPort:containerPort 格式,指定映射使用一个特定地址,比如宿主机网卡配置的一个地址192.168.100.46
<code>root@localhost sshd_dockerfile]</code><code># docker run -dit -p 192.168.100.46:10112:22 -p 192.168.100.46:800:80 centos:http</code>
<code>fd41ea4d576f9a337df993b1e39db40274a16289eda134646abd385138216b0f</code>
1. 映射到指定地址的任意端口
<code>[root@localhost sshd_dockerfile]</code><code># docker run -d -p 192.168.100.46::80 --name webserver centos:http</code>
<code>c15abaf81039fb58f3104e7a8d6f854f640cc2ea8ed67615a8388866abf0c649</code>
1 udp端口
<code>[root@localhost sshd_dockerfile]</code><code># docker run -d -p 192.168.100.46:5000:5000/udp --name db4 centos:http</code>
<code>fadedde03f89a235e6cf7dd5412dba7a6870844625d498290126c05e68961335</code>
1. 端口端口映射配置
<code>[root@localhost sshd_dockerfile]</code><code># docker port webserver</code>
<code>80</code><code>/tcp</code> <code>-> 192.168.100.46:32771</code>
Docker NAT iptables实现
默认情况下,容器可以主动访问到外部网络的连接,但是外部网络无法访问到容器
容器访问外部实现
容器所有到外部网络的连接,源地址都会被 NAT 成本地系统的 IP 地址(即docker0地址)。这是使用 iptables 的源地址伪装操作实现的
查看主机的 NAT 规则
<code>[root@localhost sshd_dockerfile]</code><code># iptables -t nat -vnL</code>
<code>Chain PREROUTING (policy ACCEPT 3 packets, 234 bytes)</code>
<code> </code><code>pkts bytes target prot opt </code><code>in</code> <code>out </code><code>source</code> <code>destination </code>
<code> </code><code>242 19323 PREROUTING_direct all -- * * 0.0.0.0</code><code>/0</code> <code>0.0.0.0</code><code>/0</code>
外部访问容器实现
容器允许外部访问,可以在 docker run 时候通过 -p 或 -P 参数来启用,不管用那种办法,其实也是在本地的 iptable 的nat 表中添加相应的规则
使用 -P 时:
<code>f2f3ca6d96693b2223d4011e770c3d2b8359219f13e5e617f2263a6bc4298f18</code>
docker0 网桥
Docker服务默认会创建一个 docker0 网桥(其上有一个 docker0 内部接口),它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。
<code>[root@localhost ~]</code><code># brctl show</code>
<code>bridge name bridge </code><code>id</code> <code>STP enabled interfaces</code>
<code>docker0 8000.02429a3b4e3e no veth3855536</code>
注意(brctl可以使用yum install bridge-utils)
容器
<code>[root@localhost ~]</code><code># docker exec -it e0c4edcb03ed /bin/bash</code>
<code>[root@e0c4edcb03ed /]</code><code># </code>
<code>[root@e0c4edcb03ed /]</code><code># sudo yum -y install iproute</code>
进入运行的容器使用exec;之后安装iproute包。
<code>[root@e0c4edcb03ed /]</code><code># ip r</code>
<code>default via 172.17.0.1 dev eth0 </code>
<code>172.17.0.0</code><code>/16</code> <code>dev eth0 proto kernel scope link src 172.17.0.3</code>
会看到容器的ip/默认网关。
Docker 网络配置
Docker 四种网络模式
docker run 创建 Docker 容器时,可以用 --net 选项指定容器的网络模式,Docker 有以下 4 种网络模式:
· host 模式,使用 --net=host 指定。
· container 模式,使用 --net=container:NAMEorID 指定。
· none 模式,使用 --net=none 指定。
· bridge 模式,使用 --net=bridge 指定,默认设置。
如果启动容器的时候使用 host 模式,那么这个容器将不会获得一个独立的 Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的 IP 等,而是使用宿主机的 IP 和端口。
查看httpd进程
<code>[root@localhost ~]</code><code># pgrep httpd</code>
启动容器 host模式
<code>root@localhost sshd_dockerfile]</code><code># docker run -dit --net=host centos:http</code>
<code>b4f57f10bbc3da6aeefaf435613f7832d152d60cd971613e7d8da30b3b5b2c29</code>
放行80端口
<code>[root@localhost sshd_dockerfile]</code><code># firewall-cmd --add-port=80/tcp</code>
<code>success</code>
这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。
运行一个容器:查看容器的IP
<code>root@localhost sshd_dockerfile]</code><code># docker run -it docker.wang.com/centos:centos7</code>
<code>[root@17cd70302107 /]</code><code>#</code>
将容器切换到后台运行:ctrl+p ctrl+q
在运行一个容器使用container模式:查看新容器的地址
docker run -it --ent=container:d86194948685(上个容器id) 镜像名
查看ip,发现与上个容器ip一致。
1. none模式(容器拥有自己的Network namespace)
需自己为容器添加网卡、配置ip等。
2. bridge模式(docker0网卡、桥接到容器的网卡。)
所有的veth*的接口都会桥接到docker0(虚拟共享网)
<a href="https://s3.51cto.com/wyfs02/M00/9F/0C/wKioL1ma3KzDCjyTAAEev0Y3vAQ029.png-wh_500x0-wm_3-wmp_4-s_2761375797.png" target="_blank"></a>
查看桥接网络的详细信息
<code>[root@localhost sshd_dockerfile]</code><code># docker network inspect</code>
<a href="https://s3.51cto.com/wyfs02/M00/00/5C/wKiom1ma3PeyhwLJAAAijPSr6hs687.png-wh_500x0-wm_3-wmp_4-s_389056282.png" target="_blank"></a>
除了默认的 docker0 网桥,用户也可以指定网桥来连接各个容器。在启动 Docker 服务的时候,使用 -b BRIDGE 或 --bridge=BRIDGE 来指定使用的网桥。
Docker 允许你管理 docker0 桥接或者通过-b选项自定义桥接网卡,需要安装bridge-utils软件包。
基本步骤如下:
1.确保 docker 的进程是停止的
2.创建自定义网桥
3.给网桥分配特定的 ip
4.以 -b 的方式指定网桥
如果服务已经运行,那需要先停止服务,并删除旧的网桥
<code>[root@localhost sshd_dockerfile]</code><code># systemctl stop docker</code>
<code>[root@localhost sshd_dockerfile]</code><code># ip link set dev docker0 down</code>
<code>[root@localhost sshd_dockerfile]</code><code># brctl delbr docker0</code>
<code>[root@localhost sshd_dockerfile]</code><code># brctl show</code>
<code>virbr0 8000.000000000000 </code><code>yes</code>
1. 创建网桥,分配ip。
<code>[root@localhost sshd_dockerfile]</code><code># brctl addbr bridge0</code>
<code>[root@localhost sshd_dockerfile]</code><code># ip addr add 192.168.1.1/24 dev bridge0</code>
<code>[root@localhost sshd_dockerfile]</code><code># ip link set dev bridge0 up</code>
查看确认网桥成功与否
<code>bridge0 8000.000000000000 no </code>
<a href="https://s4.51cto.com/wyfs02/M01/9F/0C/wKioL1ma3Tbg0zIgAAAhCqBcK9o424.png-wh_500x0-wm_3-wmp_4-s_2831328041.png" target="_blank"></a>
1. 修改/etc/sysconfig/docker文件。
<a href="https://s4.51cto.com/wyfs02/M02/00/5C/wKiom1ma3U_iCb1mAAAgvMotc_w176.png-wh_500x0-wm_3-wmp_4-s_3790175569.png" target="_blank"></a>
1. 启动服务。
<code>[root@localhost sshd_dockerfile]</code><code># systemctl start docker</code>
1. 新建容器。
<a href="https://s2.51cto.com/wyfs02/M02/9F/0C/wKioL1ma3WXwpFlyAAAjWhkDW3g646.png-wh_500x0-wm_3-wmp_4-s_2108289559.png" target="_blank"></a>
1. 进入容器查看。
<code>[root@localhost sshd_dockerfile]</code><code># docker attach 1481b536c081462aade6e8c7b590142057e6fb29a649011a983672044ea8b609</code>
<code>[root@1481b536c081 /]</code><code># yum -y install iproute</code>
<code>[root@localhost sshd_dockerfile]</code><code># 'rpm' -qf `which ifconfig`</code>
<code>net-tools-2.0-0.17.20131004git.el7.x86_64</code>
查询下ifconfig命令所需软件包
<code>[root@1481b536c081 /]</code><code># yum -y install net-tools</code>
<a href="https://s4.51cto.com/wyfs02/M01/00/5C/wKiom1ma3aqAYuZNAAAnctBPTJU892.png-wh_500x0-wm_3-wmp_4-s_2616858819.png" target="_blank"></a>
本文转自柴鑫旺 51CTO博客,原文链接:http://blog.51cto.com/chaixinwang/1958172,如需转载请自行联系原作者