数据管理

在容器中管理数据主要由两种方式

  • 数据卷 (Volumes)
  • 挂载主机目录 (Bind mounts)

数据卷

数据卷 是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性

  • 数据卷可以在容器之间共享和重用
  • 对数据卷的修改会立马生效
  • 对数据卷的更新不会影响镜像
  • 数据卷默认会一直存在,即使容器被删除

数据卷的使用,类似于 Linux 下对目录或文件进行 mount,镜像中的被指定为挂载点的目录中的文件会隐藏掉,能显示看的是挂载的 数据卷

创建一个数据卷

$ docker volume create bvol

查看所有数据卷

$ docker volume ls
local               bvol

在主机里查看指定数据卷信息

$ docker volume inspect bvol
[
    {
        "CreatedAt": "2019-06-13T10:24:51Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/bvol/_data",
        "Name": "bvol",
        "Options": {},
        "Scope": "local"
    }
]

启动一个挂载数据卷的容器

使用 --mount 标记来将数据卷挂载到容器里。在一次 docker run 中可以挂载多个数据卷

$ docker run -d -ti \
    --name web
    # -v bvol:/etc  \
    --mount source=bvol,target=/etc \
    alpine \
    /bin/echo haozibi 

查看数据卷具体信息

$ docker inspect web
# 具体信息在 Mounts 下
"Mounts": [
            {
                "Type": "volume",
                "Name": "bvol",
                "Source": "/var/lib/docker/volumes/bvol/_data",
                "Destination": "/etc",
                "Driver": "local",
                "Mode": "z",
                "RW": true,
                "Propagation": ""
            }
        ],

删除数据卷

$ docker volume rm bvol

数据卷是被设计用来持久化数据的,它的生命周期独立于容器,Docker 不会在容器被删除后自动删除 数据卷,并且也不存在垃圾回收这样的机制来处理没有任何容器引用的 数据卷。如果需要在删除容器的同时移除数据卷。可以在删除容器的时候使用 docker rm -v 这个命令。

清除无主数据卷

$ docker volume prune

挂载主机目录

挂载一个主机目录作为数据卷

使用 --mount 标记可以指定挂载一个本地主机的目录到容器中

$ docker run -d -P \
    --name web \
    # -v /src/webapp:/opt/webapp \
    --mount type=bind,source=/src/webapp,target=/opt/webapp \
    training/webapp \
    python app.py

上面的命令加载主机的 /src/webapp 目录到容器的 /opt/webapp 目录。这个功能在进行测试的时候十分方便,比如用户可以放置一些程序到本地目录中,来查看容器是否正常工作。

本地目录的路径必须是绝对路径,以前使用 -v 参数时如果本地目录不存在 Docker 会自动为你创建一个文件夹,现在使用 --mount 参数时如果本地目录不存在,Docker 会报错。

Docker 挂载主机目录的默认权限是 读写,用户也可以通过增加 readonly 指定为 只读

$ docker run -d -P \
    --name web \
    # -v /src/webapp:/opt/webapp:ro \
    --mount type=bind,source=/src/webapp,target=/opt/webapp,readonly \
    training/webapp \
    python app.py

加了 readonly 之后,就挂载为 只读 了。如果你在容器内 /opt/webapp 目录新建文件,会显示如下错误

查看容器中挂载主机目录的具体信息

$ docker inspect web

"Mounts": [
    {
        "Type": "bind",
        "Source": "/src/webapp",
        "Destination": "/opt/webapp",
        "Mode": "",
        "RW": true,
        "Propagation": "rprivate"
    }
],

注意 Type 的区别

挂载一个本地主机文件作为数据卷

$ docker run --rm -it \
   # -v $HOME/.bash_history:/root/.bash_history \
   --mount type=bind,source=$HOME/.bash_history,target=/root/.bash_history \
   ubuntu:18.04 \
   bash

root@2affd44b4667:/# history
1  ls
2  diskutil list

这样就可以记录在容器输入过的命令了。

