Docker基础 - 一个web应用实例

通过上文我们已经基本了解了docker的结构(仓库,镜像,容器)以及跑docker应用了;本文将通过介绍一个web应用:向你展示如何进行主机与web容器之间的通信,这是web开发者常用的;第二,贯穿上文中内容, 且为我们后续讲解网络提供基础。@pdai

一个web 应用运行和访问

运行一个 web 应用

我们只需要找一个webapp的镜像即可,无需自己再写个程序啥的。接下来让我们尝试使用 docker 构建一个 web 应用程序。

这里找了一个training/webapp,它是将在docker容器中运行一个 Python Flask web应用。

[root@pdai ~]# docker pull training/webapp
Using default tag: latest
latest: Pulling from training/webapp
Image docker.io/training/webapp:latest uses outdated schema1 manifest format. Please upgrade to a schema2 image for better future compatibility. More information at https://docs.docker.com/registry/spec/deprecated-schema-v1/
e190868d63f8: Pull complete
909cd34c6fd7: Pull complete
0b9bfabab7c1: Pull complete
a3ed95caeb02: Pull complete
10bbbc0fc0ff: Pull complete
fca59b508e9f: Pull complete
e7ae2541b15b: Pull complete
9dd97ef58ce9: Pull complete
a4c1b0cb7af7: Pull complete
Digest: sha256:06e9c1983bd6d5db5fba376ccd63bfa529e8d02f23d5079b8f74a616308fb11d
Status: Downloaded newer image for training/webapp:latest
docker.io/training/webapp:latest
[root@pdai ~]# docker images | grep webapp
training/webapp     latest              6fae60ef3446        4 years ago         349MB

紧接着,我们启动这个webapp

