docker基础

常用命令

Docker命令
  1. 查看docker版本
docker version
  1. 查看docker信息
docker info
  1. 查看帮助命令
# 查看docker总共有那些命令即命令简介
docker --help
# 查看具体命令的可选参数等用法
docker 命令名称 --help
镜像命令(image)
  1. 查看本地的所有镜像
docker images

可选参数为:

# docker images --help
Usage:    docker images [OPTIONS] [REPOSITORY[:TAG]]
List images
Options:
  -a, --all             Show all images (default hides intermediate images)
      --digests         Show digests
  -f, --filter filter   Filter output based on conditions provided
      --format string   Pretty-print images using a Go template
      --no-trunc        Don't truncate output
  -q, --quiet           Only show numeric IDs
  1. 搜索docker hub上的镜像
docker search image_name
# 例如:
docker search mysql

​ 使用过滤参数

如只想要stars大于3000的结果:

docker search mysql -f=stars=3000
  1. 从docker hub下载镜像
# 下载最新版
docker pull mysql
# 下载指定版本
docker pull mysql:5.7
  1. 删除本地镜像
docker rmi -f 镜像名称或者ID   # 如 docker rmi mysql
docker rmi -f 镜像名称或者ID 镜像名称或者ID 镜像名称或者ID  # 删除多个镜像用空格隔开
docker rmi -f $(docker images -q)  # 将括号中搜索到的镜像全部删除
容器命令(container)

有了镜像才能创建容器, 可以理解为: 镜像就是类, 容器就是类的实例对象

这里我们先下载centos镜像: docker pull centos

  1. 创建容器并启动
docker run [可选参数] image

# 常用参数
--name="容器名称"  给容器命名, 如centos01, centos02等等
-d                后台方式运行容器
-it               使用交互方式运行, 进入容器终端
-p                指定容器的端口
    -p 主机端口:容器端口
    -p ip:主机端口:容器端口
    -p 容器端口
    容器端口
-P                随机指定端口

测试启动并进入centos容器

docker run -it centos

可以看到主机名称变成了一串数字(这串数字就是容器的ID), 路径也变成了根目录/, 这就是进入了centos容器

但是由于centos镜像只是留下了centos系统最基础的必需资源, 所以体积小, 但是功能可能不太完善, 一些命令也没有, 如vim, wget等

  1. 退出容器
exit  # 停止容器的运行
Ctrl+p+q  # 不停止容器
docker attach  # 容器ID, 进入运行中容器的终端
  1. 查看正在运行的容器
docker ps
docker ps -a  # 查看所有容器, 包括已经停止运行了的容器
docker ps -n=?  # 显示最近的n个容器
docker ps -q  # 只显示容器编号
  1. 删除容器
docker rm -f 容器名称或者ID   # 如 docker rm mysql
docker rm -f 容器名称或者ID 容器名称或者ID 容器名称或者ID  # 删除多个容器用空格隔开
docker rm -f $(docker ps -q)  # 将括号中搜索到的容器全部删除
  1. 启动和停止容器
docker start 容器id  # 启动停止的容器
docker restart 容器id  # 重启容器
docker stop 容器id  # 停止正在运行的容器
docker kill 容器id  # 强制杀死正在运行的容器
  1. 后台启动容器
docker run -d 镜像名
# 如 docker run -d centos

该命令会返回一个容器ID, 但是运行 docker ps 时发现该容器并不在运行, 而是刚启动就停止了

原因是因为docker容器后台运行时, 必须要有一个对应的前台进程, 若这里加上(-it)那么就会启动一个前台进程, 若没有前台进程那么docker的机制就会自动把这个容器停止, 可以理解为垃圾回收

  1. 查看日志
docker log -tf 容器ID


Usage:    docker logs [OPTIONS] CONTAINER

Fetch the logs of a container

