Docker技術入門與實戰 第二版-學習筆記-8-網絡功能network-1-單個host上的容器網絡

Docker 中的網絡功能介紹
node

Docker 容許經過外部訪問容器或容器互聯的方式來提供網絡服務 python

 

1) 外部訪問容器 linux

容器中能夠運行一些網絡應用,要讓外部也能夠訪問這些應用,能夠經過 -p或 -P參數來指定端口映射
web

運行容器時若是使用-P,Docker 會隨機映射一個在49000-49900區間內的端口到內部容器開放的網絡端口。 docker

好比下面的容器,就隨機選取了本地的32768端口映射到了容器中正開放的5000端口,此時訪問本機的 32768 端口便可訪問容器內 web 應用提供的界面 數據庫

userdeMacBook-Pro:~ user$ docker run -d -P --name web -v /webapp training/webapp python app.py
Unable to find image 'training/webapp:latest' locally
latest: Pulling from training/webapp
e190868d63f8: Pull complete 
909cd34c6fd7: Pull complete 
0b9bfabab7c1: Pull complete 
a3ed95caeb02: Pull complete 
10bbbc0fc0ff: Pull complete 
fca59b508e9f: Pull complete 
e7ae2541b15b: Pull complete 
9dd97ef58ce9: Pull complete 
a4c1b0cb7af7: Pull complete 
Digest: sha256:06e9c1983bd6d5db5fba376ccd63bfa529e8d02f23d5079b8f74a616308fb11d
Status: Downloaded newer image for training/webapp:latest
1ad71e9d38081c38dcd355fd7a438cd9f94503e8bc28e99a48c0738b51e7efef

userdeMacBook-Pro:~ user$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                     NAMES
1ad71e9d3808        training/webapp     "python app.py"     42 minutes ago      Up 42 minutes       0.0.0.0:32768->5000/tcp   web

在瀏覽器中訪問http://localhost:32768:ubuntu

而後能夠經過 docker logs 命令來查看瀏覽器訪問應用的信息: api

userdeMacBook-Pro:~ user$ docker logs web
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
172.17.0.1 - - [15/Dec/2018 10:20:08] "GET / HTTP/1.1" 200 -
172.17.0.1 - - [15/Dec/2018 10:20:08] "GET /favicon.ico HTTP/1.1" 404 -

 

-p(小寫的)則能夠指定要映射的端口,而且,在一個指定端口上只能夠綁定一個 容器。瀏覽器

支持的格式有:安全

  • ip地址:主機端口:容器端口
  • ip地址::容器端口
  • 主機端口:容器端口

1》 映射全部接口地址

使用主機端口:容器端口格式,本地的 5000 端口能夠映射到容器的 5000 端 口,如:

sudo docker run -d -p 5000:5000 training/webapp python app.py

此時默認會綁定本地全部接口上的全部ip地址

 

2》映射到指定地址的指定端口

使用 ip地址:主機端口:容器端口格式指定映射使用一個特定地址,好比 localhost 地址 127.0.0.1

 

docker run -d -p 127.0.0.1:5000:5000 training/webapp python app.py

 

3》映射到指定地址的任意端口

使用ip地址::容器端口格式綁定 localhost 的任意端口到容器的 5000 端口,本地主機會自動分配一個端口:

docker run -d -p 127.0.0.1::5000 training/webapp python app.py

還可使用 udp 標記來指定 udp 端口

docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py

 

 

查看映射端口配置——docker port

查看當前映射的端口配置,也能夠查看到綁定的地址

userdeMacBook-Pro:~ user$ docker port web 5000
0.0.0.0:32768

⚠️:

容器有本身的內部網絡和 ip 地址(使用 docker inspect能夠獲取全部的變量,Docker 還能夠有一個可變的網絡配置。)

-p 標記能夠屢次使用來綁定多個端口,如:

docker run -d -p 5000:5000  -p 3000:80 training/webapp python app.py

 

 

2)容器互聯

容器的鏈接(linking)系統是除了端口映射外,另外一種跟容器中應用交互的方式。

該系統會在源和接收容器之間建立一個隧道,接收容器能夠看到源容器指定的信息。

 

1》自定義容器命名——使用 --name參數

鏈接系統依據容器的名稱來執行。所以,首先須要自定義一個好記的容器命名

當建立容器的時候,系統默認會分配一個名字。

可是自定義命名容器有2個好處:

  • 自定義的命名,比較好記,好比一個web應用容器咱們能夠給它起名叫web
  • 當要鏈接其餘容器時候,能夠做爲一個有用的參考點,好比鏈接web容器到db 容器
docker run -d -P --name web training/webapp python app.py

可使用docker ps -l查看,也可使用 docker inspect來查看容器的名字

userdeMacBook-Pro:~ user$ docker ps -l
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                     NAMES
1ad71e9d3808        training/webapp     "python app.py"     About an hour ago   Up About an hour    0.0.0.0:32768->5000/tcp   web
userdeMacBook-Pro:~ user$ docker inspect -f "{{ .Name }}" 1ad71e9d3808
/web

