docker容器啟動時,相關的網路選項
1,啟動container時,指定網路連接方式:--network bridge/host/none
# docker container run --name b1 --network bridge -it --rm busybox:latest
2,查看主機名字命令:hostname,如果啟動容器時,沒有指定主機名稱,則容器id(CONTAINER ID)和容器的主機名稱是相同的,
啟動容器的時候,指定主機名稱:-h name
# docker container run --name b1 --network bridge -it --rm -h host1 busybox:latest
3,查看本機的hosts檔案,cat /etc/hosts
# 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.4 host1
發現本容器的名字host1是可以翻譯成ip地址的,
查看一下DNS server的ip:cat /etc/resolv.conf
cat /etc/resolv.conf
# Generated by NetworkManager
search DHCP HOST
nameserver 192.168.1.1
nameserver 192.168.0.1
發現DNS server的ip是你宿主機所在網路的網關ip,如果這個網關是聯網的,則這個容器是可以連接上外網的,可以使用nslookup -type=A www.baidu.com做實驗,
# nslookup -type=a www.baidu.com
Server: 192.168.1.1
Address: 192.168.1.1:53
Non-authoritative answer:
www.baidu.com canonical name = www.a.shifen.com
Name: www.a.shifen.com
Address: 39.156.66.14
Name: www.a.shifen.com
Address: 39.156.66.18
也可以ping www.baidu.com,也是可以ping通的,
4,啟動container時,指定dns server:--dns 8.8.8.8,
# docker container run --name b1 --network bridge -it --rm -h host1 --dns 8.8.8.8 busybox:latest
# cat /etc/resolv.conf
search DHCP HOST
nameserver 8.8.8.8
5,啟動container時,指定dns 搜索域:--dns-search ubuntu.org.cn,
# docker container run --name b1 --network bridge -it --rm -h host1 --dns 8.8.8.8 --dns-search ubuntu.org.cn busybox:latest
# cat /etc/resolv.conf
search ubuntu.org.cn
nameserver 8.8.8.8
dns搜索域是什么:它的作用在于當你用主機名(比如說YourHost)去訪問別的機器時,如果DNS無法將YourHost決議為IP,則DNS會使用你的這個search設定的內容(比如說ubuntu.org.cn)加上需要查詢的主機名YourHost,變成MyHost.ubuntu.org.cn后,再去DNS server里查找一次ip地址,
6,啟動container時,指定hosts檔案內容 :---add-host list,
# docker container run --name b1 --network bridge -it --rm -h host1 --dns 8.8.8.8 --dns-search ubuntu.org.cn --add-host www.mysite.com:1.1.1.1 busybox:latest
# 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
1.1.1.1 www.mysite.com
172.17.0.4 host1
問題:啟動一個nginx容器后,nginx容器使用的是私有IP,外部機器無法直接訪問它,所以我們需要使用DNAT做映射,把ngxin暴露(expose)到外部,
解決辦法:在啟動容器時,使用-p選項,去暴露到外部,-p選項的使用方式有4種,
1,-p <containerPort>
-
把容器的埠containerPort,映射到主機上所有網卡地址的一個動態分配的埠上,因為是動態的所有每次都會變化,這對于使用nginx的客戶端來說是無法容忍的,
-
例子:把nginx的80埠,映射到主機上所有網卡地址的一個動態分配的埠上,
# docker run --name httpd --rm -p 80 ys/busybox:local3然后使用
docker port 容器名,查看映射到哪個埠上了,# docker port httpd 80/tcp -> 0.0.0.0:32769也可以使用
iptables -t nat -vnL,查看映射到哪個埠上了,-p選項會自動映射,# iptables -t nat -vnL 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 2 104 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:32768 to:172.17.0.2:80發現是映射到32769埠上了,這時訪問宿主機的32769埠,就會訪問到nginx容器,
當容器關閉后,再執行
iptables -t nat -vnL,發現映射又被自動洗掉了,
2,-p <hostPort>:<containerPort>
-
把容器埠<containerPort>映射到主機上所有網卡地址的埠<hostPort>上,
-
例子:把nginx的80埠,映射到主機上所有網卡地址的80埠上,
# docker run --name httpd --rm -p 80:80 ys/busybox:local3然后使用
docker port 容器名,查看映射到哪個埠上了,]# docker port httpd 80/tcp -> 0.0.0.0:80也可以使用
iptables -t nat -vnL,查看映射到哪個埠上了,-p選項會自動映射,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 2 104 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 to:172.17.0.2:80
3,-p <ip>::<containerPort>
-
把容器埠<containerPort>映射主機里指定網卡<ip>的動態埠,
-
例子:把nginx的80埠,映射到主機上網卡地址為10.210.65.99的動態埠上,
# docker run --name httpd --rm -p 10.210.65.99::80 ys/busybox:local3然后使用
docker port 容器名,查看映射到哪個埠上了,# docker port httpd 80/tcp -> 10.210.65.99:32768也可以使用
iptables -t nat -vnL,查看映射到哪個埠上了,-p選項會自動映射,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 0 0 DNAT tcp -- !docker0 * 0.0.0.0/0 10.210.65.99 tcp dpt:32768 to:172.17.0.2:80
4,-p <ip>:<hostPort>:<containerPort>
-
把容器埠<containerPort>映射主機里指定網卡<ip>的指定埠<hostPort>上,
-
例子:把nginx的80埠,映射到主機上網卡地址為10.210.65.99的8080埠上,
# docker run --name httpd --rm -p 10.210.65.99:8080:80 ys/busybox:local3然后使用
docker port 容器名,查看映射到哪個埠上了,docker port httpd 80/tcp -> 10.210.65.99:8080也可以使用
iptables -t nat -vnL,查看映射到哪個埠上了,-p選項會自動映射,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 0 0 DNAT tcp -- !docker0 * 0.0.0.0/0 10.210.65.99 tcp dpt:8080 to:172.17.0.2:80
5,-P
-
不需要寫埠號,docker會自動找到你要想暴露出去的埠號,比如是nginx容器的話,-P自動把80埠暴露出去,效果同1,如果image是用dockerfile做出來的話,并在dockerfile里寫了EXPOSE命令,那么指定-P會讓EXPOSE命令生效,默認dockerfile里寫了EXPOSE命令是不生效的,
-
例子:把nginx的80埠,映射到主機上所有網卡地址的一個動態分配的埠上,
# docker run --name httpd --rm -P nginx:stable-alpine然后使用
docker port 容器名,查看映射到哪個埠上了,# docker port httpd 80/tcp -> 0.0.0.0:32768也可以使用
iptables -t nat -vnL,查看映射到哪個埠上了,-P選項會自動映射,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 2 104 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:32768 to:172.17.0.2:80
額外:如果容器里的行程既監聽80埠,又監聽8080埠,則啟動容器的時候可以使用-p多次,
joined containers(聯盟式容器)
讓(user,mount, pid)成為獨立的命名空間,讓另外3個(uts, net, ipc)空間,共享使用,

