1,啓動container時,指定網絡鏈接方式:--network bridge/host/none
html
# docker container run --name b1 --network bridge -it --rm busybox:latest
2,查看主機名字命令:hostname
,若是啓動容器時,沒有指定主機名稱,則容器id(CONTAINER ID)和容器的主機名稱是相同的。node
啓動容器的時候,指定主機名稱:-h name
nginx
# docker container run --name b1 --network bridge -it --rm -h host1 busybox:latest
3,查看本機的hosts文件,cat /etc/hosts
c++
# 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地址的。docker
查看一下DNS server的ip:cat /etc/resolv.conf
shell
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
作實驗。json
# 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通的。ubuntu
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
解決辦法:在啓動容器時,使用-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屢次。
讓(user,mount, pid)成爲獨立的命名空間,讓另外3個(uts, net, ipc)空間,共享使用。
例子:先啓動一個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命名空間。
# docker run --name b1 -it --rm --network host busybox:latest
驗證user命名空間是不共享的。
宿主機裏有用戶ys,在容器裏沒法看到用戶ys
/ # su ys su: unknown user ys
添加【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使用的通訊技術是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
有了這些選項,就可使用下面的命令建立一個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中止
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 rm mybr0