注意:容器的名稱是惟一的。若是已經命名了一個叫 web 的容器,當你要再次使用 web 這個名稱的時候,須要先用docker rm來刪除以前建立的同名容器。

 

在執行 docker run的時候若是添加 -rm 標記,則容器在終止後會馬上刪除。

⚠️-rm 和 -d(後臺運行)參數不能同時使用。

 

 

2》 容器互聯——使用 --link參數

格式: --link name:alias

其中 name是要連接的容器的名稱, alias是這個鏈接的別名

 

先建立一個新的數據庫容器db

userdeMacBook-Pro:~ user$ docker run -d --name db training/postgres
Unable to find image 'training/postgres:latest' locally
latest: Pulling from training/postgres
a3ed95caeb02: Pull complete 
6e71c809542e: Pull complete 
2978d9af87ba: Pull complete 
e1bca35b062f: Pull complete 
500b6decf741: Pull complete 
74b14ef2151f: Pull complete 
7afd5ed3826e: Pull complete 
3c69bb244f5e: Pull complete 
d86f9ec5aedf: Pull complete 
010fabf20157: Pull complete 
Digest: sha256:a945dc6dcfbc8d009c3d972931608344b76c2870ce796da00a827bd50791907e
Status: Downloaded newer image for training/postgres:latest
2fca948912dcfd40849d1f2080db69bed0f51a9b1c1a10ceba7e3bf7d0960e5f

刪除以前建立的 web 容器:

userdeMacBook-Pro:~ user$ docker rm -f web
web

而後建立一個新的 web 容器,並將它鏈接到 db 容器:

userdeMacBook-Pro:~ user$ docker run -d -P --name web --link db:db training/webapp python app.py
d734bf29ad945f25e65e451d5d207b007a24004002dbaa722b28e02fb46ed51e

此時,db 容器和 web 容器成功創建了互聯關係

使用 docker ps來查看容器的鏈接:

userdeMacBook-Pro:~ user$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                     NAMES
d734bf29ad94        training/webapp     "python app.py"          7 seconds ago       Up 6 seconds        0.0.0.0:32769->5000/tcp   web
2fca948912dc        training/postgres   "su postgres -c '/us…"   39 seconds ago      Up 38 seconds       5432/tcp                  db

這樣子就不用像上面同樣須要使用-p 或 -P映射端口了。

 

Docker 經過 2 種方式爲容器公開鏈接信息:

  • 環境變量
  • 更新 /etc/hosts文件

首先是環境變量方式:

使用 env 命令來查看 web 容器的環境變量:

userdeMacBook-Pro:~ user$ docker run --rm --name web --link db:db training/webapp env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=994146340f40
DB_PORT=tcp://172.17.0.3:5432
DB_PORT_5432_TCP=tcp://172.17.0.3:5432
DB_PORT_5432_TCP_ADDR=172.17.0.3
DB_PORT_5432_TCP_PORT=5432
DB_PORT_5432_TCP_PROTO=tcp
DB_NAME=/web/db
DB_ENV_PG_VERSION=9.3
HOME=/root

其中 DB_ 開頭的環境變量是供 web 容器鏈接 db 容器使用,前綴採用大寫的鏈接別名。

 

而後更新 /etc/hosts文件方式,Docker 添加了host信息到父容器的 /etc 的文件。下面是父容器 webhosts文件:

userdeMacBook-Pro:~ user$ docker run -t -i --rm --link db:db training/webapp /bin/bash
root@36078e6ba58f:/opt/webapp# cat /etc/hosts
127.0.0.1    localhost
::1    localhost ip6-localhost ip6-loopback
fe00::0    ip6-localnet
ff00::0    ip6-mcastprefix
ff02::1    ip6-allnodes
ff02::2    ip6-allrouters
172.17.0.3    db 2fca948912dc  //db容器的 容器名和ID
172.17.0.2    36078e6ba58f  //web容器的ID

能夠在 web 容器中安裝 ping 命令來測試跟db容器的連通:

