1. 程式人生 > 實用技巧 >Docker (二) Docker網路配置

Docker (二) Docker網路配置

Docker提供網路服務

當我們在容器中執行一些網路服務,如httpd,nginx,php等。要讓外部使用者可以訪問這些服務,這就需要我們進行一些配置,才能達到這些效果。如埠對映或容器互聯的方式。

埠對映方式

我們可以在啟動容器的時候用-p或-P引數來制定埠對映。使用-p引數指定一個指定的埠對映到容器應用中,而使用-P是選擇一個隨機的埠對映到容器應用埠中。

方式一:使用-p引數,指定一個對映的埠,且這個被指定的埠只能繫結一個容器

# 繫結方式一: hostport:containerPort
[root@hd3 ~]# docker run -d -p 88:80 --name myweb nginx dac9b2d7ecab288e3fd3186e34941a78b94f4cee9368a3f0ccef8b8136a590a0 [root@hd3
~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES dac9b2d7ecab nginx "/docker-entrypoint.…" 4 seconds ago Up 2 seconds 0.0.0.0:88->80/tcp myweb [root@hd3 ~]# curl localhost:88
<!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.
</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>
# 繫結方式二:host:port:containerPort
[root@hd3 ~]# docker run -d -p 127.0.0.1:89:80 --name myweb nginx
1ce3a804f6ed20beaa353e7b9a8d8069c75f592a529fcbf95e23564a52c1d634
[root@hd3 ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
1ce3a804f6ed        nginx               "/docker-entrypoint.…"   10 seconds ago      Up 9 seconds        127.0.0.1:89->80/tcp   myweb
[root@hd3 ~]# curl 127.0.0.1:89
# 繫結方式三:host::containerPort 這種方式是選擇一個該主機的隨機埠
[root@hd3 ~]# docker run -d -p 127.0.0.1::80 --name myweb nginx
93a420d642bc36ec1f3c53bf10959b9b252603a5caff75cabc19c26a4e7f007f
[root@hd3 ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                     NAMES
93a420d642bc        nginx               "/docker-entrypoint.…"   4 seconds ago       Up 3 seconds        127.0.0.1:32768->80/tcp   myweb
[root@hd3 ~]# curl 127.0.0.1:32768
# 可以指定對映埠的連線協議
[root@hd3 ~]# docker run -d -p 127.0.0.1:82:80/udp --name myweb nginx 34917ff1230b6a8d072507df71053afee430435fd1cd232c06f010b69eb663d0 [root@hd3 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 34917ff1230b nginx "/docker-entrypoint.…" 3 seconds ago Up 1 second 80/tcp, 127.0.0.1:82->80/udp myweb
# 也可以一次性繫結多個埠
[root@hd3 ~]# docker run -d -p 88:80 -p 89:443 --name myweb nginx
76764e3c6fa2e15b28dd3da5bba28713c00d89516953927cef10c290169ea112
[root@hd3 ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                     NAMES
76764e3c6fa2        nginx               "/docker-entrypoint.…"   4 seconds ago       Up 3 seconds        0.0.0.0:88->80/tcp, 0.0.0.0:89->443/tcp   myweb

方式二:使用-P引數,Docker會隨機對映一個埠到內部的網路開放的埠和上述的第三種情況類似

[root@hd3 ~]# docker run -d -P --name myweb nginx
6e8f0737f38efea2c183b97babeaf5bc2bc12e4fa417ba5198b8cf04e75f0f6b
[root@hd3 ~]# docker ps 
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                   NAMES
6e8f0737f38e        nginx               "/docker-entrypoint.…"   3 seconds ago       Up 2 seconds        0.0.0.0:32772->80/tcp   myweb

通過docker logs -f containername可以檢視docker日誌資訊

[root@hd3 ~]# docker logs -f myweb
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Configuration complete; ready for start up

通過docker ports containername檢視容器埠資訊

[root@hd3 ~]# docker port myweb
80/tcp -> 0.0.0.0:32772
[root@hd3 ~]# 

Docker容器互聯

容器的連線系統除了埠對映外,另一種是容器的互動方式。該系統會在源和接受容器之間建立一個隧道,接受容器可以看到源容器指定的資訊。

使用 --link引數可以讓容器與容器之間進行安全的互動

[root@hd3 ~]# docker run -e MYSQL_ROOT_PASSWORD=123456 -d --name mydb mysql   # 先啟動一個mysql容器
5b835f77eb9ad738ce55286ce1837ed84f59eab3c7a25a2e52b12a457f548fad
[root@hd3 ~]# docker run -d -P --name myweb  --link mydb:db nginx             # 再啟動一個web容器,並將它連線到資料庫容器中
e74c38a73c7eee83fe017540f92284e5a71293c7159e1397a845a638b801d515
[root@hd3 ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                   NAMES
e74c38a73c7e        nginx               "/docker-entrypoint.…"   4 seconds ago       Up 2 seconds        0.0.0.0:32773->80/tcp   myweb
5b835f77eb9a        mysql               "docker-entrypoint.s…"   34 seconds ago      Up 33 seconds       3306/tcp, 33060/tcp     mydb

從上面可以看到,此時myweb和mydb容器已經相互連線起來

--link 引數的格式: --link name:alias
name:是要連結的容器的名稱,
alias:是這個連結的別名

Docker容器之間的互聯,是在容器與容器之間建立一個安全的隧道,而且不用對映他們的埠到主機上,在啟動mydb容器的時候沒有使用-p或-P引數,從而避免了暴露過多的埠到外部網路上。

Docker通過兩種方式為容器公開連線的資訊:

  1. 環境變數

  2. 更新/etc/hosts檔案

通過env可以檢視環境變數

[root@hd3 ~]# docker run --rm --name myweb01 --link mydb:db nginx env
DB_PORT_33060_TCP_ADDR=172.17.0.2
HOSTNAME=37a871abaf9d
DB_PORT=tcp://172.17.0.2:3306
DB_PORT_3306_TCP=tcp://172.17.0.2:3306
DB_PORT_33060_TCP_PORT=33060
DB_ENV_MYSQL_VERSION=8.0.21-1debian10
DB_PORT_33060_TCP_PROTO=tcp
HOME=/root
DB_NAME=/myweb01/db
PKG_RELEASE=1~buster
DB_PORT_33060_TCP=tcp://172.17.0.2:33060
NGINX_VERSION=1.19.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
NJS_VERSION=0.4.2
DB_ENV_MYSQL_MAJOR=8.0
DB_PORT_3306_TCP_ADDR=172.17.0.2
DB_ENV_MYSQL_ROOT_PASSWORD=123456
PWD=/
DB_ENV_GOSU_VERSION=1.12
DB_PORT_3306_TCP_PORT=3306
DB_PORT_3306_TCP_PROTO=tcp

其中DB_開頭的環境變數是供web容器連線 DB 容器使用的。可以看到連線容器的協議,埠,密碼等

除了環境變數,Docker 還新增host資訊到父容器的 /etc/hosts 的檔案:

[root@hd3 ~]# docker run --rm -it --name myweb03 --link mydb:db nginx  /bin/bash
root@f1ee3a4dec86:/# 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.2    db 5b835f77eb9a mydb
172.17.0.4    f1ee3a4dec86

可以看到這裡有2個hosts,第一個是 web 容器,web容器用id作為他的主機名,第二個是 DB 容器的 ip 和主機名。可以在web 容器中使用ping命令來測試跟 DB 容器的連通。

Docker四種網路模式

Host模式

Docker使用了Linux的Namespaces技術來進行資源隔離,如PID Namespace隔離程序,Mount Namespace隔離檔案系統,Network Namespace隔離網路等。一個Network Namespace提供了一份獨立的網路環境,包括網絡卡、路由、Iptable規則等都與其他的Network Namespace隔離。一個Docker容器一般會分配一個獨立的Network Namespace。但如果啟動容器的時候使用host模式,那麼這個容器將不會獲得一個獨立的Network Namespace,而是和宿主機共用一個Network Namespace。容器將不會虛擬出自己的網絡卡,配置自己的IP等,而是使用宿主機的IP和埠。

表現形式:容器和宿主IP一致

特點: 用於網路效能要求較高的場景,但安全性和隔離性相對差一些

結構如下:

配置方式:--network host

[root@hd3 ~]# docker run -itd --name host_test --network host centos  # 指定網路模式
837dd3e985b2b7e936940ee44b5cab13dc6d02a05c225a24c2e19f13c06c2d2c
[root@hd3 ~]# docker exec -it host_test /bin/bash
[root@hd3 /]# ip a  # 進入容器可以發現連容器的主機名也和宿主的主機名一致,通過ip a 檢視到網路配置也都是一致的
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 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
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:4b:a1:4f brd ff:ff:ff:ff:ff:ff
    inet 192.168.239.132/24 brd 192.168.239.255 scope global noprefixroute ens32
       valid_lft forever preferred_lft forever
。。。
[root@hd3 /]# exit 
exit
[root@hd3 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 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
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:4b:a1:4f brd ff:ff:ff:ff:ff:ff
    inet 192.168.239.132/24 brd 192.168.239.255 scope global noprefixroute ens32
。。。

Bridge模式

bridge模式是Docker預設的網路設定,此模式會為每一個容器分配Network Namespace、設定IP等,並將一個主機上的Docker容器連線到一個虛擬網橋上。類似於Vmware的nat網路模式。同一個宿主機上的所有容器會在同一個網段下,相互之間是可以通訊的。docker程序會建立一個docker0網橋,容器內的資料通過這個網絡卡裝置於主機之間進行通訊。

特點:

配置方式:預設情況下就是bridge的模式

[root@hd3 ~]# docker run -d -it --name bridge_test centos
083ba95f39ae455be1f91efaa00a368db5bbf452a611ff2a0c4d39d2889a9d78
[root@hd3 ~]# 
[root@hd3 ~]# docker inspect bridge_test
[ 。。。。。。。。。。
            "Networks": {  # 這一行顯示了該容器的網路是bridge
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "80c570b6c4ea28598da690765604caa14e02882735dc86807b6950205be8219c",
                    "EndpointID": "e62963d786270c3d1f68b5c5aba10dfaa9a1d6328807409e894976c4aa983aaf",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null
                }
            }
        }
    }
]
[root@hd3 ~]# docker exec -it bridge_test /bin/bash
[root@083ba95f39ae /]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 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
123: eth0@if124: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

[root@083ba95f39ae /]# ping www.baidu.com 
PING www.a.shifen.com (180.101.49.12) 56(84) bytes of data.
64 bytes from 180.101.49.12 (180.101.49.12): icmp_seq=1 ttl=127 time=36.1 ms
注意: 若該預設方式容器無法訪問外網可以檢視一下該配置
systcl net.ipv4.ip_forward
1     # 若該值為0則無法訪問外網

systcl -w net.ipv4.ip_forward=1  # 將其修改為1

Container模式

這個模式指定新建立的容器和已經存在的一個容器共享一個Network Namespace,而不是和宿主機共享。新建立的容器不會建立自己的網絡卡,配置自己的IP,而是和一個指定的容器共享IP、埠範圍等。同樣,兩個容器除了網路方面,其他的如檔案系統、程序列表等還是隔離的。兩個容器的程序可以通過lo網絡卡裝置通訊。

表現形式:多個容器使用的是共同的網路,看到的IP也是一致的。

特點:K8S中的pod就是使用這種模式,平時使用不多

結構如下:

[root@hd3 ~]# docker run -itd --name container_test --net=container:bridge_test centos  # 指定為container模式
0ab83d070c9c9ecff083a91ae4c3a5324c4b72eb4f726a4223cff0f31c5fd5f0
[root@hd3 ~]# docker attach container_test
[root@083ba95f39ae /]# ip a    # 檢視ip發現和上面bridge的ip一致的
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 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
123: eth0@if124: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

None模式

在這種模式下,Docker容器擁有自己的Network Namespace,但是,並不為Docker容器進行任何網路配置。也就是說,這個Docker容器沒有網絡卡、IP、路由等資訊。需要我們自己為Docker容器新增網絡卡、配置IP等。

[root@hd3 ~]# docker run -itd --name none_test --network none centos   # 指定為none模式
ac35a1a7d54315b917197ce8a73f3b328ad78348f7f919144d34824459f7dab3
[root@hd3 ~]# docker attach none_test
[root@ac35a1a7d543 /]# ip a  # 檢視網路配置發現沒有任何資訊
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 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

自定義網路

與預設的bridge一樣,但是自定義的網路具備內部的DNS發現,可以通過容器名或主機名進行容器之間的相互通訊。

[root@hd3 ~]# docker network create test_network   # 自定義一個網路
cb23126382b281f7e9ec21dfb7471d0d1db382773b3b6596b05526b36deb49c9
[root@hd3 ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
80c570b6c4ea        bridge              bridge              local
7a4c931b7874        host                host                local
671303b2ec10        lnmp                bridge              local
89b85fcb7fd0        none                null                local
cb23126382b2        test_network        bridge              local  # 可以看到我們自己定義的網路
[root@hd3 ~]# docker run -itd --name test1 --net=test_network centos    # 建立容器指定自定義的網橋
5137f1f35471832a65a275537dde5cef5671841fd18ac53ee5b0fccd0426a4c0
[root@hd3 ~]# docker run -itd --name test2 --net=test_network centos
58bf03132e8a8c51ffbe2d7ee9f4572233007de1d8d0383b7cef31968df34f6c
[root@hd3 ~]# docker attach test1
[root@5137f1f35471 /]# ping test2    # 進入網橋ping 可以自定義解析test2
PING test2 (172.19.0.3) 56(84) bytes of data.
64 bytes from test2.test_network (172.19.0.3): icmp_seq=1 ttl=64 time=0.714 ms
64 bytes from test2.test_network (172.19.0.3): icmp_seq=2 ttl=64 time=0.077 ms
[root@5137f1f35471 /]# 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.19.0.2    5137f1f35471

Docker的DNS配置

我們在建立容器的時候,並沒有指定主機名和DNS等配置,如果我們需要配置,那麼怎麼自定義配置容器的主機名和DNS配置?裡面的原理有事什麼樣的呢?

祕訣就是它利用虛擬檔案來掛載到容器的3個相關的配置檔案:

[root@hd3 ~]# docker run --rm --name mydocker -it centos /bin/bash
[root@20265bbb21cd /]# mount  # 檢視掛載資訊
。。。
/dev/sda3 on /etc/resolv.conf type xfs (rw,relatime,seclabel,attr2,inode64,noquota)
/dev/sda3 on /etc/hostname type xfs (rw,relatime,seclabel,attr2,inode64,noquota)
/dev/sda3 on /etc/hosts type xfs (rw,relatime,seclabel,attr2,inode64,noquota)
。。。

這種機制可以讓宿主機DNS資訊發生更新後,所有Docker容器的 dns 配置通過 /etc/resolv.conf 檔案立刻得到更新。

如果想要手動指定容器的配置,可以利用下面的選項。

-h HOSTNAME or --hostname=HOSTNAME 設定容器的主機名,它會被寫到容器的/etc/hostname 和 /etc/hosts。
但它在容器外部看不到,既不會在docker ps中顯示,也不會在其它容器的 /etc/hosts看到
--link=CONTAINER_NAME:ALIAS   選項會在建立容器的時候,新增一個其他容器 的主機名到/etc/hosts 檔案中,
讓新容器的程序可以使用主機名 ALIAS 就可以 連線它。
--dns=IP_ADDRESS 新增DNS伺服器到容器的 /etc/resolv.conf中,讓容器利用這個伺服器來解析所有不在 /etc/hosts 中的主機名
[root@hd3 ~]# docker run --rm --name mydocker -h host_test -it centos /bin/bash  # 指定主機名
[root@host_test /]# cat /etc/hostname  # 檢視一下主機名是我們指定的
host_test
[root@host_test /]# cat /etc/hosts   # 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.2    host_test

注意:如果沒有--dns 和--dns-search選項時,Docker會預設用宿主機上的 /etc/resolv.conf 來配置容器。

Docker容器訪問控制

容器訪問外網

容器的訪問控制,主要通過Linux上的 iptables 防火牆來進行管理和實現。

容器要想訪問外部網路,需要本地系統的轉發支援,在linux系統中,檢查轉發是否開啟

[root@hd3 ~]# sysctl net.ipv4.ip_forward

net.ipv4.ip_forward = 1

如果為0,說明沒有開啟轉發,則需要手動開啟

[root@hd3 ~]# sysctl -w net.ipv4.ip_forward=1

注意:

如果在啟動Docker服務的時候指定 --ip-forward=true,Docker就會自動設定系統的 ip_forward 引數為1。

處理引數原因,另一個就是防火牆了,容器所有到外部網路的連線,源地址都會被NAT成本地系統的IP地址,這是使用iptables 的源地址偽裝操作實現的。

檢視主機的NAT規則

[root@wallace ~]# iptables -t nat -nL
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
DOCKER     all  --  0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LO  # 預設情況下是可以出去的.

容器之間訪問

預設情況下,容器之間是可以相互通訊的

容器之間的訪問需要兩個方面的支援:

1. 容器的網路拓撲是否已經互聯,預設情況下,所有的容器都會

2.本地系統的iptable是否允許

訪問所有的埠

當啟動Docker服務時,預設會新增一條轉發策略到iptables的FORWARD鏈上,策略為通過(ACCEPT)還是禁止(DROP)取決於配置--icc=true還是--icc=false。如果手動指定--iptables=false則不會新增iptables 規則。

可見,預設情況下,不同容器之間是允許網路互通的。如果是為了安全考慮,可以在/etc/default/docker 檔案中配置DOCKER_OPTS=--icc=false來禁止它。

外部網路訪問容器

容器允許外部訪問,可以在docker run 時候通過 -p 或 -P 引數來啟用。不論用哪種,其實也是在本地的 iptables 的nat表中新增相應的規則。

使用 -P 時:

[root@server ~]# iptables -t nat -nL  #檢視防火牆nat表的規則
...
Chain DOCKER (2 references)
target     prot opt source               destination                  
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:32770 to:172.17.0.3:443
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:32771 to:172.17.0.3:80
...

使用 -p 88:80 時:

[root@server ~]# iptables -t nat -nL  #檢視防火牆規則
Chain DOCKER (2 references)
target     prot opt source               destination         
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:88 to:172.17.0.5:80

注意:這裡規則映射了 0.0.0.0,意味著將接收主機來自所有的介面的流量。

配置docker0網橋

Docker 服務預設會建立一個 docker0 網橋(其實有一個 docker0 內部介面),它在核心層連通了其它的物理網絡卡或虛擬網絡卡,這就將所有容器和本地主機都放到同一個物理網路。

Docker 預設指定了 docker0 介面的 IP 地址和子網掩碼,讓主機和容器之間可以通過網橋相互通訊,它還給出了MTU(介面允許接收的最大傳輸單元),通常是1500Bytes,或宿主機網路路由上支援的預設值,這些值都可以在服務啟動的時候進行配置。

--bip=CIDR   --IP地址加掩碼格式,例如 192.168.1.2/24
--mtu=BYTES  --覆蓋預設的 Docker mtu配置

也可以在配置檔案中配置 DOCKER_OPTS, 然後重啟服務,由於目前Docker網橋是Linux網橋,可以使用 brctl show 來檢視網橋和埠連線資訊

[root@server ~]# brctl show  #檢視網橋和埠資訊
bridge name    bridge id        STP enabled    interfaces
docker0        8000.0242d8da46c0    no         veth07c5f5c
                                        veth0bed0f7

每次建立一個新容器的時候,Docker 從可用的地址段中選擇一個空閒的 IP 地址分配給容器的 eth0 埠。使用本地主機上 docker0 介面的IP 作為所有容器的預設閘道器

[root@server ~]# docker run -it --rm --name myCentos centos /bin/bash
[root@4636797a8e7c /]# ifconfig 
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.6  netmask 255.255.0.0  broadcast 172.17.255.255
...

[root@4636797a8e7c /]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.17.0.1      0.0.0.0         UG    0      0        0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 eth0

自定義網橋

除了預設的 docker0 網橋,也可以指定網橋來連線各個容器

在啟動Docker 服務的時候, 使用-b BRIDGE或--bridge=BRIDGE來指定使用的網橋

(1)先建立網橋

[root@server ~]# systemctl stop docker  #停止docker服務
[root@server ~]# ip link set dev docker0 down  #停止docker0網橋
[root@server ~]# brctl delbr docker0  #刪除docker0網橋

[root@server ~]# brctl addbr bridge0  #新建bridge0網橋
[root@server ~]# ip addr add 192.168.2.1/24 dev bridge0  #繫結ip給bridge0網橋
[root@server ~]# ip link set dev bridge0 up  #啟動bridge0網橋
[root@server ~]# brctl show   #檢視網橋資訊
bridge name    bridge id        STP enabled    interfaces
bridge0        8000.000000000000    no        
virbr0        8000.525400caf93e    yes        virbr0-nic
[root@server ~]# ifconfig bridge0  #檢視bridge0網橋資訊
bridge0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.2.1  netmask 255.255.255.0  broadcast 0.0.0.0

( 2 )配置docker

[root@server ~]# vim /lib/systemd/system/docker.service  #由於新版本的沒有/etc/default/docker配置檔案,so 需要自己新增。
ExecStart=/usr/bin/dockerd -H unix:// $DOCKER_OPTS  #在ExecStart末尾新增 $DOCKER_OPTS
EnvironmentFile=-/etc/default/docker    #指定配置檔案的路徑

[root@server ~]# vim /etc/default/docker  #自定義編輯配置檔案,寫入啟動指定網橋的網橋資訊
DOCKER_OPTS="-b=bridge0"

[root@server ~]# systemctl start docker  #啟動docker服務
[root@server ~]# docker run --rm -ti --name Mycentos centos /bin/bash  #建立一個容器

[root@0a13bd05faae /]# ifconfig  #檢視容器的ip地址,檢查是否橋接到birdge0上面
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.2.2  netmask 255.255.255.0  broadcast 192.168.2.255

[root@0a13bd05faae /]# ping 192.168.2.1  #測試和網橋是否通
PING 192.168.2.1 (192.168.2.1) 56(84) bytes of data.
64 bytes from 192.168.2.1: icmp_seq=1 ttl=64 time=0.094 ms

說明:在老版本docker上面預設就有/etc/default/docker配置檔案,直接編輯即可, 在新版本上面沒有,所以需要自己指定。