Skip to content

docker

14402字约48分钟

云部署docker

2024-07-20

Docker概述

Docker为什么出现

​ 一款产品从开发到上线,从操作系统,到运行环境,再到应用配置。作为开发+运维之间的协作我们需要关心很多东西,这也是很多互联网公司都不得不面对的问题,特别是各种版本的迭代之后,不同版本环境的兼容,对运维人员是极大的考验!

​ 环境配置如此麻烦,换一台机器,就要重来一次,费力费时。很多人想到,能不能从根本上解决问题,软件可以带环境安装?也就是说,安装的时候,把原始环境一模一样地复制过来。解决开发人员说的“ 在我的机器上可正常工作”的问题。

​ 之前在服务器配置一个应用的运行环境,要安装各种软件,就拿一个基本的工程项目的环境来说吧,Java/Tomcat/MySQL/JDBC驱动包等。安装和配置这些东西有多麻烦就不说了,它还不能跨平台。假如我们是在 Windows 上安装的这些环境,到了 Linux 又得重新装。况且就算不跨操作系统,换另一台同样操作系统的服务器,要移植应用也是非常麻烦的

​ 传统上认为,软件编码开发/测试结束后,所产出的成果即是程序或是能够编译执行的二进制字节码文件等(Java为例)。而为了让这些程序可以顺利执行,开发团队也得准备完整的部署文件,让维运团队得以部署应用程式,开发需要清楚的告诉运维部署团队,用的全部配置文件+所有软件环境。不过,即便如此,仍然常常发生部署失败的状况。

​ Docker之所以发展如此迅速,也是因为它对此给出了一个标准化的解决方案

​ Docker镜像的设计,使得Docker得以打破过去「程序即应用」的观念。通过Docker镜像 ( images ) 将应用程序所需要的系统环境,由下而上打包,达到应用程序跨平台间的无缝接轨运作

image-20220825205128880

​ Docker的思想来自于集装箱,集装箱解决了什么问题?在一艘大船上,可以把货物规整的摆放起来。并且各种各样的货物被集装箱标准化了,集装箱和集装箱之间不会互相影响。那么我就不需要专门运送水果的船和专门运送化学品的船了。只要这些货物在集装箱里封装的好好的,那我就可以用一艘大船把他们都运走。 ​ docker就是类似的理念。

历史

​ 2010年,几个搞IT的年轻人,在美国旧金山成立了一家名叫“dotCloud”的公司。这家公司主要提供基于PaaS的云计算技术服务。具体来说,是和LXC有关的容器技术。后来,dotCloud公司将自己的容器技术进行了简化和标准化,并命名为——Docker。 ​ Docker技术诞生之后,并没有引起行业的关注。而dotCloud公司,作为一家小型创业企业,在激烈的竞争之下,也步履维艰。正当他们快要坚持不下去的时候,脑子里蹦出了“开源”的想法。什么是“开源”?开源,就是开放源代码。也就是将原来内部保密的程序源代码开放给所有人,然后让大家一起参与进来,贡献代码和意见。有的软件是一开始就开源的。也有的软件,是混不下去,创造者又不想放弃,所以选择开源。自己养不活,就吃“百家饭”。 ​ 2013年3月,dotCloud公司的创始人之一,Docker之父,28岁的Solomon Hykes正式决定,将Docker项目开源。不开则已,一开惊人。越来越多的IT工程师发现了Docker的优点,然后蜂拥而至,加入Docker开源社区。Docker的人气迅速攀升,速度之快,令人瞠目结舌。开源当月,Docker 0.1 版本发布。此后的每一个月,Docker都会发布一个版本。

​ 2014年6月9日,Docker 1.0 版本正式发布。此时的Docker,已经成为行业里人气最火爆的开源技术,没有之一。甚至像Google、微软、Amazon、VMware这样的巨头,都对它青睐有加,表示将全力支持。Docker和容器技术为什么会这么火爆?说白了,就是因为它“轻”。在容器技术之前,业界的网红是虚拟机。虚拟机技术的代表,是VMWare和OpenStack。相信很多人都用过虚拟机。虚拟机,就是在你的操作系统里面,装一个软件,然后通过这个软件,再模拟一台甚至多台“子电脑”出来。在“子电脑”里,你可以和正常电脑一样运行程序,例如开QQ。如果你愿意,你可以变出好几个“子电脑”,里面都开QQ。“子电脑”和“子电脑”之间,是相互隔离的,互不影响。虚拟机属于虚拟化技术。而Docker这样的容器技术,也是虚拟化技术,属于轻量级的虚拟化。虚拟机虽然可以隔离出很多“子电脑”,但占用空间更大,启动更慢,虚拟机软件可能还要花钱(例如VMWare)。而容器技术恰好没有这些缺点。它不需要虚拟出整个操作系统,只需要虚拟一个小规模的环境(类似“沙箱”)。 它启动时间很快,几秒钟就能完成。而且,它对资源的利用率很高(一台主机可以同时运行几千个Docker容器)。此外,它占的空间很小,虚拟机一般要几GB到几十GB的空间,而容器只需要MB级甚至KB级。 ​ 正因为如此,容器技术受到了热烈的欢迎和追捧,发展迅速。

docker 理念

​ Docker是基于Go语言实现的云开源项目。Docker的主要目标是 “Build,Ship and Run Any App , Anywhere”,也就是通过对应用组件的封装、分发、部署、运行等生命周期的管理,使用户的APP(可以是一个WEB应用或数据库应用等等)及其运行环境能够做到“一次封装,到处运行”。Linux 容器技术的出现就解决了这样一个问题,而 Docker 就是在它的基础上发展过来的。将应用运行在Docker 容器上面,而 Docker 容器在任何操作系统上都是一致的,这就实现了跨平台、跨服务器。只需要一次配置好环境,换到别的机子上就可以一键部署好,大大简化了操作。

Docker 能干什么

之前的虚拟机技术

​ 虚拟机(virtual machine)就是带环境安装的一种解决方案。

​ 它可以在一种操作系统里面运行另一种操作系统,比如在Windows 系统里面运行Linux 系统。应用程序对此毫无感知,因为虚拟机看上去跟真实系统一模一样,而对于底层系统来说,虚拟机就是一个普通文件,不需要了就删掉,对其他部分毫无影响。这类虚拟机完美的运行了另一套系统,能够使应用程序,操作系统和硬件三者之间的逻辑不变。

虚拟机缺点:

1 、资源占用多

2 、冗余步骤多

3 、启动慢

容器虚拟化技术

​ 由于前面虚拟机存在这些缺点,Linux 发展出了另一种虚拟化技术:Linux 容器(Linux Containers,缩写为 LXC)。

​ Linux 容器不是模拟一个完整的操作系统,而是对进程进行隔离。有了容器,就可以将软件运行所需的所有资源打包到一个隔离的容器中。容器与虚拟机不同,不需要捆绑一整套操作系统,只需要软件工作所需的库资源和设置。系统因此而变得高效轻量并保证部署在任何环境中的软件都能始终如一地运行。

​ 比较 Docker 和传统虚拟化方式的不同之处:

  • 传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用 进程;

  • 而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。 因此容器要比传统虚拟机更为轻便。

  • 每个容器之间互相隔离,每个容器有自己的文件系统 ,容器之间进程不会相互影响,能区分计算资源。

开发/运维

更快速的应用交付和部署:

传统的应用开发完成后,需要提供一堆安装程序和配置说明文档,安装部署后需根据配置文档进行繁杂的配置才能正常运行。而Docker只需要交付少量容器镜像文件,在正式生产环境中加载镜像并运行即可,应用安装配置在镜像里已经内置好,大大节省部署配置和测试验证时间。

更便捷的升级和扩缩容:

随着微服务架构和Docker的发展,大量的应用会通过微服务方式架构,应用的开发构建将变成搭乐高积木一样,每个Docker容器将变成一块“积木”,应用的升级将变得非常容易。当现有的容器不足以支撑业务处理时,可通过镜像运行新的容器进行快速扩容,使应用系统的扩容从原先的天级变成分钟级甚至秒级。

更简单的系统运维:

应用容器化运行后,生产环境运行的应用可与开发、测试环境的应用高度一致,容器会将应用程序相关的环境和状态完全封装起来,不会因为底层基础架构和操作系统的不一致性给应用带来影响,产生新的 BUG。当出现程序异常时,也可以通过测试环境的相同容器进行快速定位和修复。