root@36078e6ba58f:/opt/webapp# apt-get install -yqq inetutils-ping
(Reading database ... 18233 files and directories currently installed.)
Removing ubuntu-minimal (1.325) ...
Removing iputils-ping (3:20121221-4ubuntu1.1) ...
Selecting previously unselected package inetutils-ping.
(Reading database ... 18221 files and directories currently installed.)
Preparing to unpack .../inetutils-ping_2%3a1.9.2-1_amd64.deb ...
Unpacking inetutils-ping (2:1.9.2-1) ...
Setting up inetutils-ping (2:1.9.2-1) ...
root@36078e6ba58f:/opt/webapp# ping db
PING db (172.17.0.3): 56 data bytes
64 bytes from 172.17.0.3: icmp_seq=0 ttl=64 time=0.099 ms
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.120 ms
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.063 ms
64 bytes from 172.17.0.3: icmp_seq=3 ttl=64 time=0.202 ms
64 bytes from 172.17.0.3: icmp_seq=4 ttl=64 time=0.101 ms
64 bytes from 172.17.0.3: icmp_seq=5 ttl=64 time=0.133 ms
64 bytes from 172.17.0.3: icmp_seq=6 ttl=64 time=0.129 ms
64 bytes from 172.17.0.3: icmp_seq=7 ttl=64 time=0.104 ms
64 bytes from 172.17.0.3: icmp_seq=8 ttl=64 time=0.129 ms
64 bytes from 172.17.0.3: icmp_seq=9 ttl=64 time=0.130 ms
64 bytes from 172.17.0.3: icmp_seq=10 ttl=64 time=0.128 ms
64 bytes from 172.17.0.3: icmp_seq=11 ttl=64 time=0.128 ms
64 bytes from 172.17.0.3: icmp_seq=12 ttl=64 time=0.063 ms
64 bytes from 172.17.0.3: icmp_seq=13 ttl=64 time=0.130 ms
64 bytes from 172.17.0.3: icmp_seq=14 ttl=64 time=0.130 ms
^C--- db ping statistics ---
15 packets transmitted, 15 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.063/0.119/0.202/0.032 ms

ping 來測試db容器,它會解析成 172.17.0.3*注意:官方的 ubuntu 鏡像 默認沒有安裝 ping,須要自行安裝

用戶能夠連接多個父容器到子容器,好比能夠連接多個 web db 容器上

 

 

3) 高級網絡配置

1》默認網絡

docker network命令使用

1.首先查看docker network命令怎麼使用

userdeMBP:~ user$ docker network --help

Usage:    docker network COMMAND

Manage networks

Commands:
  connect     Connect a container to a network 將容器鏈接到網絡上,默認鏈接的是bridge網絡
  create      Create a network 建立一個網絡,使用--driver參數指定網絡類型
  disconnect  Disconnect a container from a network 斷開容器鏈接的網絡
  inspect     Display detailed information on one or more networks 展現一個或多個網絡的詳細信息
  ls          List networks 列舉現有的全部網絡
  prune       Remove all unused networks  移除全部再也不使用的網絡
  rm          Remove one or more networks 移除一個或多個網絡

Run 'docker network COMMAND --help' for more information on a command.

 

2.而後查看目前的網絡狀況,初始時是默認有下面的三類網絡的

userdeMBP:~ user$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
5a8633141529        bridge              bridge              local
78c9cc883ccc        host                host                local
454aa19cf801        none                null                local

 Docker 啓動時,會自動在主機上建立一個虛擬網橋,其實是 Linux 的一個 bridge(即這上面的bridge網絡),能夠理解爲一個軟件交換機。它會在掛載到它的網口之間進行轉發。 

 

none網絡——即什麼都沒有的網絡

打開兩個鏈接了默認bridge網絡的ubuntu容器和一個鏈接了none網絡的ubuntu容器,而後查看它們的ip配置信息,並ping本地主機看可否連通:

當你想要實現一些對安全要求比較高而且不須要聯網的操做時,就可使用none網絡

上圖可見,若是你使用的是bridge網絡,你是能夠ping通你如今的主機的網絡的;若是你是none網絡,你是沒法鏈接網絡的

好比你有些容器的做用時生成密鑰文件等操做時,使用none網絡就能保證密鑰文件的安全行,不會被竊取

 

host網絡

打開了一個鏈接了host網絡的ubuntu容器,而後查看其ip信息

userdeMBP:~ user$ docker run -it --network=host --name=ubuntu3 ubuntu:14.04 /bin/bash 
root@linuxkit-025000000001:/# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 brd 127.255.255.255 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 02:50:00:00:00:01 brd ff:ff:ff:ff:ff:ff
    inet 192.168.65.3/24 brd 192.168.65.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::50:ff:fe00:1/64 scope link 
       valid_lft forever preferred_lft forever
3: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1
    link/ipip 0.0.0.0 brd 0.0.0.0
4: ip6tnl0@NONE: <NOARP> mtu 1452 qdisc noop state DOWN group default qlen 1
    link/tunnel6 :: brd ::
5: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:c4:a0:b5:3e brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:c4ff:fea0:b53e/64 scope link 
       valid_lft forever preferred_lft forever
9: veth4a027b0@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 96:2b:b2:b1:de:52 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::942b:b2ff:feb1:de52/64 scope link 
       valid_lft forever preferred_lft forever
11: veth3406c1a@if10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether ba:80:0c:67:c0:9e brd ff:ff:ff:ff:ff:ff
    inet6 fe80::b880:cff:fe67:c09e/64 scope link 
       valid_lft forever preferred_lft forever
13: vethcee69e2@if12: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 72:51:1e:7b:01:0c brd ff:ff:ff:ff:ff:ff
    inet6 fe80::7051:1eff:fe7b:10c/64 scope link 
       valid_lft forever preferred_lft forever

