七、【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 -  

image-20200411113029092

2、映射所有介面地址

使用 hostPort:containerPort 格式可將本地的埠映射到容器的埠。

# 將本地的 5000 埠映射到容器的 5000 埠  $ sudo docker run -d -p 5000:5000 training/webapp python app.py  bc4f7d1a99bf5.....  # 訪問宿主機的5000埠  

image-20200411113822389

當然 -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!  

image-20200411114545198

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