docker|docker入门——简介

一、docker为什么会出现?解决了什么问题? 问题:我们在开发一个应用的时候,使用的电脑有特定开发环境,有特定的环境配置。而其他开发人员所处的环境配置也各有不同。我们开发的应用依赖于当前的环境和某些配置文件。如何能保证你开发的应用可以在别人的电脑上也顺利跑起来,而且不用重新搭建环境呢?也就是说,从开发环境移植到测试环境,再移植到运维的生产发布环境,都能顺利跑起来,不会出现版本、配置等问题。我们希望的是系统平滑移植。
答案就是使用容器container。而docker之所以发展迅速,也是因为它对此给出了一个标准化的解决方案——系统平滑移植、容器虚拟化技术。
docker可以从根本上解决“环境配置麻烦,换台机器就要重来一次的问题”:软件能否带环境安装?也就是说,安装的时候把原始环境一模一样地复制过来,开发人员利用docker可以消除协作编码时的环境配置问题。
具体操作:开发人员在自己的环境下跑通代码后,将源码+当前配置文件+环境+版本等等东西打包成一个镜像,交付给运维,然后让这个镜像跑在docker上。这样就达到了环境的匹配,做到了系统的平滑移植,实现了**“一次镜像,处处运行”**。
一句话来说:docker是解决了运行环境和配置问题的软件容器,是方便做持续集成并有助于整体发布的容器虚拟化技术。


二、容器和虚拟机比较 1. 虚拟机(传统虚拟机技术) 虚拟机是一种带环境安装的解决方案,它可以在一种操作系统中运行另一种操作系统(比如在Win10中运行Linux系统Ubuntu)。
传统虚拟机技术基于安装在操作系统上的虚拟机管理软件(如:VirtualBox和VMWare等),创建虚拟机(虚拟出各种硬件),在虚拟机上安装从操作系统,在从操作系统中安装部署各种应用。
虚拟机存在的问题:

  • 资源占用多
  • 冗余步骤多
  • 启动慢
2. docker(容器虚拟化技术) 由于上述虚拟机的缺点,Linux发展出另一种虚拟化技术:Linux容器(Linux Container,LXC)。
Linux容器不模拟一个完整的操作系统,而是对进程进行隔离。有了容器,就可以将软件运行所需的所有资源打包到一个隔离的容器中。容器不需要捆绑一整套操作系统,只需要软件工作所需的库资源和设置(最小的Linux所需环境),这使得系统变得高效、轻量,并能保证部署在任何环境的软件都能始终如一地运行。此外,背个容器之间相互隔离,每个容器都有自己的文件系统,容器之间进程不会相互影响,可以区分计算资源。(container本身也有“集装箱”的意思。集装箱之间互相隔离,可以长期反复使用,可以快速装载和卸载,而且规格标准,在任何地方(港口,船上。。)都能摆放。)
三、docker的三要素 镜像(Image) docker镜像是一个只读模板。可以用来创建docker容器。一个镜像可以创建多个容器。可以把image理解成“可执行程序”或容器的“源代码”。
docker镜像文件类似于Java的类模板,而docker容器实例类似于Java中new出来的实例对象。
容器(Container) docker利用容器独立运行一个/一组应用,应用程序或服务运行在容器里,容器类似于一个虚拟化的运行环境,容器是用镜像创建的运行实例。容器是镜像运行的实体。可以把容器理解成运行起来的进程。
容器=简易版的Linux环境(包括root用户权限、进程空间、用户空间和网络空间等)+运行在其中的应用程序
仓库(repository) 仓库就是集中存放镜像的地方。Docker公司提供的官方registry被称为Docker Hub。
仓库分为公开仓库(public)和私有仓库(private)两种形式。
四、docker的工作原理 docker|docker入门——简介
文章图片

Docker是一个Client-Server结构的系统,Docker Daemon(守护进程)运行在主机上,然后通过socket连接从客户端访问,守护进程从客户端接受命令并管理运行在主机上的容器。
docker|docker入门——简介
文章图片