(參考https://blog.csdn.net/liukuan73/article/details/51603074)

由於docker使用了Linux的Namespace技術來進行資源的隔離,如PID Namespace隔離進程,Mount Namespace隔離文件系統,Network Namespace隔離網絡等

使用bridge網絡時,一個容器會分配一個獨立的Network Namespace。可是若是使用的是host網絡,容器將不會得到一個獨立的Network Namespace,而是與宿主機公用一個Network Namespace。在這種狀況下,容器將不會虛擬出本身的網卡,配置本身的IP等,而是使用宿主機的IP和端口。容器能夠和宿主機同樣,使用宿主機的eth0,實現和外界的通訊。換言之,容器的IP地址即爲宿主機eth0的IP地址

所以上面開啓的容器使用ip addr命令時,發現獲得的信息都是宿主機上的信息。所以當外界想要訪問該容器時,直接訪問宿主機的IP和容器開放的端口便可,不須要任何的NAT轉換,就像直接運行在宿主機同樣。

⚠️可是容器的其餘方面,如文件系統、進程列表等仍是和宿主機隔離的

host網絡實際上是bridge網絡的一種補充,可是也有不足的地方:

  • 容器網絡環境隔離性弱化,即容器再也不擁有隔離、獨立的網絡棧
  • 因爲網絡隔離性的弱化,該容器會與宿主機共享競爭網絡棧的使用
  • 容器內部將再也不擁有全部的端口資源,緣由是部分端口資源已經被宿主機自己的服務佔用,還有部分端口已經用以bridge網絡模式容器的端口映射

 

 同時查看host網絡此時的詳細信息:

userdeMacBook-Pro:~ user$ docker network inspect 78c9cc883ccc
[
    {
        "Name": "host",
        "Id": "78c9cc883ccc186865ab14c31f7d3ebafecd725e2524a7ab3bb550fb91a73705",
        "Created": "2018-07-21T02:08:33.191948595Z",
        "Scope": "local",
        "Driver": "host",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": []
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "084fd2f2927a18f8c6003f7ee70e5fef80e6ffca6246f75d8ada71c5be76a8bf": {
                "Name": "ubuntu3", //即上面鏈接了host網絡的容器 "EndpointID": "a57a350fb83a4c45d276eefaf29c0ef13278af2cfbfa3a6a7c9f36a1430f07cb",
                "MacAddress": "",
                "IPv4Address": "",
                "IPv6Address": ""
            },
            "3c3f1551282d8f983faf974d96e366262d133da662108c43506e6dcb16902b4c": {
                "Name": "k8s_POD_etcd-docker-for-desktop_kube-system_1f439806cd68459343e83b51b9f719eb_0",
                "EndpointID": "6c2f76ff13c3ebe545a1c3f36d864d9525aadaebced72270abb88fe92aaed69e",
                "MacAddress": "",
                "IPv4Address": "",
                "IPv6Address": ""
            },
            "636bc1e866ed8f215261e30a522feeb91b2a8417be0a4f55324a013e7efadfcf": {
                "Name": "k8s_POD_kube-controller-manager-docker-for-desktop_kube-system_ac5424d04b6928ef15ca302888630c4e_0",
                "EndpointID": "25234b9025957c835fc0669334affd6a74bc03d9b679e50b2fe713cbfe1c9f8c",
                "MacAddress": "",
                "IPv4Address": "",
                "IPv6Address": ""
            },
            "7a58a9d0aa01abb785392264a8c5406593d4fa2b6749f27094b4f80b939e1ab4": {
                "Name": "k8s_POD_kube-scheduler-docker-for-desktop_kube-system_ea66a171667ec4aaf1b274428a42a7cf_0",
                "EndpointID": "3a83f9b42be6f8b0a68e440b839aff4326d4d524590f5471ed6882560bb9658d",
                "MacAddress": "",
                "IPv4Address": "",
                "IPv6Address": ""
            },
            "f9d84fe15fe1591d15d76fad2162285426aef4a700ed78c54b28c4a71b19c28c": {
                "Name": "k8s_POD_kube-apiserver-docker-for-desktop_kube-system_f10287b5cba0247140caeedc2e1fd602_0",
                "EndpointID": "3b43272e8ab15a3fe91d1c04cae74af2ce560b8431aaa3027bfe81b7e41fa531",
                "MacAddress": "",
                "IPv4Address": "",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

 

bridge網絡

Docker 會隨機分配一個本地未佔用的私有網段(在 RFC1918 中定義)中的一 個地址給 docker0接口。好比典型的 172.17.42.1,掩碼爲255.255.0.0。此後啓動的容器內的網口也會自動分配一個同一網段( 172.17.0.0/16 )的地址。

當建立一個 Docker 容器的時候,同時會建立了一對 veth pair接口(當數據包發送到一個接口時,另一個接口也能夠收到相同的數據包)。這對接口一端在容器內,即eth0 ——下面打開的容器查看IP信息時的eth0;

userdeMBP:~ user$ docker run -it ubuntu:14.04 /bin/bash
root@481d94d59f9f:/# ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:ac:11:00:03  
          inet addr:172.17.0.3  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:6 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:508 (508.0 B)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

root@481d94d59f9f:/# ping 10.240.203.84
PING 10.240.203.84 (10.240.203.84) 56(84) bytes of data.
64 bytes from 10.240.203.84: icmp_seq=1 ttl=37 time=0.647 ms
64 bytes from 10.240.203.84: icmp_seq=2 ttl=37 time=0.513 ms
64 bytes from 10.240.203.84: icmp_seq=3 ttl=37 time=0.674 ms
^C
--- 10.240.203.84 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2043ms
rtt min/avg/max/mdev = 0.513/0.611/0.674/0.073 ms
root@481d94d59f9f:/# ping ww.baidu.com
PING ps_other.a.shifen.com (123.125.114.144) 56(84) bytes of data.
64 bytes from 123.125.114.144: icmp_seq=1 ttl=37 time=46.3 ms
64 bytes from 123.125.114.144: icmp_seq=2 ttl=37 time=48.1 ms
64 bytes from 123.125.114.144: icmp_seq=3 ttl=37 time=47.1 ms
^C
--- ps_other.a.shifen.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 46.341/47.210/48.168/0.748 ms

能夠ping通本地主機網絡可外部網絡

另外一端在本地並被掛載到docker0網橋,名稱以 veth開頭(例如vethAQI2QT)。經過這種方式,主機能夠跟容器通訊,容器之間也能夠相互通訊。Docker 就建立了在主機和全部容器之間一個虛擬共享網絡。

 由於我使用的是mac系統,爲了使用Linux的命令來查看網橋信息,能夠在剛剛使用--network=host的容器上進行查看:

root@linuxkit-025000000001:/# brctl show //沒有安裝brctl
bash: brctl: command not found

root@linuxkit-025000000001:/# apt-get install bridge-utils
Reading package lists... Done
Building dependency tree       
Reading state information... Done
E: Unable to locate package brctl-utils //沒有找到這個包,可能須要更新下源

root@linuxkit-025000000001:/# apt-get update  //更新源             
Ign http://archive.ubuntu.com trusty InRelease                                 
Get:1 http://archive.ubuntu.com trusty-updates InRelease [65.9 kB]          
...    
Get:21 http://archive.ubuntu.com trusty/multiverse amd64 Packages [169 kB]     
Fetched 13.3 MB in 52s (252 kB/s)                                              
Reading package lists... Done

root@linuxkit-025000000001:/# apt-get install bridge-utils //而後從新下載便可
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following NEW packages will be installed:
  bridge-utils
0 upgraded, 1 newly installed, 0 to remove and 6 not upgraded.
...

而後就能夠查看網橋信息了

root@linuxkit-025000000001:/# brctl show
bridge name bridge id           STP enabled    interfaces
docker0     8000.0242c4a0b53e   no             veth3406c1a
                                               veth4a027b0
                                               vethcee69e2

能夠看見掛載到docker0網橋這邊的接口爲veth3406c1aveth4a027b0vethcee69e2

查看默認使用的bridge網絡,若是在開啓容器時沒有制定,通常就會默認使用的是bridge網絡。由於docker的橋接網絡使用虛擬網橋,bridge網絡用於同一主機上的docker容器相互通訊,鏈接到同一個網橋的docker容器能夠相互通訊

userdeMacBook-Pro:~ user$ docker network inspect a782ffdae16f
[
    {
        "Name": "bridge",
        "Id": "a782ffdae16f9c3dbfec0a992a9a6d605429c657263dc83f33c71ad499f5e2b8",
        "Created": "2018-12-19T01:34:27.308734153Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "481d94d59f9f363fd3b00f09b793c9d7e1d90169626a7170f4d1012949c9ace4": {
                "Name": "wonderful_matsumoto",
                "EndpointID": "9dd9be72550d24135202f430dfeea0fb0132d52089045c933a5bfb6fd5ddb779",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",
                "IPv6Address": ""
            },
            "876cdcff687d83e5ea85d3c2eb16d01aac62bfd3e5051e5e65f0fd49230d7333": {
                "Name": "ubuntu2",
                "EndpointID": "9c16f983ff075f1499dcc1de4ead5ac77097829a68ff868a328e90e336660e29",
                "MacAddress": "02:42:ac:11:00:04",
                "IPv4Address": "172.17.0.4/16",
                "IPv6Address": ""
            },
            "b4a512f0230fa598e7e40171e0597ea6db0740105449314a1a3767dcaa4a0edb": {
                "Name": "registry",
                "EndpointID": "b164dd37f23eac13364f1378642c5e8b88b783ea48fbbce26017ab02b33b542e",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",//說明這個是默認的bridge網絡
            "com.docker.network.bridge.enable_icc": "true",//說明支持容器間互相通訊
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",//默認網橋的名字爲docker0
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]
//上面可見爲開啓的三個容器分別分配了172.17.0.0/16網段下的地址
userdeMacBook-Pro:~ user$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
084fd2f2927a        ubuntu:14.04        "/bin/bash"              About an hour ago   Up About an hour                             ubuntu3
876cdcff687d        ubuntu:14.04        "/bin/bash"              About an hour ago   Up About an hour                             ubuntu2
e6ba811ecb6a        ubuntu:14.04        "/bin/bash"              About an hour ago   Up About an hour                             thirsty_germain
481d94d59f9f        ubuntu:14.04        "/bin/bash"              About an hour ago   Up About an hour                             wonderful_matsumoto
b4a512f0230f        registry            "/entrypoint.sh /etc…"   3 days ago          Up 2 hours          0.0.0.0:5000->5000/tcp   registry
參考:https://blog.csdn.net/dhaiuda/article/details/82820318
鏈接到同一個bridge網絡的容器(即它們地址都在同一個網段下)能夠互相訪問彼此使用-p或--publish發佈的端口
咱們也能夠自定義本身的bridge網絡,並且docker文檔也建議構建本身的網絡,由於默認bridge網絡是有缺陷的
 
自定義和默認bridge網絡的區別:
  • 默認橋接網絡中的容器只能經過IP地址訪問其餘容器(除非使用遺留的-link指令鏈接兩個容器),而自定義橋接網絡提供DNS解析,能夠經過容器的名字或是別名訪問其餘容器
  • 容器能夠自由的進入或是退出自定義橋接(bridge)網絡,若是想要退出默認橋接(bridge)網絡,須要先中止容器的運行,而後從新建立該容器,並指定須要鏈接的其餘網絡
  • 若是更改了默認橋接網絡的網絡配置,須要從新啓動docker,而且因爲默認橋接網絡只有一個,所以全部容器的網絡配置都是同樣的,而用戶自定義網絡能夠在建立時指定網絡配置(例如默認網關、MTU等),不須要重啓docker,靈活性更高
  • 在默認橋接網絡中,能夠經過--link參數鏈接兩個容器來共享環境變量,用戶自定義網絡中沒法使用這種方式,可是docker提供了更好的方式:                 

    1.多個容器可使用docker volume(這是docker存儲數據的一種方式,之後會介紹)掛載到同一個文件,在文件中指明環境變量,從而實現所容器的環境變量共享                                                     

    2.多個容器可使用同一個docker-compose.yml(與docker service有關)文件啓動 ,能夠在該文件中定義共享環境變量                                                   

    3.可使用swarm services,而且經過  secrets 和 configs  (這兩個還沒看)實現環境變量共享
 
 
container模式
其實還有一種設置網絡的方式,格式爲:
--network=container:容器名(或--net=container:容器名
多個容器使用共同的網絡,看到的ip是同樣的,舉例說明:
生成一個ubuntu10容器,使用--net=container:ubuntu8鏈接一個--link db容器的ubuntu8容器:

從上圖可見,基本上就至關於打開了別名爲ubuntu10的ubuntu8容器,二者的IP地址是徹底同樣的,連主機名都是同樣的。固然,ubuntu10容器也是開啓了的:

userdeMBP:~ user$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
3b854b76e02e        ubuntu:14.04 "/bin/bash" 2 minutes ago Up 2 minutes ubuntu10 f07c50c1c6ee ubuntu:14.04 "/bin/bash" 27 minutes ago Up 27 minutes ubuntu8

 

 
2》自定義網絡——bridge網絡
1.
使用docker network create 命令
userdeMacBook-Pro:~ user$ docker network ls //查看當前的網絡
NETWORK ID          NAME                DRIVER              SCOPE
a782ffdae16f        bridge              bridge              local
78c9cc883ccc        host                host                local
454aa19cf801        none                null                local
userdeMacBook-Pro:~ user$ docker network create --driver bridge myNetwork1 //新添加一個bridge網絡,名字叫myNetwork1
f16ae5c303c68f25e63ff80c09a3289fcf1785c1bc86a3baabeef6687035cf0b
userdeMacBook-Pro:~ user$ docker network ls //查看獲得新的網絡myNetwork1
NETWORK ID          NAME                DRIVER              SCOPE
a782ffdae16f        bridge              bridge              local
78c9cc883ccc        host                host                local
f16ae5c303c6        myNetwork1          bridge              local
454aa19cf801        none                null                local
生成完後,在以--network = host方式鏈接的容器中查看生成的網橋信息
root@linuxkit-025000000001:/# brctl show
bridge name              bridge id      STP enabled     interfaces
br-f16ae5c303c6      8000.0242751521cb   no                          //這個就是新生成的bridge網絡,尚未鏈接容器,因此interfaces爲空
docker0              8000.0242c4a0b53e   no             veth3406c1a
                                                        veth4a027b0
                                                        vethcee69e2
root@linuxkit-025000000001:/# ip addr
...
14: br-f16ae5c303c6: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:75:15:21:cb brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.1/16 brd 172.18.255.255 scope global br-f16ae5c303c6 //能夠看見其被自動分配的網段爲172.18.0.1/16
       valid_lft forever preferred_lft forever

網橋名稱br-f16ae5c303c6 即 br-networkId

 

使用docker network inspect命令查看生成的network信息:

userdeMacBook-Pro:~ user$ docker network inspect f16ae5c303c6
[
    {
        "Name": "myNetwork1",
        "Id": "f16ae5c303c68f25e63ff80c09a3289fcf1785c1bc86a3baabeef6687035cf0b",
        "Created": "2018-12-19T03:56:51.09420804Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/16", //自動分配的網段和網關 "Gateway": "172.18.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

 

使用--subset和--gateway參數指定網段和網關信息:
userdeMacBook-Pro:~ user$ docker network create --driver bridge --subnet 172.20.11.0/24 --gateway 172.20.11.1 myNetwork2
9dc30b4c7e392ad993540f19638653e62b4cff8af4944d8ab29b7b88c467331d
userdeMacBook-Pro:~ user$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
a782ffdae16f        bridge              bridge              local
78c9cc883ccc        host                host                local
f16ae5c303c6        myNetwork1          bridge              local
9dc30b4c7e39        myNetwork2          bridge              local
454aa19cf801        none                null                local
userdeMacBook-Pro:~ user$ docker network inspect 9dc30b4c7e39
[
    {
        "Name": "myNetwork2",
        "Id": "9dc30b4c7e392ad993540f19638653e62b4cff8af4944d8ab29b7b88c467331d",
        "Created": "2018-12-19T04:13:47.531039833Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.20.11.0/24",
                    "Gateway": "172.20.11.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]
userdeMacBook-Pro:~ user$ 

指明瞭網段爲172.20.11.0/24,網關爲172.20.11.1

root@linuxkit-025000000001:/# ifconfig br-9dc30b4c7e39
br-9dc30b4c7e39 Link encap:Ethernet  HWaddr 02:42:99:f9:5d:06  
          inet addr:172.20.11.1  Bcast:172.20.11.255  Mask:255.255.255.0
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

 

這樣咱們在啓動容器的時候就可以使用上面自定義的bridge網絡了:

userdeMacBook-Pro:~ user$ docker run -it --name=ubuntu4 --network=myNetwork2 ubuntu:14.04 /bin/bash
root@57fb8937e663:/# ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:ac:14:0b:02  
          inet addr:172.20.11.2  Bcast:172.20.11.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:14 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:1156 (1.1 KB)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

root@57fb8937e663:/# 

可見的確是在172.20.11.0/24網段下

 

上面的容器的IP地址都是動態分配的,若是用戶想要實現指定靜態的IP地址的話,可使用--ip參數:

userdeMacBook-Pro:~ user$ docker run -it --name=ubuntu5 --network=myNetwork2 --ip=172.20.11.8 ubuntu:14.04 /bin/bash
root@9e11c1b9e90d:/# ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:ac:14:0b:08  
          inet addr:172.20.11.8  Bcast:172.20.11.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:6 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:508 (508.0 B)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

指定了靜態地址172.20.11.8

⚠️只有當鏈接的網絡指定了--subnet時,相應的容器開啓時纔可以使用--ip參數

而後ping一下 172.20.11.1,這兩個容器的確是能夠ping通的
root@9e11c1b9e90d:/# ping -c 3 172.20.11.1
PING 172.20.11.1 (172.20.11.1) 56(84) bytes of data.
64 bytes from 172.20.11.1: icmp_seq=1 ttl=64 time=0.092 ms
64 bytes from 172.20.11.1: icmp_seq=2 ttl=64 time=0.101 ms
64 bytes from 172.20.11.1: icmp_seq=3 ttl=64 time=0.090 ms

--- 172.20.11.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2049ms
rtt min/avg/max/mdev = 0.090/0.094/0.101/0.009 ms

那若是咱們去ping默認bridge網絡下的ubuntu容器,發現是不可以ping通的:

root@9e11c1b9e90d:/# ping -c 3 172.17.0.4
PING 172.17.0.4 (172.17.0.4) 56(84) bytes of data.

--- 172.17.0.4 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2068ms
那麼若是想要ping通,讓它們之間可以通訊應該怎麼作呢?
按照道理來講若是在兩個網段中可以添加一個路由器,那麼這兩個網段就可以通訊了
首先查看它們的路由表信息
root@linuxkit-025000000001:/# ip r  //查看本地主機上的路由表信息
...
172.17.0.0/16 dev docker0  proto kernel  scope link  src 172.17.0.1 
172.20.11.0/24 dev br-9dc30b4c7e39  proto kernel  scope link  src 172.20.11.1 
...

而後再查看本地系統是否開啓了轉發支持:

root@linuxkit-025000000001:/# sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1 //開啓了

而後再查看防火牆iptables,須要從新使用--privileged參數的--network=host的容器:

 

userdeMBP:~ user$ docker run -it --privileged --network=host --name=ubuntu6 ubuntu:14.04 /bin/bash 
root@linuxkit-025000000001:/# ip r
...
172.17.0.0/16 dev docker0  proto kernel  scope link  src 172.17.0.1 
172.20.11.0/24 dev br-9dc30b4c7e39  proto kernel  scope link  src 172.20.11.1 
...

root@linuxkit-025000000001:/# iptables-save //須要安裝iptables
bash: iptables-save: command not found

root@linuxkit-025000000001:/# apt-get install iptables
Reading package lists... Done
Building dependency tree       
Reading state information... Done
E: Unable to locate package iptables //須要更新源

root@linuxkit-025000000001:/# apt-get update //更新源
Ign http://archive.ubuntu.com trusty InRelease
...   
Get:21 http://archive.ubuntu.com trusty/multiverse amd64 Packages [169 kB]     
Fetched 13.3 MB in 50s (266 kB/s)                                              
Reading package lists... Done

root@linuxkit-025000000001:/# apt-get install iptables //而後就可以成功安裝了
Reading package lists... Done
...
Setting up libnfnetlink0:amd64 (1.0.1-2) ...
Setting up libxtables10 (1.4.21-1ubuntu1) ...
Setting up iptables (1.4.21-1ubuntu1) ...
Processing triggers for libc-bin (2.19-0ubuntu6.14) ...

root@linuxkit-025000000001:/# iptables-save //查看獲得此時的防火牆規則
...
-A DOCKER -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 5000 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i br-9dc30b4c7e39 ! -o br-9dc30b4c7e39 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -i br-f16ae5c303c6 ! -o br-f16ae5c303c6 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o br-9dc30b4c7e39 -j DROP  
-A DOCKER-ISOLATION-STAGE-2 -o br-f16ae5c303c6 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
-A DOCKER-USER -j RETURN
-A KUBE-FIREWALL -m comment --comment "kubernetes firewall for dropping marked packets" -m mark --mark 0x8000/0x8000 -j DROP
COMMIT
# Completed on Wed Dec 19 06:46:37 2018

從這兩句:

-A DOCKER-ISOLATION-STAGE-2 -o br-9dc30b4c7e39 -j DROP  
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP

可知iptables DROP 掉了網橋 docker0 與 br-9dc30b4c7e39 之間雙向的流量

從規則的命名 DOCKER-ISOLATION 可知 docker 在設計上就是要隔離不一樣的 netwrok

那咱們要如何讓二者通訊呢?

方法就是而後容器ubuntu5,即網絡爲 br-9dc30b4c7e39的容器添加一個新網卡,方法就是鏈接上docker0的bridge網絡:

一開始它的網卡狀況以下所示:

root@9e11c1b9e90d:/# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    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
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1
    link/ipip 0.0.0.0 brd 0.0.0.0
3: ip6tnl0@NONE: <NOARP> mtu 1452 qdisc noop state DOWN group default qlen 1
    link/tunnel6 :: brd ::
18: eth0@if19: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:14:0b:08 brd ff:ff:ff:ff:ff:ff
    inet 172.20.11.8/24 brd 172.20.11.255 scope global eth0
       valid_lft forever preferred_lft forever

而後爲該容器添加bridge網絡:

userdeMacBook-Pro:~ user$ docker network connect bridge 9e11c1b9e90d

而後咱們就可以看見它多了一個網卡,地址爲172.17.0.5/16

root@9e11c1b9e90d:/# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    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
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1
    link/ipip 0.0.0.0 brd 0.0.0.0
3: ip6tnl0@NONE: <NOARP> mtu 1452 qdisc noop state DOWN group default qlen 1
    link/tunnel6 :: brd ::
18: eth0@if19: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:14:0b:08 brd ff:ff:ff:ff:ff:ff
    inet 172.20.11.8/24 brd 172.20.11.255 scope global eth0
       valid_lft forever preferred_lft forever
20: eth1@if21: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:05 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.5/16 brd 172.17.255.255 scope global eth1
       valid_lft forever preferred_lft forever

而後再次嘗試ping ubuntu5的容器,發現可以成功ping通了:

root@9e11c1b9e90d:/# ping -c 3 172.17.0.4
PING 172.17.0.4 (172.17.0.4) 56(84) bytes of data.
64 bytes from 172.17.0.4: icmp_seq=1 ttl=64 time=0.133 ms
64 bytes from 172.17.0.4: icmp_seq=2 ttl=64 time=0.110 ms
64 bytes from 172.17.0.4: icmp_seq=3 ttl=64 time=0.165 ms

--- 172.17.0.4 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2108ms
rtt min/avg/max/mdev = 0.110/0.136/0.165/0.022 ms

 

若是你想要解除上面ubuntu5的bridge網絡鏈接:

userdeMacBook-Pro:~ user$ docker network disconnect bridge 9e11c1b9e90d
相關文章
相關標籤/搜索