更高效的计算资源利用:

Docker是内核级虚拟化,其不像传统的虚拟化技术一样需要额外的Hypervisor [管理程序] 支持,所以在一台物理机上可以运行很多个容器实例,可大大提升物理服务器的CPU和内存的利用率。

资源

Docker官网:http://www.docker.com Docker中文网站:https://www.docker-cn.com Docker Hub官网:https://hub.docker.com (仓库)

Docker 安装

Docker的架构图

image-20220825212233509

镜像(image) :

Docker 镜像(Image)就是一个只读的模板。镜像可以用来创建 Docker 容器,一个镜像可以创建很多容器。 就好似 Java 中的 类和对象,类就是镜像,容器就是对象!

容器(container):

Docker 利用容器(Container)独立运行的一个或一组应用。容器是用镜像创建的运行实例。

它可以被启动、开始、停止、删除。每个容器都是相互隔离的,保证安全的平台。

可以把容器看做是一个简易版的 Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。

容器的定义和镜像几乎一模一样,也是一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的。

仓库(repository):

仓库(Repository)是集中存放镜像文件的场所。

仓库(Repository)和仓库注册服务器(Registry)是有区别的。仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。
仓库分为公开仓库(Public)和私有仓库(Private)两种形式。

最大的公开仓库是 Docker Hub(https://hub.docker.com/),存放了数量庞大的镜像供用户下载。

国内的公开仓库包括阿里云 、网易云 等
  • Docker 本身是一个容器运行载体或称之为管理引擎。我们把应用程序和配置依赖打包好形成一个可交付的运行环境,这个打包好的运行环境就似乎 image镜像文件。只有通过这个镜像文件才能生成 Docker 容器。image 文件可以看作是容器的模板。Docker 根据 image 文件生成容器的实例。同一个 image 文件,可以生成多个同时运行的容器实例。

  • image 文件生成的容器实例,本身也是一个文件,称为镜像文件。

  • 一个容器运行一种服务,当我们需要的时候,就可以通过docker客户端创建一个对应的运行实例,也就是我们的容器

  • 仓库,就是放了一堆镜像的地方,我们可以把镜像发布到仓库中,需要的时候从仓库中拉下来。

环境说明

​ 要求系统为64位、系统内核版本为 3.10 以上

[root@localhost ~]# uname -r
3.10.0-1160.el7.x86_64
[root@localhost ~]# cat /etc/os-release
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"

CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"

安装步骤

  1. 官网安装参考手册:https://docs.docker.com/engine/install/centos/

  2. yum安装gcc相关环境(需要确保 虚拟机可以上外网 )

    yum -y install gcc
    yum -y install gcc-c++
  3. 卸载旧版

    yum remove docker \
            docker-client \
            docker-client-latest \
            docker-common \
            docker-latest \
            docker-latest-logrotate \
            docker-logrotate \
            docker-engine
  4. 安装需要的软件包

    yum install -y yum-utils
  5. 设置镜像仓库

    sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
  6. 更新yum软件包索引

    yum makecache fast
  7. 安装 Docker CE

    yum -y install docker-ce docker-ce-cli containerd.io
  8. 启动 Docker

    启动docker:systemctl start docker
    停止docker:systemctl stop docker
    重启docker:systemctl restart docker
    查看docker状态:systemctl status docker
    开机启动:systemctl enable docker
  9. 测试

    docker version
  10. 卸载

    systemctl stop docker
    
    yum -y remove docker-ce docker-ce-cli containerd.io
    
    rm -rf /var/lib/docker

阿里云镜像加速

地址: https://cr.console.aliyun.com/cn-qingdao/instances?accounttraceid=05fa223d3d994e36affcaae109784051wavm

镜像容器服务

image-20220825215330151

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://cdfyp5gh.mirror.aliyuncs.com"],
  "dns": ["8.8.8.8", "114.114.114.114"]
}

EOF
sudo systemctl daemon-reload
sudo systemctl restart docker


#"dns": ["8.8.8.8", "114.114.114.114"] 添加docker dns解析 不然使用构建镜像可能会卡

底层原理

Docker是怎么工作的

​ Docker是一个Client-Server结构的系统,Docker守护进程运行在主机上, 然后通过Socket连接从客户端访问,守护进程从客户端接受命令并管理运行在主机上的容器。 容器,是一个运行时环境,就是我们前面说到的集装箱。

image-20220825220239467

为什么Docker比较 VM 快

1、docker有着比虚拟机更少的抽象层。由亍docker不需要Hypervisor实现硬件资源虚拟化,运行在docker容器上的程序直接使用的都是实际物理机的硬件资源。因此在CPU、内存利用率上docker将会在效率上有明显优势。

2、docker利用的是宿主机的内核,而不需要Guest OS。因此,当新建一个容器时,docker不需要和虚拟机一样重新加载一个操作系统内核。仍而避免引寻、加载操作系统内核返个比较费时费资源的过程,当新建一个虚拟机时,虚拟机软件需要加载Guest OS,返个新建过程是分钟级别的。而docker由于直接利用宿主机的操作系统,则省略了返个过程,因此新建一个docker容器只需要几秒钟。

image-20220825220349832

Docker常用命令

帮助命令

docker version 		# 显示 Docker 版本信息。

docker info 		# 显示 Docker 系统信息,包括镜像和容器数。。

docker --help 		# 帮助

镜像命令

docker images