Options:
      --details        Show extra details provided to logs
  -f, --follow         Follow log output
      --since string   Show logs since timestamp (e.g. 2013-01-02T13:23:37) or relative (e.g. 42m for 42 minutes)
      --tail string    Number of lines to show from the end of the logs (default "all")
  -t, --timestamps     Show timestamps
      --until string   Show logs before a timestamp (e.g. 2013-01-02T13:23:37) or relative (e.g. 42m for 42 minutes)
  1. 查看容器中的进程信息
docker top 容器ID
  1. 查看容器的信息
docker inspect 容器ID
  1. 进入正在运行的容器
# 方式一
docker exec -it 容器ID /bin/bash

# 方式二
docker attach 容器ID

上述两者命令的区别是:

docker exec : 进入容器后开启一个新的终端

docker attach : 进入容器正在执行的终端, 不会开启新的终端

  1. 从容器内拷贝文件到主机上
docker cp 容器ID:要拷贝的文件路径 本机目的路径
# 如: docker cp 16bd39b136a3:root/copy_test.py /home
  1. 将容器打包成新的镜像
docker commit -a "作者信息" -m "提交备注信息" 容器ID 目标镜像名:[TAG]

容器数据卷

作用: 能够实现容器的数据持久化以及数据共享同步(包括容器间和容器与主机间)

效果: 同步后, 能够直接在本机修改容器的配置文件等, 不需要进入容器

命令挂载
命令示例:docker run -it -v 主机的目录:容器中的目录 image
# 测试 

docker run -dit -v /home/test:/home/dc_test --name mytomcat02 mytomcat
  • 可以发现主机和容器都分别自动新建了test和dc_test文件夹
  • 在主机的文件夹test中新增一个test.py的文件, 去容器的终端查看对应的dc_test文件夹, 发现里面也同步增加了一个test.py文件, 说明是挂载成功了的
  • 还可以通过 docker inspect 容器ID 来查看是否挂载成功
docker inspect mytomcat02
# 查看结果, 找到mount键值对, 则挂载成功
"Mounts": [
    {
        "Type": "bind", # 绑定成功
        "Source": "/home/test",  # 主机目录
        "Destination": "/home/dc_test",  # 容器目录
        "Mode": "",
        "RW": true,  # 读写都为True
        "Propagation": "rprivate"
    }
],
  • 停止容器mytomcat02后, 更新主机的test.py文件, 然后再启动mytomcat02, 进入到容器目录后发现其中的test.py文件依然同步更新了, 说明挂载后, 即使容器处于关闭状态, 也会同步文件
具名挂载和匿名挂载
# 指定路径挂载
-v 主机目录:容器内目录

# 匿名挂载, 只写容器内路径
-v 容器内路径
	# 如 
	docker run -d -p 8000:80 --name nginx01 -v /etc/nginx nginx
	# docker volume ls 查看卷信息, 发现卷名为一个长串字符
	DRIVER      VOLUME NAME
	local     7cbeb2b6422569a9ca98cd000b1630836c108acde428fc5145723fc93126329e
	
# 具名挂载, 在主机目录的位置用一个有名的变量代替
-v some_name:容器内目录
	# 如
	docker run -d -p 8001:80 --name nginx02 -v host-nginx:/etc/nginx nginx
	# docker volume ls 查看卷信息, 发现卷名为我们定义的名字
	DRIVER      VOLUME NAME
	local       host-nginx
查看卷信息
docker volume COMMAND

Commands:
  create      Create a volume
  inspect     Display detailed information on one or more volumes
  ls          List volumes
  prune       Remove all unused local volumes
  rm          Remove one or more volumes
# 如: docker volume ls
# 如: docker volume inspect host-nginx 查看某个卷的信息
[
    {
        "CreatedAt": "2020-07-27T22:46:41+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/host-nginx/_data",
        "Name": "host-nginx",
        "Options": null,
        "Scope": "local"
    }
]
数据卷权限
-v some_name:容器内路径:ro(rw)
# 如 docker run -d -p 8000:80 --name nginx03 -v nginx03:/etc/nginx:ro nginx
# ro 表示read-only, 设置了之后, 容器内不就没有权限修改, 只能主机修改
# rw 表示read-write, 默认为rw, 容器和主机都能改
dockerfile挂载