[root@pdai ~]# docker run -d -P training/webapp python app.py
ec3eb9ae218494d5aa5902c1ca4435733567b5e81319f02e5d2509d45cbc25da
[root@pdai ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                     NAMES
ec3eb9ae2184        training/webapp     "python app.py"     18 seconds ago      Up 17 seconds       0.0.0.0:32768->5000/tcp   gifted_agnesi

参数说明:

  • -d:让容器在后台运行。
  • -P:将容器内部使用的网络端口映射到我们使用的主机上。

访问webapp

我们注意看上述PORTS部分为0.0.0.0:32769->5000/tcp

Docker 开放了 5000 端口(默认 Python Flask 端口)映射到主机端口 32768 上。

  • 从主机上看,它应该暴露了端口32768

所以我们来验证下:

[root@pdai ~]# netstat | grep 32768
[root@pdai ~]# netstat -nltp | grep 32768
tcp6       0      0 :::32768                :::*                    LISTEN      2227/docker-proxy
[root@pdai ~]# curl localhost:32768
Hello world!

这意味着,你浏览器你可以输入localhost:32768访问这个页面。

  • 从容器内部看,它应该有一个端口5000

我们再进容器验证下:

[root@pdai ~]# docker exec -it ec3eb9ae2184 /bin/bash
root@ec3eb9ae2184:/opt/webapp# netstat -nltp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:5000            0.0.0.0:*               LISTEN      1/python

所以我们的理解是对的。

设置自定义映射端口

我们发现,通过 -P参数映射到主机上的端口是随机,能否自定义端口呢?

我们可以通过 -p 参数来设置不一样的端口;为了对比,我们再起一个容器实例:

[root@pdai ~]# docker run -d -p 5001:5000 training/webapp python app.py
5da3588d5bc43a9ed3aa61fb87f98220c9719d2879b616404d443aaae6cee77a
[root@pdai ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                     NAMES
5da3588d5bc4        training/webapp     "python app.py"     33 seconds ago      Up 31 seconds       0.0.0.0:5001->5000/tcp    hopeful_bardeen
ec3eb9ae2184        training/webapp     "python app.py"     22 minutes ago      Up 22 minutes       0.0.0.0:32768->5000/tcp   gifted_agnesi
[root@pdai ~]# netstat -nltp | grep 5001
tcp6       0      0 :::5001                 :::*                    LISTEN      2591/docker-proxy
[root@pdai ~]# curl localhost:5001
Hello world!

所以你看到跑了两个内部端口都是5000的web实例,新的容器内部的 5000 端口映射到我们本地主机的 5001 端口上。

其它常用功能

查看web 应用网络端口

通过 docker ps 命令可以查看到容器的端口映射,docker 还提供了另一个快捷方式 docker port,使用 docker port 可以查看指定 (ID 或者名字)容器的某个确定端口映射到宿主机的端口号。

上面我们创建的 web 应用容器 ID 为 5da3588d5bc4 名字为 hopeful_bardeen。

我可以这样查看容器端口的映射情况:

[root@pdai ~]# docker port 5da3588d5bc4
5000/tcp -> 0.0.0.0:5001
[root@pdai ~]# docker port hopeful_bardeen
5000/tcp -> 0.0.0.0:5001

查看 WEB 应用程序日志

docker logs [ID或者名字] 可以查看容器内部的标准输出。

[root@pdai ~]# docker port hopeful_bardeen
5000/tcp -> 0.0.0.0:5001
[root@pdai ~]# docker logs -f hopeful_bardeen
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
172.17.0.1 - - [18/Feb/2020 09:08:31] "GET / HTTP/1.1" 200 -
^C

参数说明:

  • -f: 让 docker logs 像使用 tail -f 一样来输出容器内部的标准输出。

从上面,我们可以看到应用程序使用的是 5000 端口并且能够查看到应用程序的访问日志。

查看WEB应用程序容器的进程

我们还可以使用 docker top 来查看容器内部运行的进程

[root@pdai ~]# docker top hopeful_bardeen
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                2614                2597                0                   17:07               ?                   00:00:00            python app.py

检查 WEB 应用程序

使用 docker inspect 来查看 Docker 的底层信息。它会返回一个 JSON 文件记录着 Docker 容器的配置和状态信息。

[root@pdai ~]# docker inspect hopeful_bardeen
[
    {
        "Id": "5da3588d5bc43a9ed3aa61fb87f98220c9719d2879b616404d443aaae6cee77a",
        "Created": "2020-02-18T09:07:32.827193286Z",
        "Path": "python",
        "Args": [
            "app.py"
        ],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 2614,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2020-02-18T09:07:33.374368448Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        "Image": "sha256:6fae60ef344644649a39240b94d73b8ba9c67f898ede85cf8e947a887b3e6557",
        "ResolvConfPath": "/var/lib/docker/containers/5da3588d5bc43a9ed3aa61fb87f98220c9719d2879b616404d443aaae6cee77a/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/5da3588d5bc43a9ed3aa61fb87f98220c9719d2879b616404d443aaae6cee77a/hostname",
        "HostsPath": "/var/lib/docker/containers/5da3588d5bc43a9ed3aa61fb87f98220c9719d2879b616404d443aaae6cee77a/hosts",
        "LogPath": "/var/lib/docker/containers/5da3588d5bc43a9ed3aa61fb87f98220c9719d2879b616404d443aaae6cee77a/5da3588d5bc43a9ed3aa61fb87f98220c9719d2879b616404d443aaae6cee77a-json.log",
        "Name": "/hopeful_bardeen",
        "RestartCount": 0,
        "Driver": "overlay2",
        "Platform": "linux",
        "MountLabel": "",
        "ProcessLabel": "",
        "AppArmorProfile": "",
        "ExecIDs": null,
        "HostConfig": {
            "Binds": null,
            "ContainerIDFile": "",
            "LogConfig": {
                "Type": "json-file",
                "Config": {}
            },
            "NetworkMode": "default",
            "PortBindings": {
                "5000/tcp": [
                    {
                        "HostIp": "",
                        "HostPort": "5001"
                    }
                ]
            },
            "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": {
                "LowerDir": "/var/lib/docker/overlay2/c6594e5b70feca02eb4b90ac75aba711f36378d5cb9853ffca1ec92f9d0c3e14-init/diff:/var/lib/docker/overlay2/d4690a06236a3857a2a51ab84c61992e50ea3e1a613f4793334916604ea0dfa0/diff:/var/lib/docker/overlay2/c45d0215cd2076174f38fea5003c3ff11a5ba2df2141d9d069f4bf32dac9a22a/diff:/var/lib/docker/overlay2/1cf63068912234a1f4c861f58f155423c87193c6e438948db493687d4da4f0a0/diff:/var/lib/docker/overlay2/55e4ecb04b1ff8d048bc75bb8698c782c813d45caa6f0d82ac6c49adec24bead/diff:/var/lib/docker/overlay2/27fa0dc314b851b8d2f0386d230a725f57117f9f1ccdb49ca27f5ad424cb4a90/diff:/var/lib/docker/overlay2/65a5a082188d9e0b9aaf09c2e9c3b3f8141f74c781996680dfaca63d81672cdf/diff:/var/lib/docker/overlay2/658a33c92cf114ee4cbc10f117207a0c813e39a908acc014fbce1783a28bc654/diff:/var/lib/docker/overlay2/e5b5c9e0abc43ff2750dcd33decc65d90d733b18f2626b91c500d803d7fe189b/diff:/var/lib/docker/overlay2/0b5181e429a89f6ab291e090b972e11718e4f63158ed60af1fce18095d0352a6/diff:/var/lib/docker/overlay2/f7c0405739bb58fdfa9af402a72507b78bc2a48b0d74356dad59495906b6e0e5/diff:/var/lib/docker/overlay2/073c45ae4a6ff27950a1dd969a675d3dcdc18392bb205ddde5913fcc10a751ef/diff:/var/lib/docker/overlay2/f92534844c8cc5b950ea36369b8e4a7dd7f7749e73483908e5d129bf5c26442f/diff:/var/lib/docker/overlay2/477378381d03c4b347d7b9224c4c9023b5dfbfde32022c7eb8af32e7a01b88b2/diff",
                "MergedDir": "/var/lib/docker/overlay2/c6594e5b70feca02eb4b90ac75aba711f36378d5cb9853ffca1ec92f9d0c3e14/merged",
                "UpperDir": "/var/lib/docker/overlay2/c6594e5b70feca02eb4b90ac75aba711f36378d5cb9853ffca1ec92f9d0c3e14/diff",
                "WorkDir": "/var/lib/docker/overlay2/c6594e5b70feca02eb4b90ac75aba711f36378d5cb9853ffca1ec92f9d0c3e14/work"
            },
            "Name": "overlay2"
        },
        "Mounts": [],
        "Config": {
            "Hostname": "5da3588d5bc4",
            "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": "66e1f111a5d7acca71f0e9e24516a6945bca428f55ac1eab1576c99bde16190c",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {
                "5000/tcp": [
                    {
                        "HostIp": "0.0.0.0",
                        "HostPort": "5001"
                    }
                ]
            },
            "SandboxKey": "/var/run/docker/netns/66e1f111a5d7",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "794d5e97cd3bbb62c8a7a850f125404d174ecc45df4e704dbee403b1be7a2835",
            "Gateway": "172.17.0.1",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "172.17.0.3",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
            "MacAddress": "02:42:ac:11:00:03",
            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "b8c5abdb0becacfa1bfa1d72e2e663fb0157b62a9b8bee37e2607211722713cc",
                    "EndpointID": "794d5e97cd3bbb62c8a7a850f125404d174ecc45df4e704dbee403b1be7a2835",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.3",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:03",
                    "DriverOpts": null
                }
            }
        }
    }
]