网络功能

docker 网络概述

Docker 的网络模型通过驱动实现了可插拔,自带了几个驱动并提供了核心功能

  • bridge: 默认网络驱动,当应用程序用在需要通信的独立容器中运行时,通常使用 bridge 网络 bridge network
    • 最佳实践: 当多个容器需要在同一个 Docker 宿主机上进行通信
  • host: 对于独立的容器,移除了容器与宿主机之间的隔离,直接使用宿主的网络,host 只能用于 Docker17.06+ 的 swarm host network
    • 最佳实践: 容器和宿主机的网络不存在隔离,但是其他资源需要隔离
  • overlay: 将多个 Docker daemons 链接在一起,并使集群服务可以相互通信,还可以促使集群服务和独立容器之间的通信,或者在不同 Docker daemons 的容器之间进行通信。此策略消除了容器之间 OS 级别路由的需要 overlay network
    • 最佳实践: 当运行在不同 Docker Host 的容器需要通信或者多个应用程序通过 swarm 工作在一起的时候
  • macvlan: 给容器分配了一个 MAC 地址,显示为具体的物理驱动。处理那些希望直接连接到物理网络的旧应用程序, macvlan 应该是最好的选择而不是通过 Docker 宿主机的网络栈 macvlan network
    • 最佳实践: 当您从 VM 设置迁移或需要容器看起来像网络上的物理主机时,每个主机都具有唯一的MAC地址
  • none: 关闭所有网络,通常与自定义网络驱动程序一起使用,swarm 服务不支持 none none network
  • Network plugins: 可以通过 Docker 安装和使用第三方网络插件,可以从 Docker Hub 获得或者其他第三方组织

参考链接

外部访问容器

容器中可以运行一些网络应用,要让外部也可以访问这些应用,可以通过 -P-p 参数来指定端口映射。

  • -P: 随机映射一个 49000~49900 的端口到内部容器开放的网络端口。
  • -p: 可以指定要映射的端口,并且,在一个指定端口上只可以绑定一个容器。支持的格式有 ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort

映射所有接口地址

使用 hostPort:containerPort 格式本地的 5000 端口映射到容器的 5000 端口

$ docker run -d -p 5000:5000 training/webapp python app.py

默认会绑定本地所有接口上的所有地址

映射到指定地址的指定端口

可以使用 ip:hostPort:containerPort 格式指定映射使用一个特定地址,比如 localhost 地址 127.0.0.1

$ docker run -d -p 127.0.0.1:5000:5000 training/webapp python app.py

映射到指定地址的任意端口

使用 ip::containerPort 绑定 localhost 的任意端口到容器的 5000 端口,本地主机会自动分配一个端口。

$ docker run -d -p 127.0.0.1::5000 training/webapp python app.py

还可以使用 udp 标记来指定 udp 端口

$ docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py

查看映射端口配置

使用 docker port 来查看当前映射的端口配置,也可以查看到绑定的地址

$ docker port nostalgic_morse 5000
127.0.0.1:49155.

容器互联

可以使用 --link 参数来使容器互联,但是建议创建自定义的 Docker 网络来连接多个容器。

新建网络

$ docker network create -d bridge my-net

-d 参数指定 Docker 网络类型,有 bridgeoverlay。其中 overlay 网络类型用于 Swarm mode

连接容器

运行一个容器并连接到新建的 my-net 网络

$ docker run -it --rm --name busybox1 --network my-net busybox sh

打开新的终端,再运行一个容器并加入到 my-net 网络

$ docker run -it --rm --name busybox2 --network my-net busybox sh

下面通过 ping 来证明 busybox1 容器和 busybox2 容器建立了互联关系

/ # ping busybox1
PING busybox1 (172.19.0.2): 56 data bytes
64 bytes from 172.19.0.2: seq=0 ttl=64 time=0.132 ms
64 bytes from 172.19.0.2: seq=1 ttl=64 time=0.179 ms
64 bytes from 172.19.0.2: seq=2 ttl=64 time=0.181 ms
--- busybox1 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.132/0.164/0.181 ms