dockerfile就是用来构建docker镜像的构建文件, 实质为一段命令脚本.

通过这段脚本可以生成镜像, 镜像是一层一层的, 原因是脚本也是一个一个的命令, 每运行一个命令, 镜像就增加一层

新建dockerfile文件
# 继承标准的centos镜像
FROM centos
# 挂载卷(只写了容器内的路径, 为匿名挂载)
VOLUME ["volume01","volume02"]
# 完成后打印输出成功
CMD echo "---------sucess-------"
# 进入容器后使用
CMD /bin/bash
build构建dockerfile的镜像
# -f dockerfile文件
# -t tag, 自定义镜像的名字
# 注意最后有一个点.
docker build -f dockerfile01 -t alex/centos .
用自定义的镜像启动容器
docker run -it --name mycentos alex/centos

启动后, 在容器根目录下可以发现挂载的两个目录volume01、volume02

在其中volume01下新建文件container.py, 看看主机对应的目录是否会同步新增该文件夹

查看主机挂载路径
docker inspect mycentos

查看mount键值对, 可以找到主机对应的路径

img

进入volume01对应的主机路径, 可以看到确实同步了container.py文件

容器共享数据卷

测试: 多个centos容器间同步数据

多容器创建

用上面自定的镜像, 启动两个centos容器, mycentos01/mycentos02, 其中01作为主容器卷

# 启动第一个
docker run -dit --name mycentos01 alex/centos
# 启动第二个
docker run -dit --name mycentos02 --volumes-from mycentos01 alex/centos

可以看到两个容器的inspect信息中的挂载信息, 对应的主机路径都是一样的

docker inspect mycentos01
docker inspect mycentos02

也就是说其实两个容器内的数据卷都和主机同一个路径绑定了, 主机路径就像一个桥梁一样把两个容器连接起来了

即使是多级挂载, 所有的容器内目录依然与主机的同一个目录进行了关联, 那么这些容器的挂载目录文件和主机都是相互共享的.

若两个容器间对应的主机目录不相同, 则说明这两个容器不共享

DockerFile文件

dockerfile是用来构建docker镜像的文件, 是一个命令参数脚本

构建步骤:

  • 编写dockerfile文件
  • docker build 构建成一个镜像
  • docker run 运行镜像创建容器
  • docker push 发布镜像
创建dockerfile
创建规则
  • 每个保留关键字必须时大写字母
  • 命令从上往下依次执行
  • 每执行一个命令都会创建提交一个新的镜像层
  • # 表示注释

img

常用命令关键字
  • FROM 指定基础镜像, 可以理解为继承的父类
  • MAINTAINER 维护者/作者信息, 一般格式为姓名加邮箱
  • RUN 创建镜像时会运行的命令
  • ADD 添加需要的压缩文件, 创建时会自动解压, 如tomcat压缩包
  • WORKDIR 工作目录, 设置进入容器时所在的路径
  • VOLUME 挂载容器卷
  • EXPOSE 指定对外暴露的端口
  • CMD 指定容器启动时会运行的命令, 只有最后一个命令会生效, 且会被docker run后面的命令替代
  • ENTRYPOINT 指定容器启动时会运行的命令, 只有最后一个命令会生效, 但不会被docker run后面的命令替代, 而是会拼接上后面的命令
  • ONBUILD 一个触发器, 当该dockerfile构建的镜像A被其他dockerfile构建的镜像B继承时, 那么在构建B的过程中, 首先会执行这个ONBUILD命令, 且只会对子镜像生效, 对孙子镜像不会生效
  • COPY 类似ADD命令, 将文件拷贝到镜像中
  • ENV 构建镜像时设置环境变量
简单测试

Docker Hub中大部分镜像都是继承了 scratch 这个基础镜像 FROM scratch然后配置需要的软件和配置来进行构建

1.编写dockerfile创建自己的centos

  • 官方的centos中缺少一些常用命令, 如 vim/ifconfig等, 我们加上这些指令
  • 官方的centos的工作目录为根目录/, 我们改成/usr/local