具体来说,Docker是一个C/S模式的架构,后端是一个松耦合架构,众多模块各司其职。Docker运行的基本流程:
  1. 用户使用Docker Client(命令行窗口)与Docker Daemon建立通信,并发送请求给Daemon。
  2. Docker Daemon作为Docker架构中的主体部分,首先提供Docker Server的功能使其可以接受Docker Client的请求。
  3. Docker Engine执行Docker内部的一系列工作,每项工作都以一个job的形式存在。
  4. job运行过程中,当需要容器镜像时,则从Docker Registry中下载镜像,并通过镜像管理驱动Graph driver将下载镜像以Graph形式存储。
  5. 当需要为Docker创建网络环境时,通过网络管理驱动Network driver创建并配置Docker容器网络环境。
  6. 当需要限制Docker容器运行资源或执行用户指令等操作时,则通过Exec driver来完成。
  7. Libcontainer是一项独立的容器管理包,Network driver以及Exec driver都是通过Libcontainer来实现具体对容器的操作。
五、镜像分层 从拉取tomcat这个镜像的过程我们看出,镜像下载是一层一层的:
docker|docker入门——简介
文章图片

镜像的底层原理:UnionFS(联合文件系统):
是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层地叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。联合文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
联合文件系统就是一种分层、轻量且能够聚合的一种镜像基础。
Docker镜像加载原理:
docker镜像实际上是由一层一层的文件系统组成,这种层级的文件系统就叫UnionFS。
镜像分层最大的好处就是共享资源,方便复制迁移,就是为了复用。 基础镜像相当于一个基础模板,用户可以自定义添加所需的功能/命令,方便地制作出自己需要的镜像。
Docker镜像层都是只读的,容器层是可写的。 当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称为“容器层”,“容器层”之下的都叫“镜像层”。
举个例子:从docker hub上拉取的Ubuntu镜像没有vim命令,我们想要它带有vim命令,怎么办?
按下面的步骤生成我们自己的镜像:
  1. run这个镜像,生成容器
> docker run -it ubuntu bash

  1. 更新管理工具,然后安装vim
> apt-get update > apt-get install vim

apt-get命令报错可以试着重启一下docker,要是还不行请参考https://www.cnblogs.com/coffeebox/p/12672467.html
  1. 安装完成后,commit我们的新镜像
docker commit命令:提交容器副本使之成为一个新镜像
> docker commit -m="提交的描述信息" -a="作者" 容器ID 要创建的目标镜像名:[标签名] > docker commit -m="add vim cmd" -a="jcl" 1771da18f944 test/myubuntu:1.0

docker|docker入门——简介
文章图片

生成我们自己的镜像后,可以将它发布出去。
将它发布到dockerhub上:
  1. 登录docker账号
> docker login

如果报关于“credential”的错,则要修改config.json文件:
> vim ~/.docker/config.json > # 将credsStore改成credStore即可,保存退出,重新登录。

  1. 对docker镜像重新命名,使其符合规范:
> docker tag [image_id] [new_name:new_tag] > # [new_name:new_tag]的格式为:docker hub账号/镜像名字:版本

【docker|docker入门——简介】docker|docker入门——简介
文章图片

  1. 上传镜像:
> docker push [new_name:new_tag]

docker|docker入门——简介
文章图片

  1. 去docker hub官网验证一下:
docker|docker入门——简介
文章图片

镜像push成功了,仓库名就是我们之前取的。点开后还可以添加一些镜像说明和readme。

六、容器卷 卷就是目录或文件,存在于一个或多个容器中,由docker挂载到容器,但不属于UnionFS,因此能够绕过UnionFS提供一些用于持续存储和共享数据的特性:
卷的设计目的就是数据备份、数据的持久化,完全独立于容器的生存周期,因此docker不会在容器删除时删除其挂载的容器卷。
就是实现将docker内的数据保存进宿主机的磁盘中,以达到数据的持久化和敏感、重要数据的备份。
特点:
  1. 可以在容器之间共享或重用数据
  2. 卷中的更改可以实时生效
  3. 数据卷中的更改不会包含在镜像的更新中
  4. 数据卷的生命周期一直持续到没有容器使用它为止

1. 运行一个带有容器卷存储功能的容器实例:
> docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录 镜像名

建立容器卷之后,就相当于建立了一个容器和宿主机之间的映射(硬连接),容器里添加了什么文件,宿主机也会实时产生同样的文件。同样的,宿主机上添加了什么文件,容器内也会实时产生同样的文件。
查看数据卷是否挂载成功:
> docker inspect [容器ID] > # 看“Mounts”那项


2. 如果想限制容器内只能读,不能写:
> docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录:ro 镜像名


3. 卷的继承和共享 卷的继承:
> docker run-it --privileged=true --volumes-from 父容器名 --name=子容器名 镜像名

这样就实现了数据的共享和传递。
有空继续补充

    推荐阅读