Docker学习

参考文章:Docker-从入门到实践

服务器虚拟化解决的核心问题是资源调配,而容器解决的核心问题是应用开发、测试和部署。

一、Docker是什么

Docker是一种轻量级的操作系统虚拟化解决方案,它想达到一次构建到处运行,类似于Java虚拟机的效果,它最初诞生于2013年,是基于go语言的实现,最初是由dotCloud公司的内部一个业余项目,后来项目开源加入了Linux基金会,然后现在代码在github上进行维护。Docker的基础是基于Linux容器技术,在Linux容器技术的基础上,Docker进行了进一步的封装,让大家不去关心容器的管理,使得操作更加便捷。用户操作Docker容器,就像操作一个快速轻量级的虚拟机那样简单。


二、Docker和虚拟机的区别

参考文章 : Docker和虚拟机的区别

从结构上来看,容器和虚拟机还是有很大不同的。

左图的虚拟机的Guest层,还有Hypervisor层在Docker上已经被Docker Engine层所取代,在这里我们需要知道,Guest OS 是虚拟机安装的操作系统,是一个完整的系统内核,另外Hypervisor可以理解为硬件虚拟化平台,它在后Host OS以内核驱动的形式存在。

虚拟机实现资源的隔离的方式是利用独立的Guest OS,以及利用Hypervisor虚拟化CPU、内存、IO等设备来实现的,对于虚拟机实现资源和环境隔离的方案,Docker显然简单很多。

Docker 底层的核心技术包括 Linux 上的命名空间(Namespaces)、控制组(Control groups)、Union 文件系统(Union file systems)和容器格式(Container format)。简单来说,Docker就是利用Namespace 实现了系统环境的隔离,利用了cgroup实现了资源的限制,利用镜像实例实现跟环境的隔离。

Docker有着比虚拟机更少的抽象层。由于Docker不需要Hypervisor实现硬件资源的虚拟化,所以运行在Docker容器上的程序,直接使用的都是实际物理机的硬件资源。因此在cpu、内存、利用率上,Docker将会在效率上具有更大的优势。此外,Docker直接利用虚拟机机的系统内核,避免了虚拟机启动时所需要的系统引导时间和操作系统运行的资源消耗,利用Docker能够在几秒钟之内启动大量的容器,是虚拟机无法办到的。快速启动低资源消耗的优点,使Docker在弹性云平台自动运维系统方面具有很好的应用场景。

与虚拟机相比,Docker在以下几个方面具有很大的优势,它能够快速的交付和部署,Docker在整个开发周期都可以完美辅助你实现快速交付,Docker允许开发者本地应用,直接进入到可持续的开发流程中。例如开发者可以使用一个标准镜像构建一套开发容器,开发完成之后,运维人员可以直接使用这个容器来部署代码,Docker可以快速创建容器快速迭代应用程序,整个过程全程可见,使团队中的其他成员更容易理解应用程序是如何创建和工作的。

此外,容器的启动时间是秒级的,大量节约开发、测试、部署的时间。还有一个非常关键的点,就是Docker能够高效地部署和扩容,Docker容器几乎可以在任意平台上运行,包括虚拟机、物理机、公有云、私有云、个人电脑、服务器等,这种兼容性,可以让用户把一个应用程序从一个平台直接迁移到另外一个平台。Docker的兼容性和轻量性的特性可以轻松的实现负载的动态管理,你可以快速扩容或方便的下线你的应用和服务,这种速度趋近于实时!此外Docker还具有更高的资源利用率,一台主机上可以运行数千个Docker容器,容器除了运行其应用之外,基本不消耗额外的系统资源,使得应用性能高,系统开销小。

而传统的虚拟机方式则需要运行不同的应用,耗费大量的资源,此外Docker还可以有更简单的管理使用Docker只需要小小的修改就可以替代以往大量的更新工作,所有的修改都以增量的方式被分发和更新,从而实现自动化并且高效的管理。


三、通过Docker启动Mysql