FROM centos
MAINTAINER alex<g1242556827@163.com>

RUN yum -y install vim
RUN yum -y install net-tools

ENV MYPATH /usr/local
WORKDIR $MYPATH

VOLUME /home/test

EXPOSE 80

CMD echo "-----success-----"
CMD echo $MYPATH
CMD /bin/bash

使用dockerfile构建镜像

# docker build -f dockerfile路径 -t 镜像名:[tag] .
docker build -f dockerfile02 -t alex/centos .
# docker history 镜像名 查看镜像历史记录
docker history alex/centos

3.运行镜像创建容器

docker run -it alex/centos

可以看到进入容器终端端后的当前路径为dockerfile中设置的工作目录/usr/local

ifconfig命令也可以使用

CMD与ENTRYPOINT的异同

相同点:

  1. 两者都是在容器运行时会执行的命令
  2. 执行时两者优先级是等价的, 只有最后一条CMD命令或者最后一条ENTRYPOIN命令会被执行, 即:
    • 若只有两条CMD命令, 则最后一条CMD命令会被执行
    • 若只有两条ENTRYPOINT命令, 则最后一条ENTRYPOINT命令会被执行
    • 若有一条CMD命令, 有一条ENTRYPOINT命令, 则最后一条ENTRYPOINT命令会被执行, 反之亦然

不同点:

当在执行docker run 镜像名 额外命令时, 在后面添加了额外的命令, 那么:

  • 对于CMD来说, 这条额外命令会替换掉CMD的命令, 也就是说不会执行CMD命令了, 只会执行run 后额外的命令
  • 对于ENTRYPOINT来说, 这条额外的命令会追加到ENTRYPOINT后面, 最后执行的是两者拼接后的命令

Docker网络

理解Docker0

在宿主机linux上, 运行ip addr, 查看当前的网卡信息

(root@Aliyun-Alex:/home/alex)# ip addr
# 打印结果
# 第一个 lo 为回环IP 127.0.0.1
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
# 第二个 eth0 为阿里云内网IP 172.19.67.12
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:16:3e:10:69:3c brd ff:ff:ff:ff:ff:ff
    inet 172.19.67.12/20 brd 172.19.79.255 scope global dynamic noprefixroute eth0
       valid_lft 310946826sec preferred_lft 310946826sec
    inet6 fe80::216:3eff:fe10:693c/64 scope link 
       valid_lft forever preferred_lft forever
# 第三个 docker0 为Docker使用的IP 172.17.0.1
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:92:a2:eb:c6 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:92ff:fea2:ebc6/64 scope link 
       valid_lft forever preferred_lft forever

在宿主机安装了docker后, 就会新增一个名为docker0的网卡;

启动一个容器

现在运行一个tomcat容器, 尝试linux宿主机ping一下tomcat容器, 看是否能ping通

docker run -d -P --name tomcat01 tomcat

查看tomcat容器中的ip地址信息

docker exec -it tomcat01 ip addr
# 可以看到也有两个地址
# 第一个 lo 为回环IP 127.0.0.1
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
# 第二个 eth0@if161 为容器的IP 172.17.0.2
160: eth0@if161: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

发现容器内的IP地址172.17.0.2和宿主机的docker0172.17.0.1属于同一网段, 那么两者就是能ping通的

再次回到宿主机linux执行ip addr, 发现又多了个网卡 161: veth8dd219c@if160

161: veth8dd219c@if160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 16:71:2b:b0:4c:f2 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::1471:2bff:feb0:4cf2/64 scope link 
       valid_lft forever preferred_lft forever

可以看出规律, 每启动一个容器, 就会给容器分配一个IP, 同时宿主机也多一个IP地址, 且这两个IP地址是有对应关系的

在宿主机的网卡名为宿主机IP序号: vethxxx@if容器IP序号

在容器内的网卡名为容器IP序号: eth0@if宿主机IP序号