配置 DNS

自定义容器主机名和 DNS,Docker 利用虚拟文件来挂载容器的相关配置文件

在容器中可以使用 mount 命令查看到挂载信息

$ mount
/dev/sda1 on /etc/hostname type ext4 (rw,relatime,stripe=1024,data=ordered)
/dev/sda1 on /etc/hosts type ext4 (rw,relatime,stripe=1024,data=ordered)
/dev/sda1 on /etc/resolv.conf type ext4 (rw,relatime,stripe=1024,data=ordered)

这种机制可以让宿主主机 DNS 信息发生更新后,所有 Docker 容器的 DNS 配置通过 /etc/resolv.conf 文件立刻得到更新。

配置全部容器的 DNS ,也可以在 /etc/docker/daemon.json 文件中增加以下内容来设置。

{
  "dns" : [
    "114.114.114.114",
    "8.8.8.8"
  ]
}

每次启动的容器 DNS 自动配置为 114.114.114.114 和 8.8.8.8

手动指定容器的配置,可以在使用 docker run 命令启动容器时加入如下参数:

  • -h HOSTNAME 或者 --hostname=HOSTNAME 设定容器的主机名,它会被写到容器内的 /etc/hostname/etc/hosts。但它在容器外部看不到,既不会在 docker container ls 中显示,也不会在其他的容器的 /etc/hosts 看到
  • -dns=IP_ADDRESS 添加 DNS 服务器到容器的 /etc/resolv.conf 中,让容器用这个服务器来解析所有不在 /etc/hosts 中的主机名。
  • --dns-search=DOMAIN 设定容器的搜索域,当设定搜索域为 .example.com 时,在搜索一个名为 host 的主机时,DNS 不仅搜索 host,还会搜索 host.example.com

如果在容器启动时没有指定最后两个参数,Docker 会默认用主机上的 /etc/resolv.conf 来配置容器。

高级网络配置

当 Docker 启动时,会自动在主机上创建一个 docker0 虚拟网桥,实际上就是 Linux 的一个 bridge,可以理解为一个软件交换机。它会挂载到的它的网口之间进行转发。

同时,Docker 随机分配一个本地未占用的私有网段中的一个地址给 docker0接口,比如下面的 172.17.0.1,掩码为 255.255.0.0。此后启动的容器内的网口也会自动分配一个同一网段(172.17.0.0/16)的地址。

$ ifconfig

docker0   Link encap:Ethernet  HWaddr 02:42:84:8b:dc:dd
          inet addr:172.17.0.1  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:1883 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2522 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:1849684 (1.8 MB)  TX bytes:578279 (578.2 KB)

veth77c98fc Link encap:Ethernet  HWaddr 4e:b3:20:9c:f7:ea
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:33298 errors:0 dropped:0 overruns:0 frame:0
          TX packets:157330 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:2037218 (2.0 MB)  TX bytes:8883173 (8.8 MB)

当创建一个 Docker 容器的时候,同时会创建了一对 veth pair 接口(当数据包发送到一个接口时,另外一个接口也可以收到相同的数据包)。这对接口一端在容器内,即 eth0;另一端在本地并被挂载到 docker0 网桥,名称以 veth 开头(例如 vethAQI2QT)。通过这种方式,主机可以跟容器通信,容器之间也可以相互通信。Docker 就创建了在主机和所有容器之间一个虚拟共享网络。

Docker 网络
Docker 网络

快速配置指南

一些 Docker 网络相关的命令列表

其中有些命令选项只有在 Docker 服务启动的时候才能配置,而且不能马上生效。

  • -b BRIDGE--bridge=BRIDGE 指定容器挂载的网桥
  • --bip=CIDR 定制 docker0 的掩码
  • -H SOCKET...--host=SOCKET... Docker 服务端接收命令的通道
  • --icc=true|false 是否支持容器之间进行通信
  • --ip-forward=true|false 请看下文容器之间的通信
  • --iptables=true|false 是否允许 Docker 添加 iptables 规则
  • --mtu=BYTES 容器网络中的 MTU

