一、网络DNAT实现
正常启动一个nginx+fpm容器:
# docker run -itd --name dnat -p 81:80 -v /wordpress/:/var/www/html richarvey/nginx-php-fpm
f4acb915ef8a5e198522d3b44185ae2eaddfd753be79b7c4fd9587084f690ac1
检查容器状态
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f4acb915ef8a richarvey/nginx-php-fpm "docker-php-entrypoi…" 6 seconds ago Up 4 seconds 443/tcp, 9000/tcp, 0.0.0.0:81->80/tcp dnat
web访问:
# cat > /wordpress/info.php << EOF
<?php
phpinfo()
?>
EOF
通过web访问测试:
http://10.0.0.5:81/info.php
DNAT规则分析:
匹配本地地址转发到DOCKER链:
iptables -t nat -A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
DOCKER链分析:
如果是来自于docker0网桥的数据包返回(数据包总是从外面访问docker0内网地址的某个端口)
iptables -t nat -A DOCKER -i docker0 -j RETURN
如果是来至非docker0的内网地址访问目标端口81,会被映射到docker0内网172.17.0.2:80
iptables -t nat -A DOCKER ! -i docker0 -p tcp -m tcp --dport 81 -j DNAT --to-destination 172.17.0.2:80
SNAT规则分析:
iptables -t nat -A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
iptables -t nat -A POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p tcp -m tcp --dport 80 -j MASQUERADE
二、完整实现自定义网卡桥接
启动一个容器:
# docker run -itd --name test01 --net=none centos:self /usr/sbin/init
d32607ddfd03d66b66a09ff3a993edeee0da6547031a888cd0d59db75b9d96b7
# docker inspect -f '{{.State.Pid}}' test01
11381
# docker inspect -f '{{.HostConfig.NetworkMode}}' test01
none
#启动容器
C_ID=$(docker run -itd --net=none centos:self /usr/sbin/init)
C_PID=$(docker inspect -f '{{.State.Pid}}' $C_ID)
echo $C_PID
# 创建network namespace目录并将容器的network namespace软连接到此目录,以便ip netns命令读取
mkdir -vp /var/run/netns
ln -sv /proc/$C_PID/ns/net /var/run/netns/$C_PID
# 添加虚拟网卡veth+容器PID,类型是veth pair,名称是vp+容器PID
ip link add veth$C_PID type veth peer name vp$C_PID
# 添加虚拟网卡到br0网桥并激活网卡
brctl addif br0 veth$C_PID
ip link set veth$C_PID up
# 添加vp网卡进入名称空间命名并且激活
ip link set vp$C_PID netns $C_PID
ip netns exec $C_PID ip link set vp$C_PID name eth0
ip netns exec $C_PID ip link set eth0 up
# 配置容器网卡的ip地址
IP='192.168.102.12/24'
GW='192.168.102.1'
ip netns exec $C_PID ip addr add $IP dev eth0
ip netns exec $C_PID ip route add default via $GW
三、docker启动ssh服务:
# docker run -itd --name test01 centos:self
# docker attach test01
[root@5a14ba66288a /]# yum -y install openssh-server openssh iproute net-tool
# docker commit test01 centos:self
sha256:89e606716ffc582e61c8662194539c24d501e130140fabdca365e4e9d6d0bbcf
# docker run -itd --name test03 --privileged -ti -e "container=docker" -p 25:22 centos:self /usr/sbin/init
1fc1c6a7a1309ba4f5ceb14db723c1ef3d73e0f7ddda7c2df78219ee036337b4
# docker exec -it test04 bash
[root@1fc1c6a7a130 /]# systemctl start sshd
[root@1fc1c6a7a130 /]# systemctl start sshd
# passwd root
Changing password for user root.
New password:
BAD PASSWORD: The password is shorter than 8 characters
Retype new password:
passwd: all authentication tokens updated successfully.
测试ssh连接:
[F:\~]$ ssh 10.0.0.5 25
Connecting to 10.0.0.5:25...
Connection established.
To escape to local shell, press 'Ctrl+Alt+]'.
WARNING! The remote SSH server rejected X11 forwarding request.
[root@d17653aaf89b ~]#
[root@d17653aaf89b ~]#
[root@d17653aaf89b ~]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.5 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ac:11:00:05 txqueuelen 0 (Ethernet)
RX packets 64 bytes 6303 (6.1 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 33 bytes 5336 (5.2 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
四、pipework
# 安装git服务
yum -y install git
# 下载别人的pipwork成品代码
mkdir /opt/pipwork
git clone https://github.com/jpetazzo/pipework.git /opt/pipwork
# 复制pipword到工作目录
cp -av /opt/pipwork/pipework /usr/local/bin/
# 启动一个容器
docker run -itd --net=none --name test02 centos:self
# 利用pipwork配置网络
pipework br0 test02 192.168.102.89/24@192.168.102.1
# 验证网络是否配置成功
# docker attach test02
[root@ff99684ff287 /]# ifconfig
eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.102.89 netmask 255.255.255.0 broadcast 192.168.102.255
ether 9e:e7:55:15:1f:92 txqueuelen 1000 (Ethernet)
RX packets 26 bytes 1776 (1.7 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 5 bytes 322 (322.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@ff99684ff287 /]# ip route
default via 192.168.102.1 dev eth1
192.168.102.0/24 dev eth1 proto kernel scope link src 192.168.102.89
[root@ff99684ff287 /]# ping 192.168.102.1
PING 192.168.102.1 (192.168.102.1) 56(84) bytes of data.
64 bytes from 192.168.102.1: icmp_seq=1 ttl=128 time=0.754 ms
64 bytes from 192.168.102.1: icmp_seq=2 ttl=128 time=0.485 ms