版本比较
标识
- 该行被添加。
- 该行被删除。
- 格式已经改变。
Docker Bridge 网络
提示 |
---|
本节实验需要在Linux环境下进行。 |
Image Added
创建两个容器
本章介绍
网络基础知识回顾
IP、子网掩码、网关、DNS、端口号
https://zhuanlan.zhihu.com/p/65226634
Note
面试常问的一个题目, 当你在浏览器中输入一个网址(比如www.baidu.com)并敲回车,这个过程后面都发生了什么
Internet如何工作的
https://www.hp.com/us-en/shop/tech-takes/how-does-the-internet-work
从数据包的角度详细解析
https://www.homenethowto.com/advanced-topics/traffic-example-the-full-picture/
网络常用命令
IP地址的查看
Windows
ipconfig
Linux
ifconfig
或者
ip addr
网络连通性测试
ping命令
PS C:\Users\Peng Xiao> ping 192.168.178.1 Pinging 192.168.178.1 with 32 bytes of data: Reply from 192.168.178.1: bytes=32 time=2ms TTL=64 Reply from 192.168.178.1: bytes=32 time=3ms TTL=64 Reply from 192.168.178.1: bytes=32 time=3ms TTL=64 Reply from 192.168.178.1: bytes=32 time=3ms TTL=64 Ping statistics for 192.168.178.1: Packets: Sent = 4, Received = 4, Lost = 0 (0% loss), Approximate round trip times in milli-seconds: Minimum = 2ms, Maximum = 3ms, Average = 2ms PS C:\Users\Peng Xiao>
telnet命令
测试端口的连通性
➜ ~ telnet www.baidu.com 80 Trying 104.193.88.123... Connected to www.wshifen.com. Escape character is '^]'. HTTP/1.1 400 Bad Request Connection closed by foreign host. ➜ ~
traceroute
路径探测跟踪
Linux下使用 tracepath
➜ ~ tracepath www.baidu.com 1?: [LOCALHOST] pmtu 1500 1: DESKTOP-FQ0EO8J 0.430ms 1: DESKTOP-FQ0EO8J 0.188ms 2: 192.168.178.1 3.371ms 3: no reply 4: gv-rc0052-cr102-et91-251.core.as33915.net 13.970ms 5: asd-tr0021-cr101-be156-10.core.as9143.net 19.190ms 6: nl-ams04a-ri3-ae51-0.core.as9143.net 213.589ms 7: 63.218.65.33 16.887ms 8: HundredGE0-6-0-0.br04.sjo01.pccwbtn.net 176.099ms asymm 10 9: HundredGE0-6-0-0.br04.sjo01.pccwbtn.net 173.399ms asymm 10 10: 63-219-23-98.static.pccwglobal.net 177.337ms asymm 11 11: 104.193.88.13 178.197ms asymm 12 12: no reply 13: no reply 14: no reply 15: no reply 16: no reply 17: no reply 18: no reply 19: no reply 20: no reply 21: no reply 22: no reply 23: no reply 24: no reply 25: no reply 26: no reply 27: no reply 28: no reply 29: no reply 30: no reply Too many hops: pmtu 1500 Resume: pmtu 1500 ➜ ~
Windows下使用 TRACERT.EXE
PS C:\Users\Peng Xiao> TRACERT.EXE www.baidu.com Tracing route to www.wshifen.com [104.193.88.123] over a maximum of 30 hops: 1 4 ms 3 ms 3 ms 192.168.178.1 2 * * * Request timed out. 3 21 ms 18 ms 19 ms gv-rc0052-cr102-et91-251.core.as33915.net [213.51.197.37] 4 14 ms 13 ms 12 ms asd-tr0021-cr101-be156-10.core.as9143.net [213.51.158.2] 5 23 ms 19 ms 14 ms nl-ams04a-ri3-ae51-0.core.as9143.net [213.51.64.194] 6 15 ms 14 ms 13 ms 63.218.65.33 7 172 ms 169 ms 167 ms HundredGE0-6-0-0.br04.sjo01.pccwbtn.net [63.223.60.58] 8 167 ms 168 ms 168 ms HundredGE0-6-0-0.br04.sjo01.pccwbtn.net [63.223.60.58] 9 168 ms 173 ms 167 ms 63-219-23-98.static.pccwglobal.net [63.219.23.98] 10 172 ms 170 ms 171 ms
curl命令
请求web服务的
http://www.ruanyifeng.com/blog/2019/09/curl-reference.html
Docker Bridge 网络
Warning
注意,本节实验需要在Linux环境下进行
Image Removed
创建两个容器
代码块 |
---|
$ docker container run -d --rm --name box1 busybox /bin/sh -c "while true; do sleep 3600; done" $ docker container run -d --rm --name box2 busybox /bin/sh -c "while true; do sleep 3600; done" $ docker container ls CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 4f3303c84e53 busybox "/bin/sh -c 'while t…" 49 minutes ago Up 49 minutes box2 03494b034694 busybox "/bin/sh -c 'while t…" 49 minutes ago Up 49 minutes box1 |
容器间通信
两个容器都连接到了一个叫 docker0 的Linux
bridge上bridge上。
展开 | ||
---|---|---|
|
Note
brctl
使用前需要安装, 对于CentOS, 可以通过 sudo yum install -y bridge-utils
安装. 对于Ubuntu, 可以通过 sudo apt-get install -y bridge-utils
|
提示 |
---|
|
容器对外通信
查看路由:
查看路由代码块 |
---|
$ ip route
default via 10.0.2.2 dev eth0 proto dhcp metric 100
10.0.2.0/24 dev eth0 proto kernel scope link src 10.0.2.15 metric 100
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
192.168.200.0/24 dev eth1 proto kernel scope link src 192.168.200.10 metric 101 |
iptables转发规则:
代码块 |
---|
$ sudo iptables --list -t nat Chain PREROUTING (policy ACCEPT) target prot opt source destination DOCKER all -- anywhere anywhere ADDRTYPE match dst-type LOCAL Chain INPUT (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination DOCKER all -- anywhere !loopback/8 ADDRTYPE match dst-type LOCAL Chain POSTROUTING (policy ACCEPT) target prot opt source destination MASQUERADE all -- 172.17.0.0/16 anywhere Chain DOCKER (2 references) target prot opt source destination RETURN all -- anywhere anywhere |
端口转发
创建容器创建容器:
代码块 |
---|
$ docker container run -d --rm --name web -p 8080:80 nginx $ docker container inspect --format '{{.NetworkSettings.IPAddress}}' web $ docker container run -d --rm --name client busybox /bin/sh -c "while true; do sleep 3600; done" $ docker container inspect --format '{{.NetworkSettings.IPAddress}}' client $ docker container exec -it client wget http://172.17.0.2 |
查看iptables的端口转发规则:
代码块 |
---|
[vagrant@docker-host1 ~]$ sudo iptables -t nat -nvxL Chain PREROUTING (policy ACCEPT 10 packets, 1961 bytes) pkts bytes target prot opt in out source destination 1 52 DOCKER all -- * * 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL Chain INPUT (policy ACCEPT 9 packets, 1901 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 2 packets, 120 bytes) pkts bytes target prot opt in out source destination 0 0 DOCKER all -- * * 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL Chain POSTROUTING (policy ACCEPT 4 packets, 232 bytes) pkts bytes target prot opt in out source destination 3 202 MASQUERADE all -- * !docker0 172.17.0.0/16 0.0.0.0/0 0 0 MASQUERADE tcp -- * * 172.17.0.2 172.17.0.2 tcp dpt:80 Chain DOCKER (2 references) pkts bytes target prot opt in out source destination 0 0 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0 1 52 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 to:172.17.0.2:80 |
创建和使用 bridge
Docker Host 网络
网络命名空间
Linux的Namespace(命名空间)技术是一种隔离技术,常用的Namespace有 user namespace, process namespace, network namespace等
在Docker容器中,不同的容器通过Network namespace进行了隔离,也就是不同的容器有各自的IP地址,路由表等,互不影响。
Note
准备一台Linux机器,这一节会用到一个叫 brtcl
的命令,这个命令需要安装,如果是Ubuntu的系统,可以通过 apt-get install bridge-utils
安装;如果是Centos系统,可以通过 sudo yum install bridge-utils
来安装
创建bridge
[vagrant@docker-host1 ~]$ sudo brctl addbr mydocker0 [vagrant@docker-host1 ~]$ brctl show bridge name bridge id STP enabled interfaces mydocker0 8000.000000000000 no [vagrant@docker-host1 ~]$
准备一个shell脚本
脚本名字叫 add-ns-to-br.sh
#!/bin/bash bridge=$1 namespace=$2 addr=$3 vethA=veth-$namespace vethB=eth00 sudo ip netns add $namespace sudo ip link add $vethA type veth peer name $vethB sudo ip link set $vethB netns $namespace sudo ip netns exec $namespace ip addr add $addr dev $vethB sudo ip netns exec $namespace ip link set $vethB up sudo ip link set $vethA up sudo brctl addif $bridge $vethA
脚本执行
[vagrant@docker-host1 ~]$ sh add-ns-to-br.sh mydocker0 ns1 172.16.1.1/16 [vagrant@docker-host1 ~]$ sh add-ns-to-br.sh mydocker0 ns2 172.16.1.2/16
把mydocker0这个bridge up起来
[vagrant@docker-host1 ~]$ sudo ip link set dev mydocker0 up
验证
[vagrant@docker-host1 ~]$ sudo ip netns exec ns1 bash [root@docker-host1 vagrant]# ip a 1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 5: eth00@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether f2:59:19:34:73:70 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.16.1.1/16 scope global eth00 valid_lft forever preferred_lft forever inet6 fe80::f059:19ff:fe34:7370/64 scope link valid_lft forever preferred_lft forever [root@docker-host1 vagrant]# ping 172.16.1.2 PING 172.16.1.2 (172.16.1.2) 56(84) bytes of data. 64 bytes from 172.16.1.2: icmp_seq=1 ttl=64 time=0.029 ms 64 bytes from 172.16.1.2: icmp_seq=2 ttl=64 time=0.080 ms ^C --- 172.16.1.2 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1000ms rtt min/avg/max/mdev = 0.029/0.054/0.080/0.026 ms [root@docker-host1 vagrant]#
对外通信
https://www.karlrupp.net/en/computer/nat_tutorial
Python Flask + Redis 练习
程序准备
准备一个Python文件,名字为 app.py
内容如下:
from flask import Flask from redis import Redis import os import socket app = Flask(__name__) redis = Redis(host=os.environ.get('REDIS_HOST', '127.0.0.1'), port=6379) @app.route('/') def hello(): redis.incr('hits') return f"Hello Container World! I have been seen {redis.get('hits').decode('utf-8')} times and my hostname is {socket.gethostname()}.\n"
准备一个Dockerfile
FROM python:3.9.5-slim RUN pip install flask redis && \ groupadd -r flask && useradd -r -g flask flask && \ mkdir /src && \ chown -R flask:flask /src USER flask COPY app.py /src/app.py WORKDIR /src ENV FLASK_APP=app.py REDIS_HOST=redis EXPOSE 5000 CMD ["flask", "run", "-h", "0.0.0.0"]
镜像准备
构建flask镜像,准备一个redis镜像。
$ docker image pull redis
$ docker image build -t flask-demo .
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
flask-demo latest 4778411a24c5 About a minute ago 126MB
python 3.9.5-slim c71955050276 8 days ago 115MB
redis latest 08502081bff6 2 weeks ago 105MB
创建一个docker bridge
$ docker network create -d bridge demo-network 8005f4348c44ffe3cdcbbda165beea2b0cb520179d3745b24e8f9e05a3e6456d $ docker network ls NETWORK ID NAME DRIVER SCOPE 2a464c0b8ec7 bridge bridge local 8005f4348c44 demo-network bridge local 80b63f711a37 host host local fae746a75be1 none null local $
创建redis container
创建一个叫 redis-server
的container,连到 demo-network上
$ docker container run -d --name redis-server --network demo-network redis
002800c265020310231d689e6fd35bc084a0fa015e8b0a3174aa2c5e29824c0e
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
002800c26502 redis "docker-entrypoint.s…" 4 seconds ago Up 3 seconds 6379/tcp redis-server
$
创建flask container
$ docker container run -d --network demo-network --name flask-demo --env REDIS_HOST=redis-server -p 5000:5000 flask-demo
打开浏览器访问 http://127.0.0.1:5000
应该能看到类似下面的内容,每次刷新页面,计数加1
Hello Container World! I have been seen 36 times and my hostname is 925ecb8d111a.
总结
如果把上面的步骤合并到一起,成为一个部署脚本
# prepare image docker image pull redis docker image build -t flask-demo . # create network docker network create -d bridge demo-network # create container docker container run -d --name redis-server --network demo-network redis docker container run -d --network demo-network --name flask-demo --env REDIS_HOST=redis-server -p 5000:5000 flask-demo
目录 |
---|