这就是veth-pair技术, 就是一对虚拟设备接口, 他们都是成对出现的, 一端连着协议, 一端彼此相连, veth-pair可以充当一个桥梁, 连接各种虚拟网络设备

如OpenStack, OVS, 和Docker容器之间的连接, 都是使用的veth-pair技术

Docker网络桥接图

Docker使用的是Linux的桥接, 宿主机中的docker01是容器间的网桥

只要删除容器, 对应的网桥一对就没了

img

img

–link

容器间ping时或连接时, 可否直接通过名字连接, 而不是通过固定写死的ip地址, 即若某个容器的ip地址换了, 不修改连接设置, 依然可以进行连接

可以类比为url的反向解析, 不是直接写死url, 而是给url一个名字, 通过访问名字来访问url, 即使该名字对应的url地址发生了变化, 通过名字也依然可以访问到变化后的url地址

直接使用容器名称, 在容器01中ping容器02, 发生报错

(root@Aliyun-Alex:/home/alex)# docker exec -it tomcat01 ping tomcat02
ping: tomcat02: Name or service not known

通过--link可以解决这个问题

再启动一个容器 tomcat03, 使用 --link 连接 tomcat01

docker run -d -P --name tomcat03 --link tomcat01 tomcat 

进入tomcat03容器中, 直接使用ping tomcat01, 可以ping通

但是反向在 tomcat01 容器中, 直接使用ping tomcat03, 却不能ping通

查看tomcat03容器信息, 可以看到 Links 属性, 连接了tomcat01

docker inspect tomcat03
# 在输出结果中可以看到 Links 属性, 连接了tomcat01
"Links": [
	"/tomcat01:/tomcat03/tomcat01"
],

查看tomcat03的/etc/hosts文件也可以看到关联了tomcat01, 这就是–link的实质操作, 在host中添加一个连接信息

(root@Aliyun-Alex:/home/alex)# docker exec -it tomcat03 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      tomcat01 db68ef67ca80
172.17.0.4      340afdc0bb53
自定义网络

查看所有docker网络docker network ls

(root@Aliyun-Alex:/home/alex)# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
35b249810e67        bridge              bridge              local
de155dd42929        host                host                local
c8ffb814685e        none                null                local

网络连接模式

  • bridge(桥接模式): docker0就是docker容器间的桥梁
  • none: 不配置网络
  • host: 和宿主机共享网络

当直接启动容器时, 默认使用的一个参数是 --net bridge, 这个bridge就是docker0网卡

docker run -d -P tomcat
# 即为
docker run -d -P --net bridge tomcat

我们可以不使用bridge(docker0) ,而是自己创建一个网络

创建网络
# --driver bridge 网络连接模式, 默认为bridge, 因此这里也可以不写这个参数
# --subnet 子网
# --getway 网关
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
# 查看网络
docker network ls
# 结果多了mynet
NETWORK ID          NAME                DRIVER              SCOPE
35b249810e67        bridge              bridge              local
de155dd42929        host                host                local
8e7819b11d29        mynet               bridge              local
c8ffb814685e        none                null                local

查看mynet具体网络信息