# 列出本地主机上的镜像
[root@localhost ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
tomcat       8.5.3     2f36caa8fd48   6 years ago   345MB

# 解释
REPOSITORY 镜像的仓库源
TAG 镜像的标签
IMAGE ID 镜像的ID
CREATED 镜像创建时间
SIZE 镜像大小

# 同一个仓库源可以有多个 TAG,代表这个仓库源的不同版本,我们使用REPOSITORY:TAG 定义不同的镜像,如果你不定义镜像的标签版本,docker将默认使用 	lastest 镜像!

# 可选项
-a: 列出本地所有镜像
-q: 只显示镜像id
--digests: 显示镜像的摘要信息

docker search

[root@localhost ~]# docker search  redis
NAME                                        DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
redis                                       Redis is an open source key-value store that…   11267     [OK]
bitnami/redis                               Bitnami Redis Docker Image                      229                  [OK]
bitnami/redis-sentinel                      Bitnami Docker Image for Redis Sentinel         39                   [OK]

# docker search 某个镜像的名称 对应DockerHub仓库中的镜像
-f=stars=50 列出收藏数不小于指定值的镜像。

[root@localhost ~]# docker search -f=stars=50  redis
NAME            DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
redis           Redis is an open source key-value store that…   11267     [OK]
bitnami/redis   Bitnami Redis Docker Image                      229                  [OK]

docker pull

[root@localhost ~]# docker pull redis:6.0.0
6.0.0: Pulling from library/redis
54fec2fa59d0: Pull complete
9c94e11103d9: Pull complete
04ab1bfc453f: Pull complete
444196580a10: Pull complete
712be9efca72: Pull complete
4c8b54d8d272: Pull complete
Digest: sha256:9c2d321d367c582fc103ad36b7326a0edd5b558e0c987d0bea3b58bac008b20f            #签名
Status: Downloaded newer image for redis:6.0.0
docker.io/library/redis:6.0.0															   #位置

[root@localhost ~]# docker pull redis
#不写tag默认下载最新

docker rmi

# 删除镜像 
docker rmi -f 镜像id # 删除单个
docker rmi -f 镜像名:tag 镜像名:tag # 删除多个
docker rmi -f $(docker images -qa) # 删除全部

容器命令

docker pull centos

docker run

# 命令
docker run [OPTIONS] IMAGE [COMMAND][ARG...]

# 常用参数说明
--name="Name" 		# 给容器指定一个名字
-d 					# 后台方式运行容器,并返回容器的id!

-i	 				# 以交互模式运行容器,通过和 -t 一起使用
-t 					# 给容器重新分配一个终端,通常和 -i 一起使用

-P 					# 随机端口映射(大写)
-p 					# 指定端口映射(小结),一般可以有四种写法
--restart=always	# 容器在docker启动自动拉起
    ip:hostPort:containerPort
    ip::containerPort
    hostPort:containerPort (常用)
	containerPort

[root@localhost ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
centos       latest    5d0da3dc9764   11 months ago   231MB
redis        6.0.0     96812ab2b931   2 years ago     104MB
tomcat       8.5.3     2f36caa8fd48   6 years ago     345MB

[root@localhost ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
centos       latest    5d0da3dc9764   11 months ago   231MB
redis        6.0.0     96812ab2b931   2 years ago     104MB
tomcat       8.5.3     2f36caa8fd48   6 years ago     345MB
[root@localhost ~]# docker run -it centos /bin/bash
[root@d0fc31ebe3bc /]#  已经进入容器   d0fc31ebe3bc 容器id

exit # 容器停止退出
ctrl+P+Q # 容器不停止退出

docker ps

# 命令
docker ps [OPTIONS]

# 常用参数说明
-a 			# 列出当前所有正在运行的容器 + 历史运行过的容器
-l 			# 显示最近创建的容器
-n=? 		# 显示最近n个创建的容器
-q 			# 静默模式,只显示容器编号。

docker rm

docker rm 容器id 						   # 删除指定容器
docker rm -f $(docker ps -a -q) 		# 删除所有容器
docker ps -a -q|xargs docker rm 		# 删除所有容器

启动停止容器

docker start (容器id or 容器名) 			# 启动容器
docker restart (容器id or 容器名) 		# 重启容器
docker stop (容器id or 容器名) 			# 停止容器
docker kill (容器id or 容器名) 			# 强制停止容器

常用其他命令

后台启动容器

# 命令
docker run -d 容器名

# 例子
docker run -d centos # 启动centos,使用后台方式启动
# 问题: 使用docker ps 查看,发现容器已经退出了!
# 解释:Docker容器后台运行,就必须有一个前台进程,容器运行的命令如果不是那些一直挂起的命令,就会自动退出。
# 比如,你运行了nginx服务,但是docker前台没有运行应用,这种情况下,容器启动后,会立即自杀,因为他觉得没有程序了,所以最好的情况是,将你的应用使用前台进程的方式运行启动。

查看日志

# 命令
docker logs -f -t --tail 容器id

[root@localhost ~]# docker run -d centos /bin/sh -c "while true;do echo fanmei;sleep 1;done"
7a00721d6b1bca7733370f52f541ff7f4e86ebb4bed26b0f64dc9c937db04f66
[root@localhost ~]# docker ps -a
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS          PORTS      	NAMES                
7a00721d6b1b   centos         "/bin/sh -c 'while t…"   5 seconds ago    Up 4 seconds    			kind_poitras

[root@localhost ~]# docker logs -tf --tail 10 7a00721d6b1b
2022-08-25T15:04:01.170964764Z fanmei
2022-08-25T15:04:02.174736034Z fanmei
2022-08-25T15:04:03.179511199Z fanmei
2022-08-25T15:04:04.182107999Z fanmei
2022-08-25T15:04:05.185409175Z fanmei

docker top

image-20220825230810064

docker inspect 容器id

关于容器的全部信息

image-20220825231045275

进入正在运行的容器

docker exec -it 容器id /bin/bash  (建议)

docker attach 容器id

# 区别
# exec 是在容器中打开新的终端,并且可以启动新的进程		
# attach 直接进入容器启动命令的终端,不会启动新的进程  (exit 会关闭容器)

docker stats

查看内存运行情况

[root@localhost ~]# docker stats 179e6f26f7ae
CONTAINER ID   NAME           CPU %     MEM USAGE / LIMIT    MEM %     NET I/O           BLOCK I/O    PIDS
179e6f26f7ae   tomcat-18080   0.15%     127.5MiB / 3.84GiB   3.24%     9.26kB / 72.1kB   139kB / 0B   38
CONTAINER ID   NAME           CPU %     MEM USAGE / LIMIT    MEM %     NET I/O           BLOCK I/O    PIDS
179e6f26f7ae   tomcat-18080   0.15%     127.5MiB / 3.84GiB   3.24%     9.26kB / 72.1kB   139kB / 0B   38
CONTAINER ID   NAME           CPU %     MEM USAGE / LIMIT    MEM %     NET I/O           BLOCK I/O    PIDS

docker cp

# 拷贝 容器内的到本地
docker cp  容器id:/容器路径/file /本机路径 

#拷贝 本地的到容器内
docker cp  /本机路径/file 容器id:/容器路径/

类似于scp

Image

docker export/import

docker export 导出容器的内容留作为一个tar归档文件[对应import命令]
docker import 从tar包中的内容创建一个新的文件系统再导入为镜像[对应export]

#导出
docker export 51d5366c2369 > ubuntu0708.tgz 
#导入为一个新的镜像
cat ubuntu0702.tgz | docker import - upchina/ubuntu:2.1 (新建一个以前容器的镜像)

总结

image-20220825232029751

attach Attach to a running container		 		# 当前 shell 下attach 连接指定运行镜像
build Build an image from a Dockerfile 		 		# 通过 Dockerfile 定制镜像
commit Create a new image from a container changes 	# 提交当前容器为新的镜像
cp Copy files/folders from the containers filesystem to the host path  #从容器中拷贝指定文件或者目录到宿主机中
create Create a new container 						# 创建一个新的容器,同run,但不启动容器
diff Inspect changes on a container's filesystem 	# 查看 docker 容器变化
events Get real time events from the server 		# 从 docker 服务获取容器实时事件
exec Run a command in an existing container 		# 在已存在的容器上运行命令 ex
export Stream the contents of a container as a tar archive # 导出容器的内容流作为一个 tar 归档文件[对应 import ]
history Show the history of an image 				# 展示一个镜像形成历史
images List images 									# 列出系统当前镜像
import Create a new filesystem image from the contents of a tarball # 从tar包中的内容创建一个新的文件系统映像[对应export]
info Display system-wide information 				# 显示系统相关信息
inspect Return low-level information on a container # 查看容器详细信息
kill Kill a running container # kill 指定 docker 容器 
load Load an image from a tar archive # 从一个 tar 包中加载一个镜像[对应 save]
login Register or Login to the docker registry server # 注册或者登陆一个docker 源服务器
logout Log out from a Docker registry server # 从当前 Docker registry 退出
logs Fetch the logs of a container # 输出当前容器日志信息
port Lookup the public-facing port which is NAT-ed to PRIVATE_PORT #查看映射端口对应的容器内部源端口
pause Pause all processes within a container # 暂停容器
ps List containers # 列出容器列表
pull Pull an image or a repository from the docker registry server #从docker镜像源服务器拉取指定镜像或者库镜像
push Push an image or a repository to the docker registry server #推送指定镜像或者库镜像至docker源服务器
restart Restart a running container # 重启运行的容器
rm Remove one or more containers # 移除一个或者多个容器
rmi Remove one or more images # 移除一个或多个镜像[无容器使用该镜像才可删除,否则需删除相关容器才可继续或 -f 强制删除]
run Run a command in a new container # 创建一个新的容器并运行一个命令
save Save an image to a tar archive # 保存一个镜像为一个tar 包[对应 load]
search Search for an image on the Docker Hub # 在 docker hub 中搜索镜像
start Start a stopped containers # 启动容器
stop Stop a running containers # 停止容器
tag Tag an image into a repository # 给源中镜像打标签
top Lookup the running processes of a container # 查看容器中运行的进程信息 
unpause Unpause a paused container # 取消暂停容器
version Show the docker version information # 查看 docker 版本号
wait Block until a container stops, then print its exit code # 截取容器停止时的退出状态值
# 安装 es
# -e 参数可查docker hub
[root@localhost ~]# docker run -d --name=my-es -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch
a14b8cffe9feccdc7dc307c55ca093057830b1b96c22a81ecba149675323c3d7

[root@localhost ~]# docker stat a14b8cffe9fe
docker: 'stat' is not a docker command.
See 'docker --help'
[root@localhost ~]# docker stats a14b8cffe9fe
CONTAINER ID   NAME      CPU %     MEM USAGE / LIMIT    MEM %     NET I/O     BLOCK I/O     PIDS
a14b8cffe9fe   my-es     0.10%     222.5MiB / 3.84GiB   5.66%     656B / 0B   0B / 56.3kB   44
CONTAINER ID   NAME      CPU %     MEM USAGE / LIMIT    MEM %     NET I/O     BLOCK I/O     PIDS
a14b8cffe9fe   my-es     0.10%     222.5MiB / 3.84GiB   5.66%     656B / 0B   0B / 56.3kB   44
CONTAINER ID   NAME      CPU %     MEM USAGE / LIMIT    MEM %     NET I/O     BLOCK I/O     PIDS
a14b8cffe9fe   my-es     0.32%     222.4MiB / 3.84GiB   5.66%     656B / 0B   0B / 56.3kB   43

可视化

Portainer(先用这个)

# --restart=always docker 启动自动拉起容器
docker run -d -p 9000:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer

# 设置账号,记住密码  admin/upchina@999

Rancher(CI/CD 用这个,公司目前使用的就是Rancher)

#安装rancher-server
docker run --name rancher-server -p 8000:8080 -v
/etc/localtime:/etc/localtime:ro -d rancher/server
#安装agent
docker run --rm --privileged -v /var/run/docker.sock:/var/run/docker.sock -v
/var/lib/rancher:/var/lib/rancher rancher/agent:v1.2.11
http://39.101.191.131:8000/v1/scripts/D3DBD43F263109BB881F:1577750400000:7M0y
BzCw4XSxJklD7TpysYIpI

​ Portainer是Docker的图形化管理工具,提供状态显示面板、应用模板快速部署、容器镜像网络数据卷的基本操作(包括上传下载镜像,创建容器等操作)、事件日志显示、容器控制台操作、Swarm集群和服务等集中管理和操作、登录用户管理和控制等功能。功能十分全面,基本能满足中小型单位对容器管理的全部需求。如果仅有一个docker宿主机,则可使用单机版运行,Portainer单机版运行十分简单,只需要一条语句即可启动容器,来管理该机器上的docker镜像、容器等数据

image-20220825235458805

Docker镜像讲解

镜像是什么

​ 镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。

Docker镜像加载原理

UnionFS (联合文件系统)

​ UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union 文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录

Docker镜像加载原理

docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。bootfs(boot file system)主要包含bootloader和kernel, bootloader主要是引导加载kernel, Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。rootfs (root file system) ,在bootfs之上。包含的就是典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。

image-20220827144014482

​ 平时我们安装进虚拟机的CentOS都是好几个G,为什么Docker这里才200M?

​ 对于一个精简的OS,rootfs 可以很小,只需要包含最基本的命令,工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供rootfs就可以了。由此可见对于不同的linux发行版, bootfs基本是一致的, rootfs会有差别, 因此不同的发行版可以公用bootfs。

分层理解

分层的镜像

​ 我们可以去下载一个镜像,注意观察下载的日志输出,可以看到是一层一层的在下载!

[root@localhost ~]# docker pull redis:6.0.0
6.0.0: Pulling from library/redis
54fec2fa59d0: Pull complete
9c94e11103d9: Pull complete
04ab1bfc453f: Pull complete
444196580a10: Pull complete
712be9efca72: Pull complete
4c8b54d8d272: Pull complete
Digest: sha256:9c2d321d367c582fc103ad36b7326a0edd5b558e0c987d0bea3b58bac008b20f
Status: Downloaded newer image for redis:6.0.0
docker.io/library/redis:6.0.0

思考:为什么Docker镜像要采用这种分层的结构呢?

​ 最大的好处,我觉得莫过于是资源共享了!比如有多个镜像都从相同的Base镜像构建而来,那么宿主机只需在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享。

查看镜像分层的方式可以通过 docker image inspect 命令!

docker image inspect redis:6.0.0

image-20220827150533317

​ 所有的 Docker 镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。 ​ 举一个简单的例子,假如基于 Ubuntu Linux 16.04 创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加 Python包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。

​ 该镜像当前已经包含 3 个镜像层,如下图所示(这只是一个用于演示的很简单的例子)

image-20220827150718967

​ 在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点非常重要。下图中举了一个简单的例子,每个镜像层包含 3 个文件,而镜像包含了来自两个镜像层的 6 个文件。

image-20220827150755425

​ 上图中的镜像层跟之前图中的略有区别,主要目的是便于展示文件。

​ 下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有 6 个文件,这是因为最上层中的文件7 是文件 5 的一个更新版本。

image-20220827150855018

​ 这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。 ​ Docker 通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。 ​ Linux 上可用的存储引擎有 AUFS、Overlay2、Device Mapper、Btrfs 以及 ZFS。顾名思义,每种存储引擎都基于 Linux 中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。Docker 在 Windows 上仅支持 windowsfilter 一种存储引擎,该引擎基于 NTFS 文件系统之上实现了分层和 CoW[1]。 下图展示了与系统显示相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图。

image-20220827150951748

特点

Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部!这一层就是我们通常说的容器层,容器之下的都叫镜像层!

镜像Commit

docker commit 从容器创建一个新的镜像。

docker commit 提交容器副本使之成为一个新的镜像!
# 语法
docker commit -m="提交的描述信息" -a="作者" 容器id 要创建的目标镜像名:[标签名]

提交自己的镜像

[root@localhost ~]# docker images
REPOSITORY            TAG       IMAGE ID       CREATED         SIZE
nginx                 latest    605c77e624dd   8 months ago    141MB
centos                7         eeb6ee3f44bd   11 months ago   204MB
portainer/portainer   latest    580c0e4e98b0   17 months ago   79.1MB
redis                 6.0.0     96812ab2b931   2 years ago     104MB
elasticsearch         latest    5acf0e8da90b   3 years ago     486MB
tomcat                8.5.3     2f36caa8fd48   6 years ago     345MB

[root@localhost ~]# docker commit -a="merrillfan" -m="with vim and net-tool" e8b472524a55 mf/centos:7.0.0
sha256:1795687bb6bca720f178ad66d1cc142c45ef6706feaa1fa1cc72f370673de4fe
[root@localhost ~]# docker images
REPOSITORY            TAG       IMAGE ID       CREATED         SIZE
mf/centos             7.0.0     1795687bb6bc   5 seconds ago   442MB
nginx                 latest    605c77e624dd   8 months ago    141MB
centos                7         eeb6ee3f44bd   11 months ago   204MB
portainer/portainer   latest    580c0e4e98b0   17 months ago   79.1MB
redis                 6.0.0     96812ab2b931   2 years ago     104MB
elasticsearch         latest    5acf0e8da90b   3 years ago     486MB
tomcat                8.5.3     2f36caa8fd48   6 years ago     345MB

容器数据卷

什么是容器数据卷

docker的理念回顾:

​ 将应用和运行的环境打包形成容器运行,运行可以伴随着容器,但是我们对于数据的要求,是希望能够持久化的!就好比,你安装一个MySQL,结果你把容器删了,就相当于删库跑路了. 所以我们希望容器之间有可能可以共享数据,Docker容器产生的数据,如果不通过docker commit 生成新的镜像,使得数据作为镜像的一部分保存下来,那么当容器删除后,数据自然也就没有了!这样是行不通的! ​ 为了能保存数据在Docker中我们就可以使用卷!让数据挂载到我们本地!这样数据就不会因为容器删除而丢失!

作用:

​ 卷就是目录或者文件,存在一个或者多个容器中,由docker挂载到容器,但不属于联合文件系统,因此能够绕过 Union File System , 提供一些用于持续存储或共享数据的特性:卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷。 特点: 1、数据卷可在容器之间共享或重用数据 2、卷中的更改可以直接生效 3、数据卷中的更改不会包含在镜像的更新中 4、数据卷的生命周期一直持续到没有容器使用它为止 所以:总结一句话: 就是容器的持久化,以及容器间的继承和数据共享!

使用数据卷

方式一:容器中直接使用命令来添加

# 命令
docker run -it -v 宿主机绝对路径目录:容器内目录 镜像名

[root@localhost app_log]# docker run --name=centos1 -it -v /usr/local/app/taf/app_log/:/usr/local/app/taf/app_log/ 		mf/centos:7.0.0  /bin/bash

# 容器内部也可以查看日志了
[root@ab1833ac9985 app_log]# cd /usr/local/app/taf/app_log/taf/tafnode/
[root@ab1833ac9985 tafnode]# ll
total 78148
-rw-rw-rw- 1 1000 1000  3115078 Aug 27 16:21 taf.tafnode.log
-rw-rw-rw- 1 root root 10490616 Aug 25 16:00 taf.tafnode1.log
-rw-rw-rw- 1 root root  4782199 Aug 27 16:21 taf.tafnode_KeepAliveThread.log
-rw-rw-rw- 1 1000 1000 10496579 Aug 27 15:56 taf.tafnode_KeepAliveThread1.log
-rw-rw-rw- 1 1000 1000 10493604 Aug 25 16:03 taf.tafnode_KeepAliveThread2.log
-rw-rw-rw- 1 1000 1000 10490328 Aug 25 15:08 taf.tafnode_KeepAliveThread3.log
-rw-rw-rw- 1 root root 10504470 Aug 25 14:12 taf.tafnode_KeepAliveThread4.log
-rw-rw-rw- 1 1000 1000  8971141 Aug 27 16:21 taf.tafnode_ReportThread.log
-rw-rw-rw- 1 root root 10490916 Aug 25 14:57 taf.tafnode_ReportThread1.log
-rw-rw-rw- 1 1000 1000     7043 Aug 27 15:00 taf.tafnode_startServer.log
-rw-rw-rw- 1 1000 1000     3649 Aug 25 13:33 taf.tafnode_stopServer.log
-rw-rw-rw- 1 1000 1000    23534 Aug 27 15:00 taf.tafnode_synState.log
docker inspect 容器ID

image-20220827162532463

容器中写文件本地也能看达到 ,关闭容器,本地创建文件容器也能同步

使用 docker 安装 mysql

mysql 数据持久化到本地

# 启动容器 -e 环境变量!

[root@localhost ~]# docker images
REPOSITORY            TAG       IMAGE ID       CREATED          SIZE
mf/centos             7.0.0     1795687bb6bc   31 minutes ago   442MB
nginx                 latest    605c77e624dd   8 months ago     141MB
mysql                 5.7       c20987f18b13   8 months ago     448MB
centos                7         eeb6ee3f44bd   11 months ago    204MB
portainer/portainer   latest    580c0e4e98b0   17 months ago    79.1MB
redis                 6.0.0     96812ab2b931   2 years ago      104MB
elasticsearch         latest    5acf0e8da90b   3 years ago      486MB
tomcat                8.5.3     2f36caa8fd48   6 years ago      345MB

[root@localhost docker-vol]# docker run -d -p 13306:3306 -v /data/docker-vol/mysql/conf:/etc/mysql/conf.d -v /data/docker-vol/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7

启动成功,创建表检查,持久化成功

image-20220827165636865

匿名和具名挂载

# 匿名挂载
-v 容器内路径
docker run -d -P --name nginx01 -v /etc/nginx nginx
# 匿名挂载的缺点,就是不好维护,通常使用命令 docker volume维护
[root@localhost local]# docker volume ls
DRIVER    VOLUME NAME
local     04c612ec29f5e933119005535112de6dc792ae6bf9c08b9c693886aa733f79e3  #匿名挂载
local     84a0a957a2b7708a55ad3ee759246d5ffc82bd4f3e8e75abd09410016332e055
local     d5e4da8c364bef0c330123088590fdf65739ef46e02d4eea09c03a82043530d7
local     nginxconfig


# 具名挂载
# -v 卷名:/容器内路径
[root@localhost local]# docker run -d -P --name nginx02 -v nginxconfig:/etc/nginx nginx
4abf23902db21da5cabd58e2a1ff604ef3817f1be43571b27304b5a008f097aa
[root@localhost local]# docker volume inspect nginxconfig
[
    {
        "CreatedAt": "2022-08-28T01:32:12+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/nginxconfig/_data",
        "Name": "nginxconfig",
        "Options": null,
        "Scope": "local"
    }
]


# 怎么判断挂载的是卷名而不是本机目录名?
# 不是/开始就是卷名,是/开始就是目录名
# 改变文件的读写权限
# ro: readonly
# rw: readwrite
# 指定容器对我们挂载出来的内容的读写权限
docker run -d -P --name nginx02 -v nginxconfig:/etc/nginx:ro nginx
docker run -d -P --name nginx02 -v nginxconfig:/etc/nginx:rw nginx

# 当提示没有权限可以加上  --privileged=true  解决

数据卷容器

命名的容器挂载数据卷,其他容器通过挂载这个(父容器)实现数据共享,挂载数据卷的容器,称之为数据卷容器。

[root@localhost ~]# docker images
REPOSITORY            TAG       IMAGE ID       CREATED         SIZE
mf/centos             7.0.0     1795687bb6bc   2 days ago      442MB

[root@localhost ~]# docker run -it --name=centos1 -v data:/home/upchina mf/centos:7.0.0

[root@localhost ~]# docker ps
CONTAINER ID   IMAGE                 COMMAND                  CREATED              STATUS          PORTS      NAMES       
a415a0509f92   mf/centos:7.0.0       "/bin/bash"              About a minute ago   Up 3 seconds               centos1

[root@localhost ~]# docker inspect a415a0509f92
....
      "Mounts": [
            {
                "Type": "volume",
                "Name": "data",
                "Source": "/var/lib/docker/volumes/data/_data",
                "Destination": "/home/upchina",
                "Driver": "local",
                "Mode": "z",
                "RW": true,
                "Propagation": ""
            }
        ],
...
[root@1b74573952bd /]# [root@localhost ~]# docker run -it --name=centos2 --volumes-from centos1  mf/centos:7.0.0
[root@1b74573952bd /]# [root@localhost ~]# docker run -it --name=centos3 --volumes-from centos1  mf/centos:7.0.0

#可以看到容器1中创建的文件 centos2 centos3 都能看到
[root@localhost ~]# docker exec -it centos2 bash
[root@5dfeb19e62a5 /]# cd /home/upchina/
[root@5dfeb19e62a5 upchina]# ll
total 4
-rw-r--r-- 1 root root 6 Aug 29 22:28 test1.txt

#删除容器1后 在容器2中创建文件 ,容器3依旧能共享挂载

[root@localhost ~]# docker exec -it centos2 bash
[root@5dfeb19e62a5 /]# cd /home/upchina/
[root@5dfeb19e62a5 upchina]# ll
total 4
-rw-r--r-- 1 root root 6 Aug 29 22:28 test1.txt
[root@5dfeb19e62a5 upchina]# vi test2-in-os2.txt
[root@5dfeb19e62a5 upchina]# read escape sequence
[root@localhost ~]# docker exec -it centos3 bash
[root@1b74573952bd /]# cd /home/upchina/
[root@1b74573952bd upchina]# ll
total 8
-rw-r--r-- 1 root root 6 Aug 29 22:28 test1.txt
-rw-r--r-- 1 root root 5 Aug 29 22:38 test2-in-os2.txt

得出结论: 容器之间配置信息的传递,数据卷的生命周期一直持续到没有容器使用它为止。存储在本机的文件则会一直保留!

DockerFile

微服务打包成镜像,任何装了Docker的地方,都可以下载使用,极其的方便。 流程:开发应用=>DockerFile=>打包为镜像=>上传到仓库(私有仓库,公有仓库)=> 下载镜像 => 启动运行。 还可以方便移植!

什么是DockerFile

dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本。 构建步骤: 1、编写DockerFile文件 2、docker build 构建镜像 3、docker run dockerfile文件我们刚才已经编写过了一次,这里我们继续使用 centos 来看! 地址:https://hub.docker.com/_/centos

image-20220829230511498

image-20220829230537580

DockerFile构建过程

基础知识: 1、每条保留字指令都必须为大写字母且后面要跟随至少一个参数 2、指令按照从上到下,顺序执行 3、# 表示注释 4、每条指令都会创建一个新的镜像层,并对镜像进行提交

流程: 1、docker从基础镜像运行一个容器 2、执行一条指令并对容器做出修改 3、执行类似 docker commit 的操作提交一个新的镜像层 4、Docker再基于刚提交的镜像运行一个新容器 5、执行dockerfile中的下一条指令直到所有指令都执行完成

! 说明: 从应用软件的角度来看,DockerFile,docker镜像与docker容器分别代表软件的三个不同阶段。 DockerFile 是软件的原材料 (代码) Docker 镜像则是软件的交付品 (.apk) Docker 容器则是软件的运行状态 (客户下载安装执行) DockerFile 面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可! DockerFile:需要定义一个DockerFile,DockerFile定义了进程需要的一切东西。DockerFile涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当引用进行需要和系统服务和内核进程打交道,这时需要考虑如何设计 namespace的权限控制)等等。 Docker镜像:在DockerFile 定义了一个文件之后,Docker build 时会产生一个Docker镜像,当运行 Docker 镜像时,会真正开始提供服务; Docker容器:容器是直接提供服务的。

DockerFile指令

FROM # 基础镜像,当前新镜像是基于哪个镜像的
MAINTAINER # 镜像维护者的姓名混合邮箱地址
RUN # 容器构建时需要运行的命令
EXPOSE # 当前容器对外保留出的端口
WORKDIR # 指定在创建容器后,终端默认登录的进来工作目录,一个落脚点
ENV # 用来在构建镜像过程中设置环境变量
ADD # 将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包
COPY # 类似ADD,拷贝文件和目录到镜像中!
VOLUME # 容器数据卷,用于数据保存和持久化工作
CMD # 指定一个容器启动时要运行的命令,dockerFile中可以有多个CMD指令,但只有最
后一个生效!
ENTRYPOINT # 指定一个容器启动时要运行的命令!和CMD一样
ONBUILD # 当构建一个被继承的DockerFile时运行命令,父镜像在被子镜像继承后,父镜像的ONBUILD被触发

image-20220829231324035

编写dockerfile

Docker Hub 中99% 的镜像都是通过在base镜像(Scratch)中安装和配置需要的软件构建出来的

FROM scratch
ADD centos-7-x86_64-docker.tar.xz /

LABEL \
    org.label-schema.schema-version="1.0" \
    org.label-schema.name="CentOS Base Image" \
    org.label-schema.vendor="CentOS" \
    org.label-schema.license="GPLv2" \
    org.label-schema.build-date="20201113" \
    org.opencontainers.image.title="CentOS Base Image" \
    org.opencontainers.image.vendor="CentOS" \
    org.opencontainers.image.licenses="GPL-2.0-only" \
    org.opencontainers.image.created="2020-11-13 00:00:00+00:00"

CMD ["/bin/bash"]

自定义一个 centos

使用docker编写一个带vim ,ifconfig的镜像 (官方缩小版没有)

[root@localhost docker]# cat Centos-Dockerfile
# 父镜像
FROM centos:7
# log
CMD echo "----------build begining!!--------"
#作者及邮箱
MAINTAINER merrillfan<merrillfan@aliyun.com>
#定义环境变量
ENV MYPATH /usr/local
#后面的shell工作路径
WORKDIR $MYPATH
#安装vim
RUN yum -y install vim
#安装网络命令工具
RUN yum -y install net-tools
#暴露 80端口	
EXPOSE 80

#log
CMD echo $MYPATH
CMD echo "----------build success!!--------"

#最终使用容器启动镜像时的命令
CMD /bin/bash
[root@localhost docker]# docker build -f Centos-Dockerfile -t mf/centos:7.0 .
Sending build context to Docker daemon  2.048kB
Step 1/11 : FROM centos:7
 ---> eeb6ee3f44bd
Step 2/11 : CMD echo "----------build begining!!--------"
 ---> Running in 15b24fba3638
Removing intermediate container 15b24fba3638
 ---> 19b8b7500e01
Step 3/11 : MAINTAINER merrillfan<merrillfan@aliyun.com>
 ---> Running in cc357e97a94c
Removing intermediate container cc357e97a94c
 ---> 614b452f4966
Step 4/11 : ENV MYPATH /usr/local
 ---> Running in 7184d101c7ca
Removing intermediate container 7184d101c7ca
 ---> 039e84e6b14f
Step 5/11 : WORKDIR $MYPATH
 ---> Running in 7507d84ef1e5
Removing intermediate container 7507d84ef1e5
 ---> 5991893cd544
Step 6/11 : RUN yum -y install vim
 ---> Running in 5e04f8253c48
 ...
Complete!
Removing intermediate container 5e04f8253c48
 ---> 81d33168b07f
Step 7/11 : RUN yum -y install net-tools
 ---> Running in b4b6c2ae56bc
 ...
Installed:
  net-tools.x86_64 0:2.0-0.25.20131004git.el7

Complete!
Removing intermediate container b4b6c2ae56bc
 ---> 7bee0b67672f
Step 8/11 : EXPOSE 80
 ---> Running in 0959b2019ee6
Removing intermediate container 0959b2019ee6
 ---> de1989821463
Step 9/11 : CMD echo $MYPATH
 ---> Running in 46308d56c2df
Removing intermediate container 46308d56c2df
 ---> cf2dc20cc695
Step 10/11 : CMD echo "----------build success!!--------"
 ---> Running in 09ea12b532cc
Removing intermediate container 09ea12b532cc
 ---> d0744f15ae66
Step 11/11 : CMD /bin/bash
 ---> Running in 786d97b060fa
Removing intermediate container 786d97b060fa
 ---> 657dec888f5a
Successfully built 657dec888f5a
Successfully tagged mf/centos:7.0
# 校验命令可用
[root@localhost docker]# docker run -it mf/centos:7.0 bash
[root@65dc20981a6b local]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.3  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:ac:11:00:03  txqueuelen 0  (Ethernet)
        RX packets 8  bytes 656 (656.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[root@65dc20981a6b local]# vim

镜像变更历史

# docker history imageID
[root@localhost docker]# docker history 657dec888f5a
IMAGE          CREATED         CREATED BY                                      SIZE      COMMENT
657dec888f5a   4 minutes ago   /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "/bin…   0B
d0744f15ae66   4 minutes ago   /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "echo…   0B
cf2dc20cc695   4 minutes ago   /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "echo…   0B
de1989821463   4 minutes ago   /bin/sh -c #(nop)  EXPOSE 80                    0B
7bee0b67672f   4 minutes ago   /bin/sh -c yum -y install net-tools             182MB
81d33168b07f   4 minutes ago   /bin/sh -c yum -y install vim                   237MB
5991893cd544   5 minutes ago   /bin/sh -c #(nop) WORKDIR /usr/local            0B
039e84e6b14f   5 minutes ago   /bin/sh -c #(nop)  ENV MYPATH=/usr/local        0B
614b452f4966   5 minutes ago   /bin/sh -c #(nop)  MAINTAINER merrillfan<mer…   0B
19b8b7500e01   5 minutes ago   /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "echo…   0B
eeb6ee3f44bd   11 months ago   /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B
<missing>      11 months ago   /bin/sh -c #(nop)  LABEL org.label-schema.sc…   0B
<missing>      11 months ago   /bin/sh -c #(nop) ADD file:b3ebbe8bd304723d4…   204MB

CMD 和 ENTRYPOINT 的区别

两个命令都是指定一个容器启动时要运行的命令

CMD:Dockerfile 中可以有多个CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换! ENTRYPOINT: docker run 之后的参数会被当做参数传递给 ENTRYPOINT,之后形成新的命令组合!

1.CMD

[root@localhost docker]# vi Cmd.DcokerFile
[root@localhost docker]# cat Cmd.DcokerFile
FROM centos:7

CMD ["ls","-a"]
[root@localhost docker]# docker build -f Cmd.DcokerFile -t cmdtest .
Sending build context to Docker daemon  3.072kB
Step 1/2 : FROM centos:7
 ---> eeb6ee3f44bd
Step 2/2 : CMD ["ls","-a"]
 ---> Running in 6429dcb79c2e
Removing intermediate container 6429dcb79c2e
 ---> 6ac7da7b1f30
Successfully built 6ac7da7b1f30
Successfully tagged cmdtest:latest
[root@localhost docker]# docker run cmdtest
...
sbin
srv
sys
tmp
usr
var
[root@localhost docker]# docker run cmdtest -l
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "-l": executable file not found in $PATH: unknown.
ERRO[0001] error waiting for container: context canceled

2.ENTRYPOINT

[root@localhost docker]# vi entrypoint.dockerfile
[root@localhost docker]# cat entrypoint.dockerfile
FROM centos:7

ENTRYPOINT ["ls","-a"]
[root@localhost docker]# docker build -f entrypoint.dockerfile -t entrypoint-test .
Sending build context to Docker daemon  4.096kB
Step 1/2 : FROM centos:7
 ---> eeb6ee3f44bd
Step 2/2 : ENTRYPOINT ["ls","-a"]
 ---> Running in 6888df6f3a47
Removing intermediate container 6888df6f3a47
 ---> d17f4fa21e21
Successfully built d17f4fa21e21
Successfully tagged entrypoint-test:latest
[root@localhost docker]# docker run entrypoint-test
.
..
.dockerenv
anaconda-post.log
bin
dev
etc
home
...
[root@localhost docker]# docker run entrypoint-test -l
total 12
drwxr-xr-x   1 root root     6 Aug 30 22:25 .
drwxr-xr-x   1 root root     6 Aug 30 22:25 ..
-rwxr-xr-x   1 root root     0 Aug 30 22:25 .dockerenv
-rw-r--r--   1 root root 12114 Nov 13  2020 anaconda-post.log
lrwxrwxrwx   1 root root     7 Nov 13  2020 bin -> usr/bin
drwxr-xr-x   5 root root   340 Aug 30 22:25 dev
drwxr-xr-x   1 root root    66 Aug 30 22:25 etc
drwxr-xr-x   2 root root     6 Apr 11  2018 home
...

tomcat

# vim Dockerfile
FROM centos
MAINTAINER kuangshen<24736743@qq.com>
#把宿主机当前上下文的read.txt拷贝到容器/usr/local/路径下
COPY read.txt /usr/local/cincontainer.txt
#把java与tomcat添加到容器中
ADD jdk-8u11-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.22.tar.gz /usr/local/
#安装vim编辑器
RUN yum -y install vim
#设置工作访问时候的WORKDIR路径,登录落脚点
ENV MYPATH /usr/local
WORKDIR $MYPATH
#配置java与tomcat环境变量
ENV JAVA_HOME /usr/local/jdk1.8.0_11
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.22
ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.22
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
#容器运行时监听的端口
EXPOSE 8080
#启动时运行tomcat
# ENTRYPOINT ["/usr/local/apache-tomcat-9.0.22/bin/startup.sh" ]
# CMD ["/usr/local/apache-tomcat-9.0.22/bin/catalina.sh","run"]
CMD /usr/local/apache-tomcat-9.0.22/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.22/bin/logs/catalina.out

发布镜像

发布到 Dockerhub

首先注册一个Dockerhub用户

#1.登录
[root@localhost docker]# docker login --help

Usage:  docker login [OPTIONS] [SERVER]

Log in to a Docker registry.
If no server is specified, the default is defined by the daemon.

Options:
  -p, --password string   Password
      --password-stdin    Take the password from stdin
  -u, --username string   Username
[root@localhost docker]# docker login -u merrillfan
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

[root@localhost docker]# docker images
REPOSITORY            TAG       IMAGE ID       CREATED          SIZE
entrypoint-test       latest    d17f4fa21e21   10 minutes ago   204MB
cmdtest               latest    6ac7da7b1f30   14 minutes ago   204MB
mf/centos             7.0       657dec888f5a   31 minutes ago   623MB
nginx                 latest    605c77e624dd   8 months ago     141MB
mysql                 5.7       c20987f18b13   8 months ago     448MB
centos                7         eeb6ee3f44bd   11 months ago    204MB
centos                latest    5d0da3dc9764   11 months ago    231MB
portainer/portainer   latest    580c0e4e98b0   17 months ago    79.1MB
redis                 6.0.0     96812ab2b931   2 years ago      104MB
elasticsearch         latest    5acf0e8da90b   3 years ago      486MB
tomcat                8.5.3     2f36caa8fd48   6 years ago      345MB
[root@localhost docker]# docker push entrypoint-test
Using default tag: latest
The push refers to repository [docker.io/library/entrypoint-test]
174f56854903: Preparing

denied: requested access to the resource is denied



#2.发布镜像
[root@localhost docker]# docker push mf/centos:7.0
The push refers to repository [docker.io/mf/centos]
0f4f3a66a802: Preparing
c58a0c7b454e: Preparing
174f56854903: Preparing
# 拒绝:请求的资源访问被拒绝
denied: requested access to the resource is denied

#3.问题:本地镜像名无帐号信息 tag一下
# 注意,tag 后的镜像名中一定要带dockerhub 用户名
[root@localhost docker]# docker tag  mf/centos:7.0 merrillfan/centos:7.0
[root@localhost docker]# docker images
REPOSITORY            TAG       IMAGE ID       CREATED          SIZE
entrypoint-test       latest    d17f4fa21e21   19 minutes ago   204MB
cmdtest               latest    6ac7da7b1f30   23 minutes ago   204MB
merrillfan/centos     7.0       657dec888f5a   40 minutes ago   623MB
mf/centos             7.0       657dec888f5a   40 minutes ago   623MB
nginx                 latest    605c77e624dd   8 months ago     141MB
mysql                 5.7       c20987f18b13   8 months ago     448MB
centos                7         eeb6ee3f44bd   11 months ago    204MB
centos                latest    5d0da3dc9764   11 months ago    231MB
portainer/portainer   latest    580c0e4e98b0   17 months ago    79.1MB
redis                 6.0.0     96812ab2b931   2 years ago      104MB
elasticsearch         latest    5acf0e8da90b   3 years ago      486MB
tomcat                8.5.3     2f36caa8fd48   6 years ago      345MB
[root@localhost docker]# docker push merrillfan/centos:7.0
The push refers to repository [docker.io/merrillfan/centos]
0f4f3a66a802: Pushed
c58a0c7b454e: Pushed
174f56854903: Pushed
7.0: digest: sha256:dabeca8b8a0c4921e856f6583b30cb8261036bb716129abcbbbfd9ba52b48c7c size: 953

发布到阿里云

https://cr.console.aliyun.com/cn-hangzhou/instance/namespaces

1.创建命令空间

image-20220830225355327

2.创建镜像仓库

image-20220830225532407

image-20220830225623292

image-20220830225735485

使用阿里云时的大坑,查了半天

[root@localhost ~]# docker login --username=merrillfan registry.cn-hangzhou.aliyuncs.com
Password:
Error response from daemon: Get "https://registry.cn-hangzhou.aliyuncs.com/v2/": unauthorized: authentication required

https://segmentfault.com/a/1190000039890018?utm_source=sf-similar-article

注意:镜像的登录密码不是你管理台的密码,需要重新设置

image-20220830231856349

#1.登录
[root@localhost ~]# docker login --username=merrillfan registry.cn-hangzhou.aliyuncs.com
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded

REPOSITORY            TAG       IMAGE ID       CREATED             SIZE
mf/centos             7.0       92e1601eac4f   3 minutes ago       623MB
entrypoint-test       latest    d17f4fa21e21   About an hour ago   204MB
cmdtest               latest    6ac7da7b1f30   About an hour ago   204MB
nginx                 latest    605c77e624dd   8 months ago        141MB
mysql                 5.7       c20987f18b13   8 months ago        448MB
centos                7         eeb6ee3f44bd   11 months ago       204MB
centos                latest    5d0da3dc9764   11 months ago       231MB
portainer/portainer   latest    580c0e4e98b0   17 months ago       79.1MB
redis                 6.0.0     96812ab2b931   2 years ago         104MB
elasticsearch         latest    5acf0e8da90b   3 years ago         486MB
tomcat                8.5.3     2f36caa8fd48   6 years ago         345MB
# tag
[root@localhost docker]#  docker tag mf/centos:7.0 registry.cn-hangzhou.aliyuncs.com/merrillfan/docker-test:7.0

# 推送
[root@localhost docker]# docker push registry.cn-hangzhou.aliyuncs.com/merrillfan/docker-test:7.0
The push refers to repository [registry.cn-hangzhou.aliyuncs.com/merrillfan/docker-test]
5df628b75774: Pushed
c13906f22220: Pushed
174f56854903: Pushed
7.0: digest: sha256:1eda8ae18ff2e2b2c4c1b779bd1e53644271e48996fad3b0d1597d342e874a51 size: 953

image-20220830233333229

Docker 网络

docker rm -f $(docker ps -a -q) # 删除所有容器
docker rmi -f $(docker images -qa) # 删除全部镜像

docker的默认网络

原理:每次启动一个docker容器,docker就会给该容器分配一个ip地址,默认安装docker后会有一个docker0网卡。采用桥接模式,使用的是veth-pair技术。

veth-pair技术就是一对虚拟设备接口,成对出现。利用该技术充当一个桥梁,连接虚拟网络设备

# 1.创建一个tomcat容器查看容器内部的网络ip
docker run -d -p 8080:8080 --name mytomcat01 tomcat:9.0 
docker exec -it mytomcat01 ip addr
# 查看输出结果,发现除了本身的回环地址外,额外增加了478: eth0@if479
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
478: eth0@if479: <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

# 2.在主机上查看此时的网络
ip addr
# 查看输出,发现在主机也多了一个额外的ip地址
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:64:4e:34:c4 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:64ff:fe4e:34c4/64 scope link 
       valid_lft forever preferred_lft forever
479: veth3ade909@if478: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 02:e3:97:92:52:e0 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::e3:97ff:fe92:52e0/64 scope link 
       valid_lft forever preferred_lft forever

# 3.尝试在主机ping容器的ip,发现可以ping通
ping 172.17.0.2

# 4.再启动一个容器,查看其内部的ip地址
docker run -d -p 8081:8080 --name mytomcat02 tomcat:9.0 
docker exec -it mytomcat02 ip addr
# 查看输出结果,发现除了本身的回环地址外,额外增加了480: eth0@if481
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
480: eth0@if481: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

# 5.在主机上再次查看此时的网络
ip addr
# 查看输出,发现在主机又多了一个额外的ip地址
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:64:4e:34:c4 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:64ff:fe4e:34c4/64 scope link 
       valid_lft forever preferred_lft forever
479: veth3ade909@if478: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 02:e3:97:92:52:e0 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::e3:97ff:fe92:52e0/64 scope link 
       valid_lft forever preferred_lft forever
481: veth916ff39@if480: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether fe:e6:f6:f7:c3:86 brd ff:ff:ff:ff:ff:ff link-netnsid 1
    inet6 fe80::fce6:f6ff:fef7:c386/64 scope link 
       valid_lft forever preferred_lft forever

# 6.尝试在主机ping容器的ip,发现可以ping通
ping 172.17.0.3

# 7.尝试不同容器之间是否可以ping通,发现两个容器之间均可以相互ping通
docker exec -it mytomcat01 ping 172.17.0.3
docker exec -it mytomcat02 ping 172.17.0.2

# 结论:容器与容器间,主机与容器间均可以相互ping通

image-20220831224438089

​ Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信。

​ Docker容器网络就很好的利用了Linux虚拟网络技术,在本地主机和容器内分别创建一个虚拟接口,并让他们彼此联通(这样一对接口叫veth pair);Docker中的网络接口默认都是虚拟的接口。虚拟接口的优势就是转发效率极高(因为Linux是在内核中进行数据的复制来实现虚拟接口之间的数据转发,无需通过外部的网络设备交换),对于本地系统和容器系统来说,虚拟接口跟一个正常的以太网卡相比并没有区别,只是他的速度快很多

由于使用ip地址不方便,若地址变更,则编写的项目必须重启。需要设计一种机制,将容器名或者容器id与ip地址相互关联。(该方法已经不建议使用,比较笨拙)

# 1.在上一节的测试基础上,再启动一个容器,将该容器与mytomcat02互联
docker run -d -p 8082:8080 --name mytomcat03 --link mytomcat02 tomcat:9.0 
# 2.发现在03中可以直接通过容器名ping通,而不用使用ip地址
docker exec -it mytomcat03 ping mytomcat02

# 3.但是不可以通过02反向ping03,因为没有配置
docker exec -it mytomcat03 cat /etc/hosts
# 可以发现--link实际上就是在该容器的hosts文件中增添了与link容器的映射关系
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  mytomcat02 58fd8151c077
172.17.0.4  cda17937d62e

# 4.查看02的hosts配置
docker exec -it mytomcat02 cat /etc/hosts
# 可以发现在02中并没有配置与03的互联映射关系,故而无法通过容器名ping通
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  58fd8151c077

自定义网络

在创建不同的集群,例如 redis集群,mysql集群时候,可以实现网络之间的相互隔离

# 1.查看当前网卡情况
docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
fadc2303e81c        bridge              bridge              local # 桥接模式
756eeb1985eb        host                host                local # 和宿主机共享
547d72589745        none                null                local # 不配置网络
# 2.创建自定义网络
docker network create --driver bridge --subnet 192.167.0.0/16 --gateway 192.167.0.1 mynet

# 查看当前网络发现已经创建成功
NETWORK ID          NAME                DRIVER              SCOPE
fadc2303e81c        bridge              bridge              local
756eeb1985eb        host                host                local
7dde80cf160c        mynet               bridge              local
547d72589745        none                null                local

# 3.查看自定义网络的配置信息
docker network inspect mynet
[
    {
        "Name": "mynet",
        "Id": "7dde80cf160c4526e37f0d5bd76d30c6c6fe80046d631eaa42852b846202f02c",
        "Created": "2020-07-11T09:55:01.962552613+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.167.0.0/16",
                    "Gateway": "192.167.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

# 4.使用自定义的网络创建两个tomcat容器,若不指定 --net 则默认为bridge(docker0的网络)
docker run -d -P --name mytomcat-net-01 --net mynet tomcat:9.0
docker run -d -P --name mytomcat-net-02 --net mynet tomcat:9.0
# 再次查看自定义网络的配置信息,可以发现已经将两个容器的信息配置到该网络下
docker network inspect mynet
[
    {
        "Name": "mynet",
        "Id": "7dde80cf160c4526e37f0d5bd76d30c6c6fe80046d631eaa42852b846202f02c",
        "Created": "2020-07-11T09:55:01.962552613+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.167.0.0/16",
                    "Gateway": "192.167.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "67308eb3f177f9d14f718e0507eaaaf2088c76f229bfde7da15620af01f348f4": {
                "Name": "mytomcat-net-02",
                "EndpointID": "b636d43051f7abc791df8ae8213e6aac7a6d3769109291b0272ea1fba66c4611",
                "MacAddress": "02:42:c0:a7:00:03",
                "IPv4Address": "192.167.0.3/16",
                "IPv6Address": ""
            },
            "a1c5e7a59d25f130a422a6356cd2005ffab247cc8d92af99e2ccaad0de0b127a": {
                "Name": "mytomcat-net-01",
                "EndpointID": "87f65a4164398c9354d4d22c8d4c1a87c5739b632aa3647081b97cd0b974768f",
                "MacAddress": "02:42:c0:a7:00:02",
                "IPv4Address": "192.167.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]
# 5.在自定义网络下,可以直接使用容器名来ping通网络
docker exec -it mytomcat-net-01 ping mytomcat-net-02

# 6.测试打通网络,将位于docker0和mynet两个网络下的容器打通
# 具体来说,测试打通docker0网络下的mytomcat01容器和mynet网络
docker network connect mynet mytomcat01
# 查看mynet的配置信息,发现实际上将mytomcat01再映射出一个ip地址到mynet网络中(一个容器两个ip地址)
docker network inspect mynet
[
    {
        "Name": "mynet",
        "Id": "7dde80cf160c4526e37f0d5bd76d30c6c6fe80046d631eaa42852b846202f02c",
        "Created": "2020-07-11T09:55:01.962552613+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.167.0.0/16",
                    "Gateway": "192.167.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "67308eb3f177f9d14f718e0507eaaaf2088c76f229bfde7da15620af01f348f4": {
                "Name": "mytomcat-net-02",
                "EndpointID": "b636d43051f7abc791df8ae8213e6aac7a6d3769109291b0272ea1fba66c4611",
                "MacAddress": "02:42:c0:a7:00:03",
                "IPv4Address": "192.167.0.3/16",
                "IPv6Address": ""
            },
            "a1c5e7a59d25f130a422a6356cd2005ffab247cc8d92af99e2ccaad0de0b127a": {
                "Name": "mytomcat-net-01",
                "EndpointID": "87f65a4164398c9354d4d22c8d4c1a87c5739b632aa3647081b97cd0b974768f",
                "MacAddress": "02:42:c0:a7:00:02",
                "IPv4Address": "192.167.0.2/16",
                "IPv6Address": ""
            },
            "dfa3c4a48de5581f22c6b9fc47dfe906e4e40047b54cdeba533a22e03ad8c382": {
                "Name": "mytomcat01",
                "EndpointID": "8033a85b503549504ba8e8aa18a3b23c65cf843af6877606795af12073b20995",
                "MacAddress": "02:42:c0:a7:00:04",
                "IPv4Address": "192.167.0.4/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

# 7.测试不同网络下的容器可否ping通,发现成功互联
docker exec -it mytomcat01 ping mytomcat-net-01

# 8.删除网络
docker network rm mynet