七、【Docker筆記】Docker中網路基礎配置
- 2020 年 4 月 11 日
- 筆記
一個系統一般都包含多個服務組件,這些大量的服務組件不可能放在同一個容器中,這就需要多個容器之間可以互相通訊。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