Docker的命令组成为Docker + 动作 + 命令 + 镜像

  1. 搜索镜像
    docker search mysql

    ps:这里有个坑,解决了但不知道原因
    在登陆状态下search镜像会报错
    在这里插入图片描述
    但是logout之后就可以正常search和pull了…

  2. 拉取镜像
    docker pull mysql

  3. 启动镜像
    docker run -dit --name mysql -e MYSQL_ROOT_PASSWORD=root mysql

    这里各个-命令的意思:
    -d: 在后台运行容器,并且打印容器id。
    -i: 即使没有连接,也要保持标准输入保持打开状态,一般与 -t 连用。
    -t: 分配一个伪tty,一般与 -i 连用。
    --name: 给容器赋予一个name,后续命令除了使用容器id还可以使用name指定容器
    -e MYSQL_ROOT_PASSWORD=root : 初始化root用户的密码
    -p 3306:3306: 表示这个容器中使用3306(第二个)映射到本机的端口号也为3306(第一个)

  4. 进入Mysql
    先进入容器: docker exec -it mysql bash
    登陆Mysql:mysql -u root -p 输入密码
    成功:
    在这里插入图片描述


四、容器间互相访问

  1. 通过 --link 连接容器

    1
    2
    3
    4
    5
    # 例如使用xxl-job连接容器中的mysql5.7
    docker run ... --link mysql_5.7:mysql ...
    # --link mysql容器名:mysql容器在xxl-job容器中的映射名
    -> 注意:建立映射名后配置文件中的地址应直接改为映射名,比如下方的mysql连接 <-
    -e PARAMS="--spring.datasource.url=jdbc:mysql://mysql:3306/xxl_job"
  2. 通过 --network 创建一个Bridge网络,在run容器时指定该网络即可

    1
    2
    3
    4
    5
    6
    7
    docker network create mynet  # 创建网络
    docker run -dit --name redis --network mynet -p 10087:6379 redis # 创建redis容器
    # 创建mysql容器
    docker run -dit --name mysql --network mynet -p 3307:3306 -e MYSQL_ROOT_PASSWORD=root mysql

    # 进入redis容器看看能不能ping通mysql
    docker exec -it redis bash

    此时执行ping命令,出现 bash: ping: command not found
    在这里插入图片描述
    百度后通过 apt-get update + apt-get install iputils-ping 解决问题,解决问题后再ping就可以ping通了
    在这里插入图片描述

  3. 通过虚拟IP访问
    安装docker时,docker会默认创建一个内部的桥接网络docker0,每创建一个容器分配一个虚拟网卡,容器之间可以根据ip互相访问。

    使用 ifconfig 命令出现 bash: ifconfig: command not found
    在这里插入图片描述
    解决:apt install net-tools,解决后使用 ifconfig 看到如下:
    在这里插入图片描述
    redis 容器中我们得到的 ip地址是 172.18.0.2,然后进入mysql容器去ping一下redis

    在没使用虚拟IP之前先ping一次,可以看到无法ping通
    在这里插入图片描述
    再ping一下虚拟IP:
    在这里插入图片描述
    没ping通??使用2中同一个Bridge网络的mysql来ping这个redis可以ping通:
    在这里插入图片描述
    排查:
    运行 docker network inspect bridge ,可以看到处于docker0网络的只有mysql_5.7这一个容器!才想起来我使用的是已经指定了network的redis,所以可能并没有被分配到默认的docker0中。
    在这里插入图片描述
    运行 docker network connect bridge redis 后,再查看docker0中的容器:
    在这里插入图片描述
    再进入mysql中ping一下redis,发现还是ping不通!

    进入redis中查看 ifconfig
    在这里插入图片描述
    发现出现了两个虚拟IP地址,反应过来应该是每一个网络都会给容器分配一个不同的虚拟ip地址,原来我一直ping的都是2中mynet给redis分配的地址,人麻了…

    在redis里再ping这个mysql,终于通了!
    在这里插入图片描述