停止 WEB 应用容器

再复习下docker的停止

[root@pdai ~]# docker stop hopeful_bardeen
hopeful_bardeen
[root@pdai ~]# docker ps -a | grep 'hopeful_bardeen'
5da3588d5bc4        training/webapp      "python app.py"      13 minutes ago      Exited (137) 12 seconds ago                             hopeful_bardeen

重启WEB应用容器

已经停止的容器,我们可以使用命令 docker start 或者docker restart 来启动。

[root@pdai ~]# docker restart hopeful_bardeen
hopeful_bardeen
[root@pdai ~]# docker ps -a | grep hopeful_bardeen
5da3588d5bc4        training/webapp      "python app.py"      14 minutes ago      Up 10 seconds            0.0.0.0:5001->5000/tcp    hopeful_bardeen

移除WEB应用容器

我们可以使用 docker rm 命令来删除不需要的容器

我们上文也讲过,如果是启动着的docker实例,需要加-f,强制(force)删除。

[root@pdai ~]# docker ps -a | grep hopeful_bardeen
5da3588d5bc4        training/webapp      "python app.py"      14 minutes ago      Up 10 seconds            0.0.0.0:5001->5000/tcp    hopeful_bardeen
[root@pdai ~]# docker rm -f hopeful_bardeen
hopeful_bardeen
[root@pdai ~]# docker ps -a | grep hopeful_bardeen
[root@pdai ~]#