下面2个命令选项既可以在启动服务时指定,也可以在启动容器时指定。在 Docker 服务启动的时候指定则会成为默认值,后面执行 docker run 时可以覆盖设置的默认值。

  • --dns=IP_ADDRESS... 使用指定的DNS服务器
  • --dns-search=DOMAIN... 指定DNS搜索域

下面选项只有在 docker run 执行时使用,因为它是针对容器的特性内容。

  • -h HOSTNAME--hostname=HOSTNAME 配置容器主机名
  • --link=CONTAINER_NAME:ALIAS 添加到另一个容器的连接
  • --net=bridge|none|container:NAME_or_ID|host 配置容器的桥接模式
  • -p SPEC--publish=SPEC 映射容器端口到宿主主机
  • -P or --publish-all=true|false 映射容器所有端口到宿主主机

容器访问控制

容器的访问控制,主要通过 Linux 上的 iptables 防火墙来进行管理和实现。iptables 是 Linux 上默认的防火墙软件,在大部分发行版中都自带。

容器访问外部网络

容器要想访问外部网络,需要本地系统的转发支持。在Linux 系统中,检查转发是否打开。

$ sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1

如果为 0,说明没有开启转发,则需要手动打开。

$ sysctl -w net.ipv4.ip_forward=1

如果在启动 Docker 服务的时候设定 --ip-forward=true, Docker 就会自动设定系统的 ip_forward 参数为 1。

容器之间访问

容器之间相互访问,需要两方面的支持。

  • 容器的网络拓扑是否已经互联。默认情况下,所有容器都会被连接到 docker0 网桥上。
  • 本地系统的防火墙软件 – iptables 是否允许通过
访问所有端口

当启动 Docker 服务(即 dockerd)的时候,默认会添加一条转发策略到本地主机 iptables 的 FORWARD 链上。策略为通过(ACCEPT)还是禁止(DROP)取决于配置 --icc=true(缺省值)还是 --icc=false。当然,如果手动指定 --iptables=false 则不会添加 iptables 规则。

可见,默认情况下,不同容器之间是允许网络互通的。如果为了安全考虑,可以在 /etc/docker/daemon.json 文件中配置 {"icc": false} 来禁止它。

访问指定端口

在通过 -icc=false 关闭网络访问后,还可以通过 --link=CONTAINER_NAME:ALIAS 选项来访问容器的开放端口。

例如,在启动 Docker 服务时,可以同时使用 icc=false --iptables=true 参数来关闭允许相互的网络访问,并让 Docker 可以修改系统中的 iptables 规则。

启动容器(docker run)时使用 --link=CONTAINER_NAME:ALIAS 选项。Docker 会在 iptable 中为 两个容器分别添加一条 ACCEPT 规则,允许相互访问开放的端口(取决于 Dockerfile 中的 EXPOSE 指令)。

当添加了 --link=CONTAINER_NAME:ALIAS 选项后,添加了 iptables 规则。

可以通过 sudo iptables -nL 查看 iptables 规则。

--link=CONTAINER_NAME:ALIAS 中的 CONTAINER_NAME 目前必须是 Docker 分配的名字,或使用 --name 参数指定的名字。主机名则不会被识别。

映射容器端口到宿主主机的实现

默认情况下

  • 容器可以主动访问到外部网络的连接,
  • 外部网络无法访问到容器。

容器访问外部实现

容器所有到外部网络的连接,源地址都会被 NAT 成本地系统的 IP 地址。这是使用 iptables 的源地址伪装操作实现的。

$ sudo iptables -t nat -nL 

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
MASQUERADE  all  --  172.17.0.0/16        0.0.0.0/0
MASQUERADE  all  --  172.20.0.0/16        0.0.0.0/0
MASQUERADE  tcp  --  172.20.0.3           172.20.0.3           tcp dpt:4443

