美文网首页
Docker 体验及总结(3) - 网络

Docker 体验及总结(3) - 网络

作者: 千反田爱瑠爱好者 | 来源:发表于2018-08-22 11:20 被阅读16次
    https://www.docker.com/

    Docker网络

    • 单机网络:Bridge,Host,None
    • 多机网络:Overlay

    学习Docker网络务必至少清晰理解以下概念:

    • 数据包通信
    • 网络分层模型
    • IP地址和路由
    • 公有IP、私有IP与NAT(网络地址转换)
    • 网络检测工具:ping,telnet,tracert

    命名空间

    • 网络命名空间即ip和端口
    • Container的Namespace与宿主机隔离
    • Container之间的Namespace也是隔离但互通的
    docker run -d --name test1 busybox /bin/sh -c "while true; do sleep 3600; done"
    docker run -d --name test2 busybox /bin/sh -c "while true; do sleep 3600; done"
    
    docker ps
    docker exec -it container_id /bin/sh    # 进入Container中的操作系统
        ip a
    或
    docker exec container_id ip a               # 查看Namespace:ip地址和端口
        1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
            link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
            inet 127.0.0.1/8 scope host lo
               valid_lft forever preferred_lft forever
        35: eth0@if36: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
            link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
            inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
               valid_lft forever preferred_lft forever
    # 可发现这两个Container可以相同
    

    创建、删除Namespaces

    ip netns list                               # 查看、删除、创建Namespace
    ipnetns delete test1
    ipnetns delete test2
    
    ip netns add test1      # 创建namespace,创建后默认为Down
    ip netns add test2
    
    ip netns exec test1 ip a                    # 在test1中执行“ip a”命令:查看test1的网卡信息
    ipnetns exec test1 ip link set dev lo up    # 启动test1的lo接口(不能单独启动,必须成对)
    

    实例:Linux环境下创建veth-pair连通两个Namespace的步骤

    1. 添加一对Veth:
    ip link add veth-test1 type veth peer name veth-test2
    
    1. 分别把两个Namespace接口添加到Veth:
    ip link set veth-test1 netns test1
    ip link set veth-test2 netns test2
    
    1. 为两个接口分配ip地址
    ip netns exec test1 ip addr add 192.168.1.1/24 dev veth-test1
    ip netns exec test2 ip addr add 192.168.1.2/24 dev veth-test2
    
    1. 启动两端接口并查看状态
    ip netns exec test1 ip link set dev veth-test1 up
    ip netns exec test2 ip link set dev veth-test2 up
    
    ip netns exec test1 ip link
    ip netns exec test2 ip link
    ip link
    
    1. 测试两个Namespace是否可ping通
    ip netns exec test1 ping 192.168.1.2
    ip netns exec test2 ping 192.168.1.1
    

    Link

    • Container创建会动态生成ip,因此无法通过固定的ip预先配置好连接(如数据库);
    • 可以使用--name为Container命名,容器之间直接通过--link连通,被连通的容器之间可以直接通过Link访问而不需要指定ip;
    • 实际使用场景中会有更方便的方法,因此Link并不常用。
    # test2通过--link指定了test1,因此test2可以直接通过test1来ping通,反之不行
    docker run -d --name test1 busybox /bin/sh -c "while true; do sleep 3600; done"    
    docker run -d --name test2 --link test1 busybox /bin/sh -c "while true; do sleep 3600; done"
    
    docker exec -it test2 /bin/sh
        ping test1
    

    Bridge

    Container创建时默认网络模式为Bridge(也可以自己手动指定,如果没有指定--network,则默认连接docker0):

    docker network ls    # 查看当前机器上Docker有哪些网络
    docker ps
    docker network inspect container_id    # 查看Container网络状态
    

    两个容器各有一个Network Namespace,通过docker0相互通信:

    # 创建一个Container test1
    docker run -d --name test1 busybox /bin/sh -c "while true; do sleep 3600; done"
    
    # 安装brctl命令,查看接口连接状态
    yum install -y brctl
    ip a
    brctl show 
    
    # 可发现test1与docker0通过一个Veth相连
    ip a
    docker ps
    docker exec test1 ip a
    
    # 创建第二个Container2
    docker run -d --name test2 busybox /bin/sh -c "while true; do sleep 3600; done"
    brctl show
    ip a    # 可发现docker0上连上了两个接口
    

    实例:自定义一个Bridge,并使容器通过这个Bridge互连

    • 容器通过用户自己创建的Bridge(而不是默认的docker0),则连接到Bridge时已经Link好,不需要--link指定。
    • 访问外网:容器可通过NAT使用外部主机的网卡访问外网。
    # 创建Bridge
    docker network create -d bridge my-bridge
    docker network ls
    brctl show
    
    # 创建第二个Container
    docker run -d --name test3 --network my-brdge busybox /bin/sh -c "while true; do sleep 3600; done"
    brctl show  
    docker ps
    docker inspect container_id
    
    # 把test1也连接到Bridge
    docker network connect my-bridge test1      
    
    # 在test3中测试ping
    docker exec -it test3 
        ping test1
    

    Host

    Container与宿主机共享一套Network Namespace(端口可能会冲突)。

    docker run --name test1 -d --network host busybox /bin/sh -c "while true; do sleep 3600; done"
    docker exec -it test1 /bin/sh
        ip a
    

    None

    指定--network为none,没有ip地址和mac地址,只允许通过exec本地访问(安全性要求较高时适用)。

    端口映射

    需要供外界访问的Container服务:端口映射

    # 把Container的80端口映射到本地的8080端口
    docker run --name web -d -p 8080:80 nginx   
    curl localhost:8080
    

    Overlay

    多机器通信

    具体部署方法:https://github.com/yipwinghong/FileRepository/blob/master/docker/multi-host-network.md

    Etcd

    分布式存储,避免多机器环境下Container的ip不会被占用。

    VxLAN

    多容器应用部署

    app.py(接收请求,返回从Redis获取的数据)

    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 'Hello Container World! I have been seen %s times and my hostname is %s.\n' % (redis.get('hits'),socket.gethostname())
    
    if __name__ == "__main__":
        app.run(host="0.0.0.0", port=5000, debug=True)
    

    Dockerfile

    FROM python:2.7
    LABEL maintaner="YWH yipwinghong0401@gmail.com"
    COPY . /app
    WORKDIR /app
    RUN pip install flask redis
    EXPOSE 5000
    CMD [ "python", "app.py" ]
    

    Redis Container:

    docker run -d --name redis redis    # 仅app访问,不需要把端口暴露给外部
    

    Flask Container:

    docker build -t ywh/flask-redis .
    docker run -d -p 5000:5000 --link redis --name flask-redis -e REDIS_HOST=redis ywh/flask-redis    # 动态指定环境变量
    docker exec -it flask-redis
        ping redis
    

    外部访问:

    curl localhost:5000
    

    相关文章

      网友评论

          本文标题:Docker 体验及总结(3) - 网络

          本文链接:https://www.haomeiwen.com/subject/oameiftx.html