与其它容器(DB容器)互联

上述是一个web单一容器通过端口映射,可以通过主机端口访问容器;那么如果需要访问数据库,就涉及到容器互联。

与数据库容器互联

  • 先停止上述的web容器, 且清理所有不用的容器
[root@pdai ~]# docker ps -a
CONTAINER ID        IMAGE                COMMAND              CREATED             STATUS                    PORTS                     NAMES
ec3eb9ae2184        training/webapp      "python app.py"      18 hours ago        Up 18 hours               0.0.0.0:32768->5000/tcp   gifted_agnesi
11de9755a084        pdai/ubuntu:v2.0.2   "/bin/bash"          24 hours ago        Exited (0) 24 hours ago                             pdai-ubuntu-202
57bd797570b6        pdai/ubuntu:v2.0.2   "--name pdai-test"   24 hours ago        Created                                             sharp_brahmagupta
[root@pdai ~]# docker stop ec3eb9ae2184
ec3eb9ae2184
[root@pdai ~]# docker ps -a
CONTAINER ID        IMAGE                COMMAND              CREATED             STATUS                        PORTS               NAMES
ec3eb9ae2184        training/webapp      "python app.py"      18 hours ago        Exited (137) 29 seconds ago                       gifted_agnesi
11de9755a084        pdai/ubuntu:v2.0.2   "/bin/bash"          24 hours ago        Exited (0) 24 hours ago                           pdai-ubuntu-202
57bd797570b6        pdai/ubuntu:v2.0.2   "--name pdai-test"   24 hours ago        Created                                           sharp_brahmagupta
[root@pdai ~]# docker container prune
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
Deleted Containers:
ec3eb9ae218494d5aa5902c1ca4435733567b5e81319f02e5d2509d45cbc25da
11de9755a08402d963d263a559a7daf48f4a2188398f258641240b5eb50fbc89
57bd797570b68b6587b16809889e6e8f710ec7a934229aa6391add02f758e036

Total reclaimed space: 89B
[root@pdai ~]#
  • 创建一个新的数据库容器。