上述规则将所有源地址在 172.17.0.0/16 网段,目标地址为其他网段(外部网络)的流量动态伪装为从系统网卡发出。MASQUERADE 跟传统 SNAT 的好处是它能动态从网卡获取地址。

外部访问容器实现

容器允许外部访问,可以在 docker run 时候通过 -p 或 -P 参数来启用。

不管用那种办法,其实也是在本地的 iptable 的 nat 表中添加相应的规则。

使用 -P 时:

$ sudo iptables -t nat -nL
...
Chain DOCKER (2 references)
target     prot opt source               destination
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:49153 to:172.17.0.2:80

使用 -p 80:80 时:

$ iptables -t nat -nL
Chain DOCKER (2 references)
target     prot opt source               destination
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:80 to:172.17.0.2:80
  • 这里的规则映射了 0.0.0.0,意味着将接受主机来自所有接口的流量。用户可以通过 -p IP:host_port:container_port-p IP::port 来指定允许访问容器的主机上的 IP、接口等,以制定更严格的规则。
  • 如果希望永久绑定到某个固定的 IP 地址,可以在 Docker 配置文件 /etc/docker/daemon.json 中添加如下内容。
{
  "ip": "0.0.0.0"
}

配置 docker0

Docker 服务默认会创建一个 docker0 网桥(其上有一个 docker0 内部接口),它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。

Docker 默认指定了 docker0 接口 的 IP 地址和子网掩码,让主机和容器之间可以通过网桥相互通信,它还给出了 MTU(接口允许接收的最大传输单元),通常是 1500 Bytes,或宿主主机网络路由上支持的默认值。这些值都可以在服务启动的时候进行配置

  • --bip=CIDR IP 地址加掩码格式,例如 192.168.1.524
  • --mtu=BYTES 覆盖默认的 Docker mtu 配置

也可以在配置文件中配置 DOCKER_OPTS,然后重启服务。

由于目前 Docker 网桥是 Linux 网桥,用户可以使用 brctl show(sudo apt install bridge-utils) 来查看网桥和端口连接信息。

$ brctl show
bridge name	bridge id		STP enabled	interfaces
br-0f8a6fd2b981		8000.02422e207cbb	no		veth77c98fc
docker0		8000.0242848bdcdd	no		vetha98842d

每次创建一个新容器的时候,Docker 从可用的地址段中选择一个空闲的 IP 地址分配给容器的 eth0 端口。使用本地主机上 docker0 接口的 IP 作为所有容器的默认网关。

$ docker run -i -t --rm alpine /bin/sh
/ # ip addr show eth0
80560: eth0@if80561: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # ip route
default via 172.17.0.1 dev eth0
172.17.0.0/16 dev eth0 scope link  src 172.17.0.3
/ # route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         172.17.0.1      0.0.0.0         UG    0      0        0 eth0
172.17.0.0      *               255.255.0.0     U     0      0        0 eth0

自定义网桥

除了默认的 docker0 网桥,用户也可以指定网桥来连接各个容器。

在启动 Docker 服务的时候,使用 -b BRIDGE--bridge=BRIDGE 来指定使用的网桥。

  1. 如果服务已经运行,那需要先停止服务,并删除旧的网桥。
$ sudo systemctl stop docker
$ sudo ip link set dev docker0 down
$ sudo brctl delbr docker0
  1. 然后创建一个网桥 bridge0。
$ sudo brctl addbr bridge0
$ sudo ip addr add 192.168.5.1/24 dev bridge0
$ sudo ip link set dev bridge0 up
  1. 查看确认网桥创建并启动。
$ ip addr show bridge0
4: bridge0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state UP group default
    link/ether 66:38:d0:0d:76:18 brd ff:ff:ff:ff:ff:ff
    inet 192.168.5.1/24 scope global bridge0
       valid_lft forever preferred_lft forever
  1. 使用新创建的网桥

