docker使用到的與linux網絡有關的主要技術python
標準的dokcer支持如下4種網絡模式linux
器要想訪問外部網絡,須要本地系統的轉發支持。在Linux 系統中,檢查轉發是否打開。web
$sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1
若是爲 0,說明沒有開啓轉發,則須要手動打開。docker
容器中能夠運行一些網絡應用,要讓外部也能夠訪問這些應用,能夠經過 -P 或 -p 參數來指定端口映射。數據庫
當使用 -P 標記時,Docker 會隨機映射一個 49000~49900 的端口到內部容器開放的網絡端口。
-p(小寫的)則能夠指定要映射的端口,而且,在一個指定端口上只能夠綁定一個容器。支持的格式有 json
ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort。
映射全部接口地址ubuntu
使用 hostPort:containerPort 格式本地的 5000 端口映射到容器的 5000 端口,能夠執行api
$ sudo docker run -d -p 5000:5000 training/webapp python app.py
此時默認會綁定本地全部接口上的全部地址。安全
映射到指定地址的指定端口
能夠使用 ip:hostPort:containerPort 格式指定映射使用一個特定地址,好比 localhost 地址 127.0.0.1bash
$ sudo docker run -d -p 127.0.0.1:5000:5000 training/webapp python app.py
映射到指定地址的任意端口
使用 ip::containerPort 綁定 localhost 的任意端口到容器的 5000 端口,本地主機會自動分配一個端口。
$ sudo docker run -d -p 127.0.0.1::5000 training/webapp python app.py
還能夠使用 udp 標記來指定 udp 端口
$ sudo docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py
查看映射端口配置
使用 docker port 來查看當前映射的端口配置,也能夠查看到綁定的地址
$ docker port nostalgic_morse 5000 #container NAMES
127.0.0.1:49155.
注意:
容器有本身的內部網絡和 ip 地址(使用 docker inspect 能夠獲取全部的變量,Docker 還能夠有一個可變的網絡配置。)
-p 標記能夠屢次使用來綁定多個端口,例如:
$ sudo docker run -d -p 5000:5000 -p 3000:80 training/webapp python app.py
官網示例
先建立一個新的 Docker 網絡。 $ docker network create -d bridge my-net -d 參數指定 Docker 網絡類型,有 bridge overlay。其中 overlay 網絡類型用於 Swarm mode\ 鏈接容器,運行一個容器並鏈接到新建的 my-net 網絡 $ docker run -it --rm --name busybox1 --network my-net busybox sh 打開新的終端,再運行一個容器並加入到 my-net 網絡 $ docker run -it --rm --name busybox2 --network my-net busybox sh 進入容器,經過互相ping 容器名稱來判斷是否互聯
本身測試示例
#查看全部網絡: docker network ls #建立本身的網絡 docker network create -d bridge my-bridge-network #檢查網絡(若是你檢查網絡,會發現裏面什麼都沒有) docker network inspect my-bridge-network
添加一個容器到自定義的網絡
#指定網絡 運行(將db添加爲自定義的網絡)
docker run -d --net=my-bridge-network --name db training/postgres #--name 爲定義的名字
#再次檢查網絡(會發現多了一個容器) docker network inspect my-bridge-network #查看網絡狀況 docker inspect --format='{{json .NetworkSettings.Networks}}' db #查看ip地址 docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' db #啓動另外一個容器:並不在一個網段,未加入到自定義的網絡 名稱爲web docker run -d --name web training/webapp python app.py
進入交互模式,而且ping web的地址進行測試
docker exec -it db bash #此時是ping 不通的 #將web加入自定義的網絡 $ docker network connect my-bridge-network web docker exec -it db bash #而後在去交互模式ping web,就能夠通訊了
docker有一個linking 系統能夠鏈接多個容器。它會建立一對父子關係,父容器能夠看到所選擇的 子容器的信息。
注意:
容器的名 稱 是 惟 一的。若是 你 命名了一個 叫 web的容器,當 你 要 再次 使用 web這個名 稱 的 時候 , 你 須要用 docker rm來 刪 除以前建立的容器,也能夠 再 執行 docker run的 時候 加--rm標記來 中止舊 的容器, 並刪 除, rm 和 -d 參 數是 不兼 容的。
使用--name標記能夠爲容器命名
$ sudo docker run -d -P --name web training/webapp python app.py
使用docker ps -l 來驗證咱們設定的命名
$ sudo docker ps -l
links可讓容器之間安全的交互,使用--link標記。
#先建立一個新的數據庫容器, $ sudo docker run -d --name db training/postgres #建立一個新的web容器,並將它link到db容器 $ docker run -d -P --name web --link db:db training/webapp python app.py # --link標記的格式:--link name:alias,name是咱們要連接的容器的名稱,alias是這個連接的別名(會在新建的容器中/etc/hosts添加一條記錄 ip db 此處的db爲指定的alias別名)
使用docker ps來查看容器的連接
能夠看到命名的容器,db和web,db容器的names列有db也有web/db。這表示web容 器連接到db容器,他們是一個父子關係。在這個link中,2個容器中有一對父子關係。docker在2個 容器之間建立了一個安全的鏈接,並且不用映射他們的端口到宿主主機上。在啓動db容器的時候也不 用-p和-P標記。使用link以後咱們就能夠不用暴露數據庫端口到網絡上。
docker 經過2種方式爲父子關係的容器公開鏈接信息:
• 環境變量
• 更新/etc/hosts文件
#使用env命令來查看容器的環境變量 $ sudo docker run --rm --name web2 --link db:db training/webapp env #除了環境變量,docker還添加host信息到父容器的/etc/hosts的文件。下面是父容器web的hosts文件 $ sudo docker run -t -i --rm --link db:db training/webapp /bin/bash root@aed84ee21bde:/opt/webapp# cat /etc/hosts
這裏有2個hosts,第一個是web容器,web容器用id做爲他的主機名,第二個是db容器的ip和主機名
root@aed84ee21bde:/opt/webapp# apt-get install -yqq inetutils-ping root@aed84ee21bde:/opt/webapp# ping db PING db (172.17.0.5): 48 data bytes 56 bytes from 172.17.0.5: icmp_seq=0 ttl=64 time=0.267 ms 56 bytes from 172.17.0.5: icmp_seq=1 ttl=64 time=0.250 ms 56 bytes from 172.17.0.5: icmp_seq=2 ttl=64 time=0.256 ms 用ping來ping db容器,它會解析成172.17.0.5
注意:官方的ubuntu鏡像默認沒有安裝ping
注意:你能夠連接多個子容器到父容器,好比咱們能夠連接多個web到db容器上。
快速配置指南
下面是一個跟docker網絡相關的命令列表,有些命令選項只有 在docker服務啓動的時候才能夠執行,並且不能立刻生效。
• -b BRIDGE or --bridge=BRIDGE — 橋接配置 • --bip=CIDR — 定製docker0的掩碼 • -H SOCKET... or --host=SOCKET... — 它告訴docker從哪一個通道來接收run container stop container這樣的命令,也是docker api的地址 • --icc=true|false • --ip-forward=true|false • --iptables=true|false • --mtu=BYTES — • --dns=IP_ADDRESS... • --dns-search=DOMAIN... • -h HOSTNAME or --hostname=HOSTNAME — 主機名配置 • --link=CONTAINER_NAME:ALIAS — link 系統 • --net=bridge|none|container:NAME_or_ID|host —橋接配置 • -p SPEC or --publish=SPEC — 映射容器端口到宿主主機 • -P or --publish-all=true|false — 映射容器端口到宿主主機
配置容器dns服務的方法
注意:若是 沒 有上 述最 後 2個 選 項, docker會用主機上的 /etc/resolv.conf來配置容器, 它 是 默 認配置。
建立本身的橋接
#中止舊網橋並刪除 $ sudo service docker stop $ sudo ip link set dev docker0 down $ sudo brctl delbr docker0 # 建立本身的網橋 $ sudo brctl addbr bridge0 $ sudo ip addr add 192.168.5.1/24 dev bridge0 $ sudo ip link set dev bridge0 up # 確認網橋啓動 $ ip addr show bridge0 # 告訴docker橋接設置,並啓動docker服務(在ubuntu上) $ echo 'DOCKER_OPTS="-b=bridge0"' >> /etc/default/docker $ sudo service docker start
docker服務啓動成功並綁定容器到新的網橋,建一個容器,你會看到它的ip是咱們的設置的新ip 段,docker會自動檢測到它。
用brctl show能夠看到容器啓動或則中止後網橋的配置變化,在容器中使 用ip a 和ip r 來查看ip地址配置和路由信息
建立一個點到點鏈接(network namespace)
#建立一個名爲nestest的 network namespace ip netns add netest #列出系統中存在的network namespace ip netns list #刪除一個network namespace ip netns delete nstest #在network namespace中執行一條命令 ip netns exec <network namespace name > command 如: ip netns exec <network namespace name > ip addr #在network namespace中啓動一個bash ip netns exec <network namespace name > /bin/bash
默認docker會將全部容器鏈接到由docker0提供的虛擬子網,你也能夠使用本身建立的網橋。但如 果你想要2個特殊的容器之間能夠直連通訊,而不用去配置複雜的主機網卡橋接。
解決辦法很簡單:建立一對接口,把2個容器放到這對接口中,配置成點到點鏈路類型。這2個容 器就能夠直接通訊了。配置以下:
# 在2個終端中啓動2個容器 $ sudo docker run -i -t --rm --net=none base /bin/bash root@1f1f4c1f931a:/# $ sudo docker run -i -t --rm --net=none base /bin/bash root@12e343489d2f:/# #找到他們的process IDs ,而後建立他們的 namespace entries $ sudo docker inspect -f '{{.State.Pid}}' 1f1f4c1f931a 2989 $ sudo docker inspect -f '{{.State.Pid}}' 12e343489d2f 3004 $ sudo mkdir -p /var/run/netns $ sudo ln -s /proc/2989/ns/net /var/run/netns/2989 $ sudo ln -s /proc/3004/ns/net /var/run/netns/3004 # 建立」peer「接口,而後配置路由
#在主機上建立虛擬網卡 $ sudo ip link add A type veth peer name B
$ sudo ip link set A netns 2989 #2989爲一個network namespace ,此處是將網卡放到network namespace中的命令 $ sudo ip netns exec 2989 ip addr add 10.1.1.1/32 dev A $ sudo ip netns exec 2989 ip link set A up #啓動網卡 $ sudo ip netns exec 2989 ip route add 10.1.1.2/32 dev A #分配ip $ sudo ip link set B netns 3004 $ sudo ip netns exec 3004 ip addr add 10.1.1.2/32 dev B $ sudo ip netns exec 3004 ip link set B up $ sudo ip netns exec 3004 ip route add 10.1.1.1/32 dev B
如今這2個容器就能夠相互ping通,併成功創建鏈接。點到點鏈路不須要子網和子網掩碼,使用ip route 來鏈接單個ip地址到指定的網絡接口。
若是 沒 有 特 殊 須要 你不 須要指定 --net=none來建立點到點 鏈路 。 還有一個辦法就是建立一個只跟主機通訊的容器,除非有特殊需求,你能夠僅用--icc=false來限制 主機間的通訊。