[root@pdai ~]# docker run -d --name db training/postgres
Unable to find image 'training/postgres:latest' locally
latest: Pulling from training/postgres
Image docker.io/training/postgres:latest uses outdated schema1 manifest format. Please upgrade to a schema2 image for better future compatibility. More information at https://docs.docker.com/registry/spec/deprecated-schema-v1/
a3ed95caeb02: Pull complete
6e71c809542e: Pull complete
2978d9af87ba: Pull complete
e1bca35b062f: Pull complete
500b6decf741: Pull complete
74b14ef2151f: Pull complete
7afd5ed3826e: Pull complete
3c69bb244f5e: Pull complete
d86f9ec5aedf: Pull complete
010fabf20157: Pull complete
Digest: sha256:a945dc6dcfbc8d009c3d972931608344b76c2870ce796da00a827bd50791907e
Status: Downloaded newer image for training/postgres:latest
d992e3c761e00649eb436b88c737adc54093b76119af0fb7878596b523f743ca
[root@pdai ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
d992e3c761e0        training/postgres   "su postgres -c '/us…"   9 seconds ago       Up 7 seconds        5432/tcp            db
  • db 容器和 web 容器建立互联关系
[root@pdai ~]# docker run -d -p 5001:5000 --name web --link db:db training/webapp python app.py
1cbc9aeba2a8a826d460ecb49de17ddf8ac336e150c752a3c762fd38a3e15254
[root@pdai ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
1cbc9aeba2a8        training/webapp     "python app.py"          5 seconds ago       Up 4 seconds        0.0.0.0:5001->5000/tcp   web
d992e3c761e0        training/postgres   "su postgres -c '/us…"   7 minutes ago       Up 7 minutes        5432/tcp                 db

--link 参数的格式为 --link name:alias,其中 name 是要链接的容器的名称,alias 是这个连接的别名。

Docker 在两个互联的容器之间创建了一个安全隧道,而且不用映射它们的端口到宿主主机上。在启动 db 容器的时候并没有使用 -p 和 -P 标记,从而避免了暴露数据库端口到外部网络上。

容器公开的连接信息

Docker 通过 2 种方式为容器公开连接信息:

  • 环境变量
  • 更新 /etc/hosts 文件

环境变量

使用 env 命令来查看 web 容器的环境变量

[root@pdai ~]# docker exec -it web /bin/bash
root@1cbc9aeba2a8:/opt/webapp# env
HOSTNAME=1cbc9aeba2a8
DB_NAME=/web/db
DB_PORT_5432_TCP_ADDR=172.17.0.2
DB_PORT=tcp://172.17.0.2:5432
DB_PORT_5432_TCP=tcp://172.17.0.2:5432
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/opt/webapp
DB_PORT_5432_TCP_PORT=5432
SHLVL=1
HOME=/root
DB_PORT_5432_TCP_PROTO=tcp
DB_ENV_PG_VERSION=9.3
_=/usr/bin/env

其中 DB_ 开头的环境变量是供 web 容器连接 db 容器使用,前缀采用大写的连接别名。

hosts 文件

除了环境变量,Docker 还添加 host 信息到父容器的 /etc/hosts 的文件。下面是父容器 web 的 hosts 文件

root@1cbc9aeba2a8:/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.2      db d992e3c761e0
172.17.0.3      1cbc9aeba2a8
root@1cbc9aeba2a8:/opt/webapp#

这里有 2 个 hosts:

  • 第一个, 172.17.0.2 db d992e3c761e0 表示 db 容器的 ip, ID和Name
  • 第二个,172.17.0.3 1cbc9aeba2a8 表示 web 容器的 ip, ID

可以在 web 容器中安装 ping 命令来测试跟db容器的连通。

root@1cbc9aeba2a8:/opt/webapp# apt-get install -yqq inetutils-ping
(Reading database ... 18233 files and directories currently installed.)
Removing ubuntu-minimal (1.325) ...
Removing iputils-ping (3:20121221-4ubuntu1.1) ...
Selecting previously unselected package inetutils-ping.
(Reading database ... 18221 files and directories currently installed.)
Preparing to unpack .../inetutils-ping_2%3a1.9.2-1_amd64.deb ...
Unpacking inetutils-ping (2:1.9.2-1) ...
Setting up inetutils-ping (2:1.9.2-1) ...
root@1cbc9aeba2a8:/opt/webapp# ping db
PING db (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: icmp_seq=0 ttl=64 time=0.110 ms
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.092 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.094 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.104 ms
64 bytes from 172.17.0.2: icmp_seq=4 ttl=64 time=0.111 ms
64 bytes from 172.17.0.2: icmp_seq=5 ttl=64 time=0.093 ms
64 bytes from 172.17.0.2: icmp_seq=6 ttl=64 time=0.095 ms
^C--- db ping statistics ---
7 packets transmitted, 7 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.092/0.100/0.111/0.000 ms

用 ping 来测试db容器,它会解析成 172.17.0.2。

当然,你还可以ping db容器的ID或者内部IP, 结果是一样的。

root@1cbc9aeba2a8:/opt/webapp# ping -t 4 d992e3c761e0
ping: unsupported packet type: 4
root@1cbc9aeba2a8:/opt/webapp# ping d992e3c761e0
PING db (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: icmp_seq=0 ttl=64 time=0.089 ms
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.093 ms
^C--- db ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.089/0.091/0.093/0.000 ms
root@1cbc9aeba2a8:/opt/webapp# ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: icmp_seq=0 ttl=64 time=0.094 ms
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.103 ms
^C--- 172.17.0.2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.094/0.099/0.103/0.000 ms
root@1cbc9aeba2a8:/opt/webapp#

用户可以链接多个父容器到子容器,比如可以链接多个 web 到 db 容器上。