七、【Docker筆記】Docker中網路基礎配置
一個系統一般都包含多個服務元件,這些大量的服務元件不可能放在同一個容器中,這就需要多個容器之間可以互相通訊。Docker提供了兩種方式來實現網路服務:對映容器埠到宿主主機、容器互聯機制。
一、埠對映實現訪問容器
1、從外部訪問容器中的應用
在啟動容器時,若我們不指定某些引數,則我們在容器外部是無法通過網路來訪問容器中的應用和服務的。若想讓容器中的應用可以被外部訪問,則在啟動容器時,需要加入 -P / -p 來指定埠的對映。若我們直接加上 -P 後面不指定埠,則Docker會隨機對映一個 49000 ~ 49900 的埠到容器內部開放的網路埠:
# 啟動一個web應用,讓其在外部可訪問 $ sudo docker run -d -P training/webapp python app.py 61d7b0ed72bd...... $ sudo docker run -d training/webapp python app.py 16ddce67f62a...... # 檢視當前正在執行的容器 $ sudo docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 16ddce67f62a training/webapp "python app.py" 5 seconds ago Up 3 seconds 5000/tcp cool_mestorf 61d7b0ed72bd training/webapp "python app.py" 16 seconds ago Up 14 seconds 0.0.0.0:32768->5000/tcp quizzical_cray # 訪問 帶有 -P 引數的容器如下,不帶 -P 啟動的容器我們無法訪問。訪問之後,我們來檢視日誌 $ sudo docker logs -f 61d7b0ed72bd * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit) 192.168.0.1 - - [11/Apr/2020 03:29:53] "GET / HTTP/1.1" 200 - 192.168.0.1 - - [11/Apr/2020 03:29:53] "GET /favicon.ico HTTP/1.1" 404 -
2、對映所有介面地址
使用 hostPort:containerPort 格式可將本地的埠對映到容器的埠。
# 將本地的 5000 埠對映到容器的 5000 埠
$ sudo docker run -d -p 5000:5000 training/webapp python app.py
bc4f7d1a99bf5.....
# 訪問宿主機的5000埠
當然 -p 引數可以多次使用。
# 在啟動容器時繫結多個宿主機埠到容器埠
$ sudo docker run -d -p 5000:5000 -p 3000:80 training/webapp python app.py
3、對映到指定地址的指定埠
我們也可使用 ip:hostPort:containerPort 格式來指定對映一個特定地址的特定埠到容器中的埠。
$ sudo docker run -d -p 127.0.0.1:5000:5000 training/webapp python app.py
#此時訪問宿主機對應的5000埠
$ curl http://192.168.0.128:5000/
curl: (7) Failed connect to 192.168.0.128:5000; 拒絕連線
$ curl http://127.0.0.1:5000/
Hello world!
4、對映到指定地址的任意埠
使用 ip::containerPort 來繫結宿主機的任意埠到容器的指定埠。
# 0. 執行容器 $ sudo docker run -d -p 127.0.0.1::5000 training/webapp python app.py c54763267e956fe15ab3aedd14893a4269c19995bf3d56f9519b68ddffccb9cd # 1. 檢視執行容器資訊 $ sudo docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c54763267e95 training/webapp "python app.py" 14 seconds ago Up 13 seconds 127.0.0.1:32768->5000/tcp angry_merkle # 2. 訪問 127.0.0.1:32768 $ curl 127.0.0.1:32768 Hello world!
從上面通過 docker ps 我們可知,對應容器中的埠都是 tcp的,其實我們可以指定對映為udp埠。
$ sudo docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
950a6d4c7f6c training/webapp "python app.py" 48 seconds ago Up 47 seconds 5000/tcp, 127.0.0.1:5000->5000/udp compassionate_ganguly
5、檢視對映埠配置
使用 docker port 來檢視當前對映的埠配置,也可檢視繫結地址。
$ sudo docker port 705e17a35936
5000/tcp -> 127.0.0.1:5000
# 容器有自己的ip和網路資訊,若想了解容器的網路資訊
$ sudo docker inspect 705e17a35936
[
{
"Id": "705e17a3593616ff5f4cd47057e5be83f5f344e69e9cb5665855f2acfe16cb54",
"Created": "2020-04-11T03:44:34.703449795Z",
"Path": "python",
"Args": [
"app.py"
],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 2659,
"ExitCode": 0,
"Error": "",
"StartedAt": "2020-04-11T04:01:25.917279404Z",
"FinishedAt": "2020-04-11T03:55:26.502040545Z"
},
"Image": "sha256:6fae60ef344644649a39240b94d73b8ba9c67f898ede85cf8e947a887b3e6557",
"ResolvConfPath": "/var/lib/docker/containers/705e17a3593616ff5f4cd47057e5be83f5f344e69e9cb5665855f2acfe16cb54/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/705e17a3593616ff5f4cd47057e5be83f5f344e69e9cb5665855f2acfe16cb54/hostname",
"HostsPath": "/var/lib/docker/containers/705e17a3593616ff5f4cd47057e5be83f5f344e69e9cb5665855f2acfe16cb54/hosts",
"LogPath": "/var/lib/docker/containers/705e17a3593616ff5f4cd47057e5be83f5f344e69e9cb5665855f2acfe16cb54/705e17a3593616ff5f4cd47057e5be83f5f344e69e9cb5665855f2acfe16cb54-json.log",
"Name": "/sleepy_pike",
"RestartCount": 0,
"Driver": "devicemapper",
"Platform": "linux",
"MountLabel": "",
"ProcessLabel": "",
"AppArmorProfile": "",
"ExecIDs": null,
"HostConfig": {
"Binds": null,
"ContainerIDFile": "",
"LogConfig": {
"Type": "json-file",
"Config": {}
},
"NetworkMode": "default",
"PortBindings": {
"5000/tcp": [
{
"HostIp": "127.0.0.1",
"HostPort": "5000"
}
]
},
"RestartPolicy": {
"Name": "no",
"MaximumRetryCount": 0
},
"AutoRemove": false,
"VolumeDriver": "",
"VolumesFrom": null,
"CapAdd": null,
"CapDrop": null,
"Capabilities": null,
"Dns": [],
"DnsOptions": [],
"DnsSearch": [],
"ExtraHosts": null,
"GroupAdd": null,
"IpcMode": "private",
"Cgroup": "",
"Links": null,
"OomScoreAdj": 0,
"PidMode": "",
"Privileged": false,
"PublishAllPorts": false,
"ReadonlyRootfs": false,
"SecurityOpt": null,
"UTSMode": "",
"UsernsMode": "",
"ShmSize": 67108864,
"Runtime": "runc",
"ConsoleSize": [
0,
0
],
"Isolation": "",
"CpuShares": 0,
"Memory": 0,
"NanoCpus": 0,
"CgroupParent": "",
"BlkioWeight": 0,
"BlkioWeightDevice": [],
"BlkioDeviceReadBps": null,
"BlkioDeviceWriteBps": null,
"BlkioDeviceReadIOps": null,
"BlkioDeviceWriteIOps": null,
"CpuPeriod": 0,
"CpuQuota": 0,
"CpuRealtimePeriod": 0,
"CpuRealtimeRuntime": 0,
"CpusetCpus": "",
"CpusetMems": "",
"Devices": [],
"DeviceCgroupRules": null,
"DeviceRequests": null,
"KernelMemory": 0,
"KernelMemoryTCP": 0,
"MemoryReservation": 0,
"MemorySwap": 0,
"MemorySwappiness": null,
"OomKillDisable": false,
"PidsLimit": null,
"Ulimits": null,
"CpuCount": 0,
"CpuPercent": 0,
"IOMaximumIOps": 0,
"IOMaximumBandwidth": 0,
"MaskedPaths": [
"/proc/asound",
"/proc/acpi",
"/proc/kcore",
"/proc/keys",
"/proc/latency_stats",
"/proc/timer_list",
"/proc/timer_stats",
"/proc/sched_debug",
"/proc/scsi",
"/sys/firmware"
],
"ReadonlyPaths": [
"/proc/bus",
"/proc/fs",
"/proc/irq",
"/proc/sys",
"/proc/sysrq-trigger"
]
},
"GraphDriver": {
"Data": {
"DeviceId": "129",
"DeviceName": "docker-253:0-67518837-48c42a21a8b771836053ba03b954ab6a882146ed580b81bd2c540459127e6655",
"DeviceSize": "10737418240"
},
"Name": "devicemapper"
},
"Mounts": [],
"Config": {
"Hostname": "705e17a35936",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"5000/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"python",
"app.py"
],
"Image": "training/webapp",
"Volumes": null,
"WorkingDir": "/opt/webapp",
"Entrypoint": null,
"OnBuild": null,
"Labels": {}
},
"NetworkSettings": {
"Bridge": "",
"SandboxID": "6ec9b1986ffaa317d9d962b615025b8f94c926f4a83eb68c929d964655b74022",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {
"5000/tcp": [
{
"HostIp": "127.0.0.1",
"HostPort": "5000"
}
]
},
"SandboxKey": "/var/run/docker/netns/6ec9b1986ffa",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "8e70e95f6e5a4d9d6164d61c2d0807430bdaaa2342ac6175dd22964d8bc74cbd",
"Gateway": "172.17.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"MacAddress": "02:42:ac:11:00:02",
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "6dffe521ab44a55127f8f43c5a542dc7969cfbfc85a17e5692bf58472261e6cf",
"EndpointID": "8e70e95f6e5a4d9d6164d61c2d0807430bdaaa2342ac6175dd22964d8bc74cbd",
"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
}
}
}
}
]
二、容器互聯實現容器間通訊
容器的連線系統是除了埠對映以外的另一種可以與容器中應用互動的方式。它會在源與接收容器之間建立一個隧道,接收容器可以看到源容器指定的資訊。
1、自定義容器命名
連線系統是依據容器的名稱來執行,這就要求我們在建立容器的時候自定義一個容器名稱,系統自動生成的名稱不利於理解。自定義的容器命名比較好記,且在連線其他容器的時候,可以根據名稱來作為很好的參考。可使用 --name 來標記容器名稱。
$ sudo docker run -d -P --name web training/webapp python app.py
7abf01b7507d46e88412206d0cdd26d38248a4bbd5fca9ba0e7c68070b1f6d73
# 可使用以下兩種方式來檢視容器的名稱
$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7abf01b7507d training/webapp "python app.py" 41 seconds ago Up 41 seconds 0.0.0.0:32769->5000/tcp web
# 或
$ sudo docker inspect -f "{{.Name}}" 7abf01b7507d
/web
2、容器互聯
使用 --link 引數可讓容器之間安全的互動。語法格式為:--link name:alias 即需要連線的容器名稱:連線別名
# 0. 建立資料庫容器
$ sudo docker run -d --name db training/postgres
26690fc69651a03dbcc1e8674c0258f8b2e54ddf22fcf5c5bf7f6d267543df04
# 1. 刪除之前的 web 容器,可使用 -f 來強制刪除
$ sudo docker rm -f 7abf01b7507d
7abf01b7507d
# 2. 建立新的web容器,並讓其連線到剛才建立的資料庫容器
$ sudo docker run -d -P --name web --link db:db training/webapp python app.py
699cd56b6b5444e34a83bfe363bd448711150c020a116dd8200f042296690ed4
# 3. 檢視容器的連線資訊
$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
699cd56b6b54 training/webapp "python app.py" 10 seconds ago Up 9 seconds 0.0.0.0:32770->5000/tcp web
26690fc69651 training/postgres "su postgres -c '/us…" 5 minutes ago Up 5 minutes 5432/tcp db,web/db
Docker可以通過兩種方式來為容器公開連線資訊:環境變數、更新 /etc/hosts 檔案。
# 使用 env 命令來檢視web容器的環境
$ sudo docker run --rm --name tmp_web --link db:db training/webapp env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=ffb7ed25135e
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=/tmp_web/db
DB_ENV_PG_VERSION=9.3
HOME=/root
# 檢視父容器web的hosts檔案
$ sudo docker run -ti --rm --link db:db training/webapp /bin/bash
root@d78ad4411828:/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 26690fc69651 # db容器的ip和主機
172.17.0.4 d78ad4411828 # web容器的ip和主機
# 此時我們處於web容器內部,可以使用 ping 來檢視與db容器網路是否暢通
root@d78ad4411828:/opt/webapp# ping db
PING db (172.17.0.3) 56(84) bytes of data.
64 bytes from db (172.17.0.3): icmp_seq=1 ttl=64 time=0.060 ms
64 bytes from db (172.17.0.3): icmp_seq=2 ttl=64 time=0.042 ms
64 bytes from db (172.17.0.3): icmp_seq=3 ttl=64 time=0.093 ms
64 bytes from db (172.17.0.3): icmp_seq=4 ttl=64 time=0.055 ms
# 若web容器中沒有 ping 命令可使用以下命令來安裝
root@d78ad4411828:/opt/webapp# apt-get install -yqq inetutils-ping