在 Docker 配置文件 /etc/docker/daemon.json 中添加如下内容,即可将 Docker 默认桥接到创建的网桥上。

{
  "bridge": "bridge0",
}
  1. 启动 Docker 服务。

新建一个容器,可以看到它已经桥接到了 bridge0 上。

可以继续用 brctl show 命令查看桥接的信息。

另外,在容器中可以使用 ip addrip route 命令来查看 IP 地址配置和路由信息。

创建一个点到点连接

默认情况下,Docker 会将所有容器连接到由 docker0 提供的虚拟子网中。

用户有时候需要两个容器之间可以直连通信,而不用通过主机网桥进行桥接。

解决办法很简单:创建一对 peer 接口,分别放到两个容器中,配置成点到点链路类型即可。

  1. 启动两个容器
$ docker run -i -t --rm --net=none base /bin/bash
root@1f1f4c1f931a:/#
$ docker run -i -t --rm --net=none base /bin/bash
root@12e343489d2f:/#
  1. 找到进程号,然后创建网络命名空间的跟踪文件。
$ docker inspect -f '{{.State.Pid}}' 1f1f4c1f931a
2989
$ docker inspect -f '{{.State.Pid}}' 12e343489d2f
3004
$ sudo mkdir -p /var/run/netns
$ sudo ln -s /proc/2989/ns/net /var/run/netns/2989
$ sudo ln -s /proc/3004/ns/net /var/run/netns/3004
  1. 创建一对 peer 接口,然后配置路由
$ sudo ip link add A type veth peer name B

$ sudo ip link set A netns 2989
$ sudo ip netns exec 2989 ip addr add 10.1.1.1/32 dev A
$ sudo ip netns exec 2989 ip link set A up
$ sudo ip netns exec 2989 ip route add 10.1.1.2/32 dev A

$ sudo ip link set B netns 3004
$ sudo ip netns exec 3004 ip addr add 10.1.1.2/32 dev B
$ sudo ip netns exec 3004 ip link set B up
$ sudo ip netns exec 3004 ip route add 10.1.1.1/32 dev B

现在这 2 个容器就可以相互 ping 通,并成功建立连接。点到点链路不需要子网和子网掩码。

此外,也可以不指定 --net=none 来创建点到点链路。这样容器还可以通过原先的网络来通信。

利用类似的办法,可以创建一个只跟主机通信的容器。但是一般情况下,更推荐使用 --icc=false 来关闭容器之间的通信。

Linux 网络常用命令

  • route 查看、配置路由表(route table)
$ route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         172.27.0.1      0.0.0.0         UG    0      0        0 eth0
172.17.0.0      *               255.255.0.0     U     0      0        0 docker0
172.20.0.0      *               255.255.0.0     U     0      0        0 br-0f8a6fd2b981
172.27.0.0      *               255.255.240.0   U     0      0        0 eth0
  • ifconfig 主要是可以手动的启动、观察与修改网络接口的相关参数,可以修改的参数很多啊, 包括 IP 参数以及 MTU 等等都可以修改
$ ifconfig

docker0   Link encap:Ethernet  HWaddr 02:42:84:8b:dc:dd
          inet addr:172.17.0.1  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1887 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2526 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:1849878 (1.8 MB)  TX bytes:578647 (578.6 KB)

eth0      Link encap:Ethernet  HWaddr 52:54:00:3d:cf:3b
          inet addr:172.27.0.4  Bcast:172.27.15.255  Mask:255.255.240.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:44731076 errors:0 dropped:0 overruns:0 frame:0
          TX packets:44911630 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:6137765087 (6.1 GB)  TX bytes:5758830677 (5.7 GB)

veth77c98fc Link encap:Ethernet  HWaddr 4e:b3:20:9c:f7:ea
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:33298 errors:0 dropped:0 overruns:0 frame:0
          TX packets:157590 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:2037218 (2.0 MB)  TX bytes:8894093 (8.8 MB)

参考链接