一,和別的容器共享net命名空間的方法:使用【--networt containner:已經啟動了容器的name】
-
例子:先啟動一個busybox,名字叫b1;再啟動一個busybox,名字叫b2,并且共享b1的net命名空間,在b2里啟動一個httpd服務,然后在b1里用lo(127.0.0.1)去訪問在b2里啟動的httpd服務,
-
步驟1:先啟動一個busybox,名字叫b1,
# docker run --name b1 -it busybox:latest -
步驟2:再啟動一個busybox,名字叫b2,并在b2里啟動一個httpd服務,
# docker run --name b2 -it --network container:b1 busybox:latest / # echo "<h1>hello!</h1>" > /tmp/index.html / # httpd -h /tmp / # netstat -tnl Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 :::80 :::* LISTEN -
步驟3:在b1里用lo(127.0.0.1)去訪問在b2里啟動的httpd服務,
/ # wget -O - -q 127.0.0.1 <h1>hello!</h1>
-
-
驗證net命名空間是共享的,
- 使用
ifconfig,發現b1和b2的ip地址是相同的,
- 使用
-
驗證uts命名空間是共享的,
- 使用
hostname,發現主機名稱是相同的,
- 使用
-
ipc命名空間不知道用什么命令驗證,
-
驗證mount命名空間是不共享的,
在b2里創建了/tmp/index.html檔案,但是在b1的/tmp/目錄下沒有index.html檔案,
-
驗證pid命名空間是不共享的,
在b2里執行ps命令結果如下:
PID USER TIME COMMAND 1 root 0:00 sh 10 root 0:00 httpd -h /tmp在b1里執行ps命令結果如下:
PID USER TIME COMMAND 1 root 0:00 sh行程httpd的pid,在b1里面是沒有的,
-
不知道如何驗證user命名空間是不共享的,
二,和宿主機共享net命名空間的方法:使用【--networt host】
-
例子:使用宿主機的net命名空間,
# docker run --name b1 -it --rm --network host busybox:latest -
驗證user命名空間是不共享的,
宿主機里有用戶ys,在容器里無法看到用戶ys
/ # su ys su: unknown user ys
bridge containers(NAT橋式容器)
一,修改docker0橋自身的ip地址的方法:
添加【bip】到,檔案/etc/docker/daemon.json中,
bip:bridge ip,
{
"registry-mirrors": ["https://f61bammj.mirror.aliyuncs.com","https://registry.docker-cn.com"],
"bip": "192.0.0.1/16"
}
除了bip還可以添加一下資訊.
下面的除了dns,都可以通過bip自動算出來,
{
"fixed-cidr": "10.20.0.0/16",//子網
"fixed-cidr-v6": "2001.db8::/64",//ipv6子網
"mtu": "1500",
"default-gateway": "10.20.1.1",//網關
"default-gateway-v6": "",//ipv6網關
"dns": ["x.x.x.x","x.x.x.x","x.x.x.x"]//dns
}
如果容器不想使用宿主機的dns,則可以指定dns,容器默認是使用宿主機的dns,dns最大指定3個,
二,docker客戶端,可以訪問遠程的docker服務嗎?
由于,docker使用的通信技術是unix socker,
所以,默認是不支持遠程訪問docker服務的,
在本地訪問時,docker客戶端和服務器是通過/var/run/docker.sock檔案來通信的,[s]代表本地socker檔案,
srw-rw----. 1 root docker 0 Dec 4 17:39 /var/run/docker.sock
那么可不可以,讓docker客戶端,訪問非本機的docker服務的呢?是可以的,需要修改檔案/etc/docker/daemon.json,添加下面的設定,就可以讓外面的客戶端訪問了,
{
"hosts": ["tcp://0.0.0.0:2375", "unix:///var/run/docker.sock"]
}
[0.0.0.0:2375]:docker服務所在的機器上的所有網卡的IP地址都監聽2375埠,
注意:【unix:///var/run/docker.sock】要留著,不然本地的docker客戶都就無法訪問本地的docker服務端了,
重新啟動docker服務,用查看系統在監聽哪些埠的命令ss -tnl,去看2375埠是否是被監聽的,
# ss -tnl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 :::2375 :::*
然后,外面的客戶端使用:-H或者--host選項,指定IP地址和埠號來訪問docker服務端,
# docker -H 192.168.0.21:2375 images
-
在/etc/docker/daemon.json里加上hosts無法啟動docker服務的有沒有?
反正我是不能啟動docker服務了,
折騰了老半天,終于知道為什么了,
docker服務啟動時默認是加了【-H fd://】選項的,然后你又在/etc/docker/daemon.json里加上hosts,它倆就沖突了,只能留一個,
先不要在/etc/docker/daemon.json里加上hosts,然后啟動docker服務,用下面的命令驗證發現有【-H fd://】,如何解決呢?
# systemctl cat docker | grep Exec ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock ExecReload=/bin/kill -s HUP $MAINPID解決辦法:
-
步驟1:創建檔案:/etc/systemd/system/docker.service.d/docker.conf
-
步驟2:把下面的檔案內容寫入到上面的檔案,保存檔案,
[Service] ExecStart= ExecStart=/usr/bin/dockerd -
步驟3:重新啟動docker服務,就可以正常啟動了,
再使用
systemctl cat docker | grep Exec,發現最下面又多了2行,就說明把【-H fd://】覆寫掉了,# systemctl cat docker | grep Exec ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock ExecReload=/bin/kill -s HUP $MAINPID ExecStart= ExecStart=/usr/bin/dockerd -
三,創建自定義的橋
docker安裝完成,默認只有下面3種network,是否還有其他種類的network呢?
# docker network ls
NETWORK ID NAME DRIVER SCOPE
283d6e0a0dc9 bridge bridge local
d4106bd6d37e host host local
bbe1571b559b none null local
答案是有的,使用docker info可以看到,還有【ipvlan macvlan overlay】3種network,
# docker info
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
我們嘗試再創建一個bridge型別的network,先看一下命令幫助,
# docker network --help
Usage: docker network COMMAND
Manage networks
Commands:
connect Connect a container to a network
create Create a network
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
發現了create命令,再看一下,create命令的使用幫助,
# docker network create --help
Usage: docker network create [OPTIONS] NETWORK
Create a network
Options:
--attachable Enable manual container attachment
--aux-address map Auxiliary IPv4 or IPv6 addresses used by Network driver (default map[])
--config-from string The network from which copying the configuration
--config-only Create a configuration only network
-d, --driver string Driver to manage the Network (default "bridge")
--gateway strings IPv4 or IPv6 Gateway for the master subnet
--ingress Create swarm routing-mesh network
--internal Restrict external access to the network
--ip-range strings Allocate container ip from a sub-range
--ipam-driver string IP Address Management Driver (default "default")
--ipam-opt map Set IPAM driver specific options (default map[])
--ipv6 Enable IPv6 networking
--label list Set metadata on a network
-o, --opt map Set driver specific options (default map[])
--scope string Control the network's scope
--subnet strings Subnet in CIDR format that represents a network segment
- -d:知道network的型別,
- --subnet:ip和子網
- --gateway:網關
有了這些選項,就可以使用下面的命令創建一個network了,
# docker network create -d bridge --subnet "172.26.0.0/16" --gateway "172.26.0.1" mybr0
8e2468865ca64f8f16a697399613314a6615be23ed2ac58bd7d45a09f80b0778
[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
283d6e0a0dc9 bridge bridge local
d4106bd6d37e host host local
8e2468865ca6 mybr0 bridge local
bbe1571b559b none null local
發現上面多了一個剛剛創建的network,型別是bridge,名字是mybr0.
使用ifconfig看看,是否多了一個橋,一看果然多了一個名字為br-8e2468865ca6的橋,
# ifconfig
br-8e2468865ca6: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.26.0.1 netmask 255.255.0.0 broadcast 172.26.255.255
ether 02:42:12:85:e1:a0 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 192.0.0.1 netmask 255.255.0.0 broadcast 192.0.255.255
ether 02:42:a0:74:84:52 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
啟動一個容器,并使用剛剛創建的橋,試一試,
# docker run --name b1 --network mybr0 -it --rm busybox:latest
/ # ls
bin dev etc home proc root sys tmp usr var
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:1A:00:02
inet addr:172.26.0.2 Bcast:172.26.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:20 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:2282 (2.2 KiB) 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:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
/ #
發現ip地址是剛剛創建的橋給分配的ip地址,
問題來了,在docker0上啟動的容器,和在mybr0上啟動的容器,它們之間可以通信嗎?
如果內核的轉發功能打開了,并且iptables里的沒有阻止它們通信的規則,它們之間是可以通信的,
-
使用下面命令查看內核是否打開了轉發的功能,
# cat /proc/sys/net/ipv4/ip_forward 1值為1,說明內核的轉發功能已經打開了.
-
使用下面命令查看iptables里的規則,
# iptables -vnL
額外小知識,剛剛創建的mybr0時,橋的名字是隨機生成的,比如為br-8e2468865ca6,提供一個修改名字的命令,如果修改了名字,在啟動容器的如果指定了剛剛做成的network mybr0的話,容器會啟動失敗,理由是你把橋的名字br-8e2468865ca6修改了,docker就找不到mybr0對應的橋了,所有還是不要修改橋的名字,
修改橋br-8e2468865ca6名字的方法:
-
先讓網卡br-8e2468865ca6停止
ifconfig br-8e2468865ca6 down -
修改橋的名字
ip link set dev br-8e2468865ca6 name docker1 -
查看是否修改成功
ifconfig -a -
激活橋docker1
ifconfig docker1 up
洗掉橋的命令:ip link delete dev docker1
洗掉docker 里的network:docker network rm mybr0
c/c++ 學習互助QQ群:877684253

本人微信:xiaoshitou5854
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/102273.html
標籤:其他
上一篇:現在IT界的現狀???