(root@Aliyun-Alex:/home/alex)# docker network inspect mynet
[
    {
        "Name": "mynet",
        "Id": "8e7819b11d292e30e36a38095dc4b30f310affc9841b4500f5851c670a7f9b48",
        "Created": "2020-07-30T17:41:46.204861397+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.0.0/16",
                    "Gateway": "192.168.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]
使用自定义网络, 启动容器

启动两个容器 tomcat01 和 tomcat02

docker run -d -P --name tomcat01 --net mynet tomcat
docker run -d -P --name tomcat02 --net mynet tomcat

再次查看mynet具体网络信息, 可以看到关联的容器

(root@Aliyun-Alex:/home/alex)# docker network inspect mynet 

                    "Subnet": "192.168.0.0/16",
                    "Gateway": "192.168.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "282a1cd78979de4afcfb24b10fd9c322e21f1eb01879cf5e02918a7dfc9945a4": {
                "Name": "tomcat01",
                "EndpointID": "2eccabd1b12d555cdbc4fd0a66e9618a3f0df40f6dd7199c94f01caa2b6c1d15",
                "MacAddress": "02:42:c0:a8:00:02",
                "IPv4Address": "192.168.0.2/16",
                "IPv6Address": ""
            },
            "680e66da888e5c18cff7aae19f51c5189127405a54547925f4482b955a604e79": {
                "Name": "tomcat02",
                "EndpointID": "7ce54ee89ba6332ce67920ba687c9af83ba1fd5407aca4e91fcf9e5c23cb5959",
                "MacAddress": "02:42:c0:a8:00:03",
                "IPv4Address": "192.168.0.3/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]
容器间使用容器名相互ping通

之前使用容器名来ping是ping不同的, 且就算使用了--link也只能单向使用容器名ping通

现在双向都使用容器名ping通试试看

  • 在容器 tomcat01 中ping 容器 tomcat02, 发现可以ping通
(root@Aliyun-Alex:/home/alex)# docker exec -it tomcat01 ping tomcat02
PING tomcat02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.118 ms
64 bytes from tomcat02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.076 ms
64 bytes from tomcat02.mynet (192.168.0.3): icmp_seq=3 ttl=64 time=0.093 ms
^C
--- tomcat02 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 8ms
rtt min/avg/max/mdev = 0.076/0.095/0.118/0.020 ms
  • 在容器 tomcat02 中ping 容器 tomcat01, 发现也可以ping通
(root@Aliyun-Alex:/home/alex)# docker exec -it tomcat02 ping tomcat01
PING tomcat01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.101 ms
64 bytes from tomcat01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.095 ms
^C
--- tomcat01 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 3ms
rtt min/avg/max/mdev = 0.095/0.098/0.101/0.003 ms

发现通过自定义网络比docker0使用起来更加方便, 推荐使用自定义网络

网络连通

在前面的步骤中, mynet网络上连接了两个容器, 分别是tomcat01和tomcat02, 他们的网段是192.168.0.0

我们现在使用默认的网络docker0再创建两个容器tomcat03和tomcat04, 他们的网段是172.17.0.0

docker run -d -P --name tomcat03 tomcat
docker run -d -P --name tomcat04 tomcat

现在的网络结构如下:

img

(root@Aliyun-Alex:/home/alex)# docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known

直接尝试连接, 发现tomcat02并不能ping通03

但是我们可以做一个操作, 如果将tomcat02能与Docker0连接, 那么就能和tomcat03和tomcat04连接

docker network命令中有一个connect命令

docker network --help
# 打印结果
Usage:  docker network COMMAND

Manage networks

Commands:
  connect     Connect a container to a network
  create      Create a network
  disconnect  Disconnect a container from a network
  inspect     Display detailed information on one or more networks
  ls          List networks
  prune       Remove all unused networks
  rm          Remove one or more networks

Run 'docker network COMMAND --help' for more information on a command.

这个命令可以将一个网络连接入一个容器中

(root@Aliyun-Alex:/home/alex)# docker network connect --help

Usage:  docker network connect [OPTIONS] NETWORK CONTAINER

Connect a container to a network

Options:
      --alias strings           Add network-scoped alias for the container
      --driver-opt strings      driver options for the network
      --ip string               IPv4 address (e.g., 172.30.100.104)
      --ip6 string              IPv6 address (e.g., 2001:db8::33)
      --link list               Add link to another container
      --link-local-ip strings   Add a link-local address for the container

将网络docker0连接容器tomcat02

docker network connect bridge tomcat02

查看tomcat02的信息, 找到网络属性, 发现该容器有两个网络属性(mynetbridge)和两个IP(192.168.0.3172.17.0.4)

docker inspect tomcat02
# 打印结果
"bridge": {                                                                                                            
    ...
    "NetworkID": "35b249810e679e94e48b0dce387ad422fe4241c3335f82355cf919a56d96bc0c",                                   
    "EndpointID": "cf79813e3322df01cd9e693a0e42d803a26d0f2bf29762e82c5d28c9fa900710",
    "Gateway": "172.17.0.1",
    "IPAddress": "172.17.0.4",
    ...
},
"mynet": {
    ...
    "NetworkID": "8e7819b11d292e30e36a38095dc4b30f310affc9841b4500f5851c670a7f9b48",
    "EndpointID": "7ce54ee89ba6332ce67920ba687c9af83ba1fd5407aca4e91fcf9e5c23cb5959",
    "Gateway": "192.168.0.1",
    "IPAddress": "192.168.0.3",
    ...
}

或者查看网络 docker0 的信息, 可以看到有三个容器连接上了, tomcat02/tomcat03/tomcat04

docker inspect bridge
# 打印结果
"Containers": {                                                                                                                
        "1152c9fa07e21798589e2f36de0dc9529b104b65f95fe4749b54b557cf51fa0c": {                                                   
            "Name": "tomcat03",
            ...
            "IPv4Address": "172.17.0.2/16",
	},
    "680e66da888e5c18cff7aae19f51c5189127405a54547925f4482b955a604e79": {
        "Name": "tomcat02",
        ...
        "IPv4Address": "172.17.0.4/16",
	},
    "daf280a8066191e42a4e80168ecb0bc285e9ef92a01723c3d862a0b18b2d38f8": {
        "Name": "tomcat04",
        ...
        "IPv4Address": "172.17.0.3/16",
	}
}

此时网络结构如下:

img

现在测试tomcat02去ping容器tomcat03或者tomcat04

(root@Aliyun-Alex:/home/alex)# docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known

发现依然ping不通, 回想一下, 想起了之前说过了Docker0这个网卡默认情况不支持直接通过容器名去ping

那么测试用tomcat02去ping容器tomcat03的IP地址172.17.0.2或者tomcat04的IP地址172.17.0.3, 发现可以ping通

(root@Aliyun-Alex:/home/alex)# docker exec -it tomcat02 ping 172.17.0.3
PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.134 ms
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.080 ms
^C
--- 172.17.0.3 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 48ms
rtt min/avg/max/mdev = 0.080/0.107/0.134/0.027 ms

那么反过来, 我们将tomcat03连接到mynet网络下, 在自定义的网络中, 是可以实现通过容器名去ping的

docker network connect mynet tomcat03

现在网络结构如下:

img

在测试用tomcat03去ping容器tomcat01, 发现可以ping通

(root@Aliyun-Alex:/home/alex)# docker exec -it tomcat03 ping tomcat01
PING tomcat01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.112 ms
64 bytes from tomcat01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.091 ms
^C
--- tomcat01 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 2ms
rtt min/avg/max/mdev = 0.091/0.101/0.112/0.014 ms

那么结论就是:

  1. bytes of data.
    64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.134 ms
    64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.080 ms
    ^C
    — 172.17.0.3 ping statistics —
    2 packets transmitted, 2 received, 0% packet loss, time 48ms
    rtt min/avg/max/mdev = 0.080/0.107/0.134/0.027 ms

那么反过来, 我们将tomcat03连接到mynet网络下, 在自定义的网络中, 是可以实现通过容器名去ping的

```shell
docker network connect mynet tomcat03

现在网络结构如下:

[外链图片转存中…(img-RcmcDmmM-1671515956519)]

在测试用tomcat03去ping容器tomcat01, 发现可以ping通

(root@Aliyun-Alex:/home/alex)# docker exec -it tomcat03 ping tomcat01
PING tomcat01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.112 ms
64 bytes from tomcat01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.091 ms
^C
--- tomcat01 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 2ms
rtt min/avg/max/mdev = 0.091/0.101/0.112/0.014 ms

那么结论就是:

想要不同网段的容器间连接, 需要通过docker network connect network_name docker_name将容器加入到目标网络中即可, 且目标网络最好是自定义的网络, 在自定义的网络中才能直接使用容器名ping通, 而默认的网络docker0(bridge)中只能使用IP地址ping通

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值