虚拟化系统:
  1. Type-I: 此种虚拟化是Hypervisor直接运行在硬件之上,来创建虚拟机.
  2. Type-II: 这种虚拟化类似与VMware Workstations。

  

  IPC: 在相同的名称空间中的进程才能通过IPC实现进程间通信。
  PID: 在每个名称空间中必须有一个进程ID为1的进程,它是所有进程的父进程,即init进程,所以要实现用户空间隔离,就需要让每个用户空间中进程,以为自己是运行在init进程下的.
  user: 要让每个用户空间中的进程以为自己是运行在独立的主机中,那就必须实现每个用户空间中都一个UID为0的用户, 但该用户在真实系统中,却是一个普通用户。

容器虚拟化:
 资源限制:
  通常有两种,一种是弹性百分比限制能使用全部资源的百分比.另一种是决对资源限制.

 实现资源限制的是Cgroups(Control Groups):
  1. blkio: 块设备IO
  2. cpu: CPU
  3. cpuacct: CPU资源使用报告
  4. cpuset: 多处理器平台上的CPU集合
  5. devices: 设备访问
  6. freezer: 挂起 或 恢复任务
  7. memory: 内存用量及报告
  8. perf_event: 对cgroup中的任务进行统一性能测试
  9. net_cls: cgroup中的任务创建的数据报文的类别标识符.

Docker、LXC、CNCF:
  Docker是一家商业公司开发的容器技术,早期是容器内核是基于LXC(LinuX Container),来实现容器的创建和管理的。
  LXC: 早期有一种技术叫 jail(监狱,或叫沙盒),这种技术可让一个应用程序运行在一个沙箱中,该应用程序无论做出任何对系统的破坏都不会影响到真实的系统,仅仅只是沙箱中的虚拟环境。后来这种技术在Linux也引入了,叫vserver,即现在我们比较熟悉的chroot功能。但是在Linux系统中早期内核支持名称空间,是需要通过自己编写代码,调用系统调用来创建出UTS,Network,IPC,等不同的名称空间,结合chroot实现在一个操作系统上创建出一个用户空间,但这对普通用户来说,是很困难的,而LXC则提供了一组工具,将这些功能整合成工具,用户若需要创建容器,只需要使用lxc-create等命令行工具,就可以很轻松的创建容器,但是LXC在创建容器时,它需要借助于template(模板),当允许lxc-create来创建一个容器时,你可以在CentOS的系统上,创建一个Ubuntu的容器,或FreeBSD的容器等,都可以只有你提供相应的template和这些系统的软件包安装源即可; 但LXC这种方式带来的问题是使用上依然非常困难,应用模板的创建并不容易,而且又产生了很多冗余数据;如:我想创建两个Ubuntu的容器,我就需要安装两份相同的数据; 而且若我需要将一个容器
迁移到另一台主机上,怎么做?LXC没有提供相应的工具。所以它并不适合大规模使用。Docker:它早期创建容器的内核是LXC,但它使用了比LXC更高效,更精巧的方式来创建容器,它不在使用模板来安装容器,而是将容器制作成镜像,当需要使用容器时,直接从镜像仓库中下载之前制作好的镜像到本地,直接启动容器即可。并且它的镜像采用一种叫做叠加镜像的方式解决数据冗余的问题,实际上它采用一种叫三层叠加镜像的方式来实现数据的高效利用 和 容器私有数据的保存。借助于共享存储来将容器的私有数据保存在宿主机的外部,当宿主机宕机时,只要在新的宿主机上下载镜像,启动容器,挂载数据即可恢复服务。具体如下图:
  注:
   Docker为了管理容器方便,它定义一个容器中只能运行一个进程, 但实际上容器跟虚拟机类似,它是可运行多个进程的,只是为了管理方便,限制容器中只能运行一个进程。

    

容器这种技术带来好处:
  对于开发人员来说,是天大的好处,因为Docker的出现真正解决代码一次编写到处运行,无论底层是什么系统,只要能运行docker,将镜像做好后,直接编排好,然后在宿主机上启动容器即可。对于运维人员来说,带来的问题是,系统构架更加复杂,原本的调试进程的方式,在容器时代变的异常困难,因为容器中很可能没有各种调试工具等。

容器部署上的问题:
  如NMP环境的构建上, 通常我们需要先部署MySQL容器,接着是PHP容器,最后是Nginx容器,这样的顺序部署才能让环境都正常工作,否则可能出现Nginx代理PHP服务器,结果找不到PHP服务器,因为容器启动后,它的IP地址会改变,那通过DHCP根据MAC不是可以固定分配IP吗?但其实是不可以的,因为容器是没有固定MAC的,它的网卡是虚拟的,是通过Linux上的"虚拟网线”创建的两个虚拟网卡,一端接入容器,一端接入Docker0(默认桥)桥上,这样就实现了容器能接入网络中,因此每次启动容器时,是无法知道这一次创建的虚拟网卡的MAC地址是多少的,因此必须使用其它方法来获取启动完成后的容器的IP地址,这也就是为啥容器需要编排,对于LNMP环境,Nginx要依赖PHP,因为它要代理PHP,而PHP又依赖MySQL,因为PHP应用程序要从MySQL中获取数据,因此必须先启动MySQL容器,这样才能获取MySQL容器当前使用的IP,接着启动PHP容器,将MySQL容器的IP传入到PHP容器中,这样PHP容器就可以知道MySQL的IP,而Nginx也是一样,这样编排后,LNMP环境中每个容器就都能获取它所依赖的容器的IP,就可以正常通信了。

为了解决部署容器的顺序问题,容器技术,必须结合编排工具一起使用,才能实现大规模应用。
目前比较知名的编排工具:
  Docker: machine+swarm+compose,这三个工具配合使用来实现编排。
  第三方提供的编排工具: mesos+marathon
  Google: kubernetes-->简称k8s

libcontainer:
  又称为RunC,它是Docker官方提供的新Docker构建容器的核心程序,由于LXC在功能上,没有与时俱进,因此Docker官方,最终决定自己开发一个新的容器构建核心,它就是runC。

Docker,Moby,CNCF的历史故事:
  Docker我们知道它是一家商业公司,早期Docker刚出现时,以下轰动世界,为了让Docker技术,能够有更大的发展,Docker将自己的产品分成商业版和社区开源版,但是Docker的商业版在商业领域上始终没能活动 大佬们的信赖,没能得到太多融资,但是社区开源版确始终火热的不行,Docker为了能获得更多商业利益,它最终决定将社区版的Docker更名为Moby,希望能吸引更多关注的目光到它的商业版上,但事与愿违。 而此时Google发现自己秘密使用了十几年的容器技术竟然被Docker给开源了,而且还发展的如此红火,尽人皆知,但Google不希望自己在容器技术上的话语权落到Docker手中,它决定扶持一家小容器公司,但这家公司的产品在Google大力扶植下,依然是名落孙山,不是Docker的对手,最后,Google发现Docker在编排工具的开发上,好无建树,而自己拥有十几年的容器使用经验(Google内部的容器叫Borg(博格)),因此就组织了工程师开发了Kubernetes,又鉴于Docker一家公司为了商业目的,随意更改Docker社区版,改变Docker的性质,因此Google将Kubernetes捐给了CNCF,而CNCF是容器标准化基金会组织,它是Google联合多家
知名公司,如:IBM,微软,Facebook等联合成立的组织。向世人表态为不会左右Kubernetes的发展进程,加上Kubernetes从其诞生就是站在Bong的肩膀上成立的,所以它一经发布就成为世人聚焦的目标,短短3年,就已经从0.1发展到1.1版本,以每年4个版本迭代,2018年为止,其市场占有率达到80%以上.

OCI(Open Container Initiative):
  它由Linux基金会主导于2015年6月创立,皆在围绕容器格式和运行时制定了一个开放的工业标准.
  它制定了两个规范标准:
    1. 运行时标准(The Runtime Specifications (runtime-spec))
    2. 镜像格式标准(The Image Specification (image-spec))

OCF(Open Container Format):
  OCF开放容器格式就是OCI的倡导下产生的标准。

Docker的基本架构:

  

注:
 Docker的镜像:
   Registry:在Docker中称为镜像仓库,Docker的镜像仓库有点类似与yum源仓库,但它的组织方式是这样的:
    官方提供的Docker镜像仓库地址: hup.docker.org,当然国内也有很多docker镜像站.
    Docker镜像仓库的组织格式为:
      应用程序名:版本号
      其中: 应用程序名为仓库名.
      版本号: 为仓库中镜像名.也是它的tag标签号.
    以Nginx为例:
      Nginx:为仓库名.
      nginx:1.15 这就是一个镜像名.同时一个镜像可能有多个名字,
        比如: 1.15是Nginx的最新发行版,则还会给它提供一个名字叫: nginx:lasted 即最新版,
        这个名字会随着Nginx发布的最新版而改变。
      nginx:1.14 另外我们知道,Nginx的发行版中,次号码为偶数表示,此版本为稳定版,
        为奇数则为开发版,所以这种版本通常也会有一个名字: nginx:stated 即稳定版的nginx镜像.

  docker的下载站有很多:
    若使用清华大学的repo仓库,下载其repo文件后,还需要修改其repo镜像的站点为清华大学的镜像站.
      yum install docker-ce

    安装完docker后,要下载其docker镜像,可使用国内的镜像加速器来下载:使用方式:
    mkdir /etc/docker
    vim /etc/docker/daemon.json
      {  "registry-mirrors": ["https://registry.docker-cn.com"]  }

  查看docker版本信息:
    docker version
    docker info

  docker的常用操作:
    docker search :搜索docker镜像仓库中指定的镜像名.
    docker pull : 下载指定镜像到本地.
    docker images : 列出本地已有的镜像

  下载docker镜像:
    docker image pull nginx:1.14-alpine
    注: alpine:这是一个小发行版的nginx,大小很小. 它仅集成了nginx运行所必须的环境,其它什么都没有,若你需要一些调试工具,它就不太适合了。
      另外,一般官方发行的镜像,一般都很少会带调试工具。
      另注: 我们搜索docker镜像时,会看到类似 tom/nginx 这类的镜像,它们是表示 tom这个人,在docker官方注册了账号,上传了自己制作的nginx镜像.

    docker pull busybox

    docker imgle ls --help    #查看ls子命令的帮助.
    docker imgle --help

  创建容器:
    docker container create    #仅创建容器,但不运行.
    docker container run     #创建容器,并运行。
    docker container start          #启动一个或多个已经创建好的容器。
    docker container stop |kill    #都可以停在一个或多个容器.
    docker container top      #查看那些容器最消耗资源.

  docker container run [options] Image [Command] [参数...]
   options:
    -t :启动镜像时,给其添加一个终端访问接口,以便能够启动后,连接登录.
    -i :启动为交互模式.
    --rm :停止后,直接删除该容器.
    -d : 运行到后台.
    --name <ImangeName> :为启动的容器名一个名字.
    --network <NetName> :将容器加入一个指定的网络中.

  docker network ls    #可列出当前本机有多少网络可用.
  ifconfig    可查看到,当docker安装完成后,它会自动创建一个docker0的桥,这个桥是NAT桥.
       它是直接桥接在物理网卡上的,可直接和物理网络通信。

  示例:
   docker pull busybox    #下载一个busybox的镜像.
   docker container run -it --name b1 busybox:latest    #这样就启动了一个叫b1的容器.
    / #ps      #这样就启动了busybox,当前显示的是它的sh终端.
    / #mkdir /data/httpd
    / #vim /data/httpd/index.html
    / #httpd -f -h /data/httpd      #在busybox中启动一个httpd进程,并指明其web根目录.
    / #exit              #执行exit就退出了sh终端,也就终止了容器.

  终端2:
    docker ps
    docker inspect b1    #可查看b1这个容器的详细信息.
    curl http://1.1.1.1/    #这样就可以访问容器中的httpd服务了。

    docker ps -a    #可查看停止的容器.

  示例2:
    终端1:
      docker start -a -i b1 #重新启动停止的容器b1

    终端2:
      docker ps
      docker kill b1    #可强制关闭b1容器. 正常情况下应该使用stop,可保障数据不丢失.
      docker rm b1    #删除停止的容器b1

  示例3:
    docker run --name nginx1 -d nginx:1.14-alpine #若本机能访问互联网,这里可直接运行,docker会自动下载镜像.
    注:
        在容器中运行应用程序,它必须工作在前台,否则容器已启动就会关闭,因为在容器中只有一个进程,该进程是支撑容器的骨架
    docker ps

    docker run --name redis1 -d redis:4-alpine    #启动一个redis容器,它将自动下载该镜像.并启动.

  示例4:
    docker exec -it redis1 /bin/sh    #在指定容器redis1上运行一个命令,/bin/sh,并使用交互式登录.
    /data # ps             #这样就可以登录到redis1这个容器上了.

    docker logs nginx1    #查看容器nginx1的日志信息.

docker 所有状态转化示意

  

  Docker的镜像:

  

    Docker镜像包含了启动容器所需的文件系统及其内容,因此它用于创建并启动docker容器.
  docker镜像采用分层构建的机制,最底层为bootfs,其上为rootfs.
  bootfs: 用于系统引导文件系统,包括bootloader和kernel,容器启动完成后,bootfs会被卸载,以节省内存空间.
  rootfs: 它在运行中的docker容器中变现为根文件系统.
  如: docker exec -it nginx1 /bin/sh   #登录后, ls / 可以看到全部的根文件系统目录.
  传统OS:
    系统启动时,内核挂载rootfs时,为确保不会误删除文件,通常会先以只读模式挂载,完整性自检完成后,再重新以读写模式挂载rootfs.
    docker: 它在启动内核,挂载rootfs时,始终是以只读模式挂载, 而后在通过联合挂载技术额外挂载一个可写层.实现读写操作。

Docker Image Layer

  

  

此镜像显示了Docker的镜像层级,从上到下分别为:
  可写层
  add Apache 和 add emacs(类似于vim的编辑器): 这两层为自己通过yum安装在镜像中的工具.
  Debian: 这是为安装的工具提供的基本的最小安装的根文件系统已共Apache能运行起来.这里使用的是Debian.还可以使用CentOS等.
  bootfs: 这一层则是启动Debian这个rootfs所需的bootloader和kernel,通常在将Debian启动起来后,它将自动被卸载.

Docker实现叠加挂载镜像的文件系统:
  overlayfs: 从kernel3.18以后被整合到Linux内核中了. 它叫 叠加文件系统, 再早期Docker实现叠加挂载是使用Aufs(Advanced multi-layered unification filesystem:高级多层统一文件系统), 而此文件系统是2006年开发,但因代码质量问题,一直未被整合到kernel中; 据说它的代码有3万行,而ext4这种文件系统总代码量4千多行。所以早期要使用docker有两种方式 一种手动给内核打aufs的补丁,另一种就是使用Ubuntu系统,因为它比较早的将Aufs整合到它的kernel中了。不过现在目前 CentOS系统已经能支持overlayfs的第2版了,所以可以直接使用docker即可.
  docker info
     #输出中Storage Driver: overlay2 ,overlay2是一种虚拟抽象层的文件系统,它是建构在Backing Filesystem: xfs ,即后端文件系统xfs之上的文件系统。

  docker pull quay.io/coreos/flannel:v0.10.0-amd64
     #下载quay.io 这个网站的coreos名称空间下的flannel仓库中的tag为v0.10.0-amd64 的镜像。默认docker使用https去下载. quay.io是docker镜像很有名的第三方提供者.

 示例1:
  #基于busybox创建一个测试镜像:
    docker run --name bx1 -it busybox
    / #mkdir -p /data/html
    / #vi /data/html/index.html
      <h1>Hello busybox HTTP Server</h1>

  终端2:
    docker commit -p bx1    #-p是让bx1容器先暂停,避免有人访问镜像,导致镜像创建不完成.
    docker image ls       #可看到刚创建的镜像.
    docker tag <IMAGE ID> tom/bbox:v0.1        #这样就给指定的镜像打上了tom/bbox的标签,并且tag为v0.1s
    docker tag tom/bbox:v0.1 tom/bbox:latest    #在tom/bbox:v0.1上再给其创建一个标签名.
    docker image rm tom/bbox:latest    #删除一个标签名, 它只是删除标签,就像删除硬链接,文件是不会被删除的。

 示例2:
  docker inspect nginx:v1.14    #查看其CMD,可以看到的其被docker启动后,容器中将启动的第一个进程为nginx
  docker inspect tom/bbox:latest

 示例3:
  #基于busybox制作一个启动后运行busybox中的httpd的镜像.

  终端1:
    docker run --name bx1 -it tom/bbox:latest    #注:这是基于示例1中的内容创建的.

  终端2:
    docker commit -a "tom <tom@test.com>" -c ‘CMD ["/bin/httpd","-f","-h","/data/html"]’ -p bx1 tom/bbox:v0.2
    注:
      CMD: 这是仅修改启动容器后,执行什么命令, 注意CMD必须大写!! 其次参数的顺序不能乱.
      -p : 制作时让容器处于暂停状态.
            制作完成后,直接给它加一个标签名为tom/bbox:v0.2
    docker image ls  #查看制作好的镜像
    

    docker  run  --name bx2  -d  tom/bbox:v02
  终端3:
    docker inspect bx2  #查看bx2的定义,主要看CMD定义
    curl http://1.1.1.3/    #这样就可以直接访问busybox启动的微型httpd了。

  示例4:
  #上传镜像到docker hup中的仓库中.
    1. 要创建docker hup的登录账户,并登录到后台,创建一个仓库.
       如: 上面创建的镜像名为: tom/bbox:v0.1
        那创建的仓库就叫 tom/bbox
    2. 上传镜像前,要先登录
      docker login -u tom #然后要求输入密码,Login Succeeded表示登录成功.
    3. 开始上传镜像:
      docker push tom/bbox #不加tag则表示将本地所有镜像都推送上去。

  示例5:
    #导出已有镜像,并在其它主机上导入镜像:
    docker image ls
    docker save -o myimages.gz tom/bbox:v0.1 tom/bbox:v0.2    #这样即可将两个镜像打包成myimages.gz。

    #登录到另一台docker上就可以执行:
    docker load -i myimages.gz #就可以导入镜像了
    docker image ls

  示例6:
    docker exec -it --name bx1
    / #wget -O - -q http://1.1.1.2/   # 假如Nginx容器启动后的地址为1.1.1.2,则通过wget测试访问.
           -O :加载完成页面后,不保存,直接输出当标准输出."-"

Docker的四种网络模型:
  第一种是Closed Container(封闭式容器): 它主要是用来处理一些Docker计算任务的,完成后就自动退出了,因此它无需网络协议栈.
  第二种是Bridge Container(桥接式容器): 它是通过创建一根虚拟网线,一头接入容器中,也就是Container Virtual interface,另一头接在Docker bridge Virtual Interface上.
  第三种是Joined Container(联合容器): 它是让A和B两个容器都共享一组Net,UTS,IPC名称空间,这样的好处是A和B可以直接通过lo接口通信,并且还可以桥接到Docker桥上,共享网络接口。
  第四种是Open Container(开放容器): 它是第三种的扩展,它直接与物理机共享了Net,UTS,IPC名称空间,因此物理机上的网络接口它都可以看到,并且可以直接管理。

    

  示例1:
    #inspect 查看docker组件的详细信息.
    docker network ls
    docker network inspect bridge #查看bridge网络的详细信息。

  示例2:
    #创建网络模型3
    终端1:
      docker run --name bx1 -it --rm busybox
      / # wget -O - -q http://127.0.0.0.1/

    终端2:
      docker run --name bx2 -it --network container:bx1 --rm busybox
      / #echo "hello world." > /tmp/index.html
      / #httpd -f -h /tmp

  示例2:
    vim /etc/docker/daemon.json     #以下仅供参考,新版本有些参数以不支持!!
    {
      "bip": "1.1.1.1/24", #设置docker0的IP
      “fixed-cidr”:"10.20.0.0/16",
      "fixed-cidr-v6":"2001:db8::/64",
      "mtu":"1500",
      "default-gateway":"10.20.1.1",
      "default-gateway-v6":"2001:db8:dbcd::89",
      "dns":["10.20.1.2","8.8.8.8"],
      "hosts":["tcp://0.0.0.0:2375","unix:///var/run/docker.sock"] #启动docker监听在2375端口上.
    }

    systemctl restart docker      #新版本建议直接修改启动脚本,已参数形式传入

  在主机2:
    docker -H 1.1.1.1:2375 image ls #这样就可以查看1.1.1.1这台主机上docker的是否有镜像了。

  示例3:
    #创建docker网络
    docker network create -d bridge --subnet "1.1.1.0/16" --gateway "1.1.1.1" mybr0
    docker run -it --name bx1 --net mybr0 busybox:v0.1

  示例4:
    #启动容器时传递参数:
    docker run --name t1 -it --network bridge -h t1.test.com --rm busybox:latest

    docker run --name t1 -it --network bridge -h t1.test.com --dns 114.114.114.114 --rm busybox:latest
    docker run --name t1 -it --network bridge -h t1.test.com --dns 114.114.114.114 --add-host www.test.com:1.1.1.1 --rm busybox:latest

  示例5:
    docker run --name myweb --rm -p 80 tom/bbox:v0.2 #创建一个地址映射,允许外部访问此容器.
      #注: -p 80 ,实际是创建了一条 iptables DNAT规则.
    docker port myweb #查看docker创建的端口映射

    docker run --name myweb --rm -p 1.1.1.1::80 tom/bbox:v0.2
    docker run --name myweb --rm -p 80:80 tom/bbox:v0.2
    docker run --name myweb --rm -p 1.1.1.1:80:80 tom/bbox:v0.2

Docker的数据卷(Data Volume):
  为避免关闭再重启容器,其数据不受影响,但删除Docker容器,则其更改将会全部丢失.
  存在的问题:
    1. 存储于联合文件系统中的数据,宿主机不易访问.
    2. 容器间数据共享不方便.
    3. 删除容器其数据会丢失.
  解决方案:"卷(Volume)":
    卷是容器上的一个或多个目录(即:多个卷),此类目录可绕过联合文件系统,与宿主机上的某目录绑定(即关联)

Docker有两种类型的卷:
  1. Bind mount volume(绑定挂载卷):这是有用户自定义指定docker中的某目录挂载到宿主机的某个指定目录.
  2. Docker-managed volume(docker管理的卷): 这是由docker自己维护,用户需要在/etc/docker/daemon.json中指定启用docker自动启动容器时,关联宿主机上由docker默认自动创建一个目录,并与容器中指定目录关联的方式。

  示例:
    #由docker管理的卷:
    docker run --rm --name b2 -it -v /data busybox:latest

    终端2:
    docker inspect b2   #可查看其“Mounts”段,其中有说明容器中/data 目录与宿主机上的那个目录建立的关联.
              接着可测试在宿主机上目录中创建文件,在容器中编辑,是否可行。

  示例2:
    docker run --name b2 --rm -it -v /data/volumes/b2:/data busybox:latest

    终端2:
    echo “Hello Container busybox.” >> /data/volumes/b2/index.html
      #接着在容器中查看.
      # 再尝试删除容器,再关联相同目录,查看数据是否依然可访问。

    docker inspect -f {{.Mounts}} b2    #简单过滤.
     #注:
      JSON中使用"[]": 表示这是一个列表, {}: 表示这是一个关联数组(也叫Hash映射),它可嵌套.
      在关联数组中的格式:
      {
        "Key":"Value",    #每个键 值对要使用 逗号分隔.
        "Key":"Value",
        "key0": {
          "key1":"Value1",    #key1的上层是“key0”, 而key0上层是 根(通常用"."表示.)
          ..
        },
      ..
      }

  docker inspect -f  {{.Mounts}}  b2
     #最外层{} 为引用格式, 内层{.Mounts} 为引用数组中.Mounts
      . :表示根,.Mounts:表示根下的Mounts.
  docker inspect -f {{.NetworkSettings.IPAddress}} b2 #这是简单的Go模板,go模板还支持循环,判断等.

  示例3:
   #创建一个基础容器,让其它容器共享它的UTS,IPC,Network名称空间 已经它的卷映射.
  终端1:
    docker run --name infraCon -it -v /data/volumes/b2:/data/web/html busybox
    / #ifconfig

  终端2:
    docker run --name nginx --network container:infraCon --volumes-from infraCon -it busybox
    / #ifconfig

  终端3:
    docker inspect infraCon
    docker inspect nginx    #查看“Mounts” 和 Networks是否与上面的一样。

Dockerfile:
 格式:
  # : #号开头为注释.
  FROM : 第一个指令必须是FROM,它用来指明,依据那个基础镜像做镜像。
      一般指令建议使用大写以区分参数, 但指令不区分大小写.
     格式:
      FROM <仓库名>[:<tag>] 或 FROM <仓库名>@<Hash摘要值>

  使用dockerfile制作镜像的注意事项:
   1. 必须把镜像文件都放到一个指定目录中, docker build在打包时,只打包该目录中的文件.超出此目录的文件将不会被打包到镜像中.
   2. .dockeringore : 这个隐藏文件在指定目录的中,用于设定打包时排除的文件列表,可使用通配符。
   3. docker build 在进行镜像打包时,它实际上类似于通过启动一个容器,然后,在容器中运行一些命令,创建一些文件,这些数据都保存在可写层中, 再将可写层打包到镜像中一样,不过,docker build是隐藏式启动基础镜像来自动完成这些操作,所以,需要知道你要使用某些命令,这些命令必须在基础镜像中存在才能使用。
   4. 变量替换:
    变量格式: $VarName 或 ${VarName}
    变量替换: ${VarName:-String}    #若VarName为空或未定义,则使用String做为值. 否则使用VarName的值.
          ${VarName:+String}   #若VarName有值,则使用String替换该值.
      5. dockerfile中的指令:
    1. copy <Src> <Dest> 或 COPY ["<Src>",..."<Dest>"]    #注:Src若为目录,复制时,是仅复制目录中文件,而不复制目录本身的.

  示例:
    mkdir /dockerfile/
    cd /dockerfile
    vim Dockerfile    #注: 文件名首字母必须大写.
      #注: Dockerfile中的每条指令都是一层,层数越多挂载效率越差!!
      #Description: test image
      FROM busybox:latest
      MAINTAINER "Tom <tom@test.com>"
      # LABEL maintainer="Tom <tom@test.com>"   #功能和上面一样.
      COPY index.html /data/web/html/        #需要将index.html放到/dockerfile中
      COPY yum.repos.d /etc/yum.repos.d/      #注: 先将yum.repos.d 复制党/dcokerfile中, 然后在写此命令.
            
      ADD http://nginx.org/download/nginx-1.15.2.tar.gz /usr/local/src/    #它会自动在打包时下载该URL指定的文件.
      ADD nginx-1.15.2.tar.gz /usr/local/src      #打包时,会自动将tar.gz展开放入/usr/local/src/的文件.

      WORKDIR /usr/local/src    #将它做为工作目录.
      ADD test.tar.gz ./       #这里引用的相对路径就是WORRDIR所设定的目录.

      WORKDIR /etc/yum.repos.d/
      ADD yum.repos.d.tar.gz ./      #这里的相对路径就是/etc/yum.repos.d/了。

      #VOLUME ["/dir_1", "/dir_2" ..]    #设置容器挂载主机目录
      VOLUME /data/mysql/        #指定Docker自动管理的卷。

      #EXPOSE <Port>/<Protocol>
      EXPOSE 80/tcp     
        #指定要对外暴露TCP的80端口,但这里指定暴露,实际并不会直接暴露,而是需要在启动容器时,使用 “-P” 才会真正暴露此端口给外部用户.
           # docker port 容器名 #在不加"-P"时,可使用它来验证是否暴露了80端口.
      #ENV <KeyName> <Value>        #此格式定义的变量,会将空格后面的所有字符串都当做keyname的值.
      #ENV <Key>=<Value> <Key2>=<V2> ...    #此格式可创建多个环节变量. 若值中有空格,需要用"\"转义, 或用引号引起来.
      ENV DOC_ROOT /data/web/html
      COPY *.html $DOC_ROOT
      COPY *.jsp ${JSP_ROOT:-/data/web/jsp/}  #注:这些环境变量,是可以在启动容器时,指定"-e JSP_ROOT=/data/jsp" 来修改的.

      #RUN <Command1> && <Command2> ...      #RUN执行命令是在docker build时执行命令.
      WORKDIR /usr/local/src
      ADD http://test.org/test.tar.gz ./
      RUN cd ./ && \
      tar xf test.tar.gz     #仅做多行写命令的测试

     #RUN ["<Executable>","<Param1>",....]
     #RUN的第二种语法格式.它使用JSON数组,Executable为要运行的命令,后面为命令的参数,可有多个.此格式启动的命令不会以/bin/sh -c 的方式启动,因此它不能使用sh的命令语法,如:变量替换,通配符等. 若想使用shell特性的话,可用以下方式:
    RUN ["/bin/sh","-c","<Executable>","Param1",...]
    注:
      RUN 和 CMD 及 ENTRYPOINT 若使用中括号来表示数组时,其中不能使用单引号.必须使用双引号.

    docker build --tag tinyhttpd:v0.1 ./

  测试:
    docker run --name tinyweb1 --rm tinyhttpd:v0.1 cat /data/web/html/index.html
    docker run --name tinyweb1 --rm tinyhttpd:v0.1 ls /etc/yum.repos.d/

  #启动镜像时,传递参数:
    Dockerfile:
    FROM java:8
    ADD microsoft.jar /root
    ENV PARAMS=""
    ENTRYPOINT ["sh","-c","java $PARAMS -jar /root/microsoft.jar"]

    测试:
      docker run -d -e PARAMS="-Dserver.port=8080" -p 2000:8080 镜像名称

Docker私有仓库的构建:
  1. 安装docker的仓库构建程序包.
    yum install docker-distribution
  2. vim /etc/docker-distribution/registry/config.yml
    services: registry #表示运行的服务为registry
    layerinfo: inmemory #表示缓存在内存中.
    addr: :5000 #没有指定地址,表示使用0.0.0.0:5000

  3.启动服务:
    systemctl start docker-distribution

  4. 给自己做的镜像打上自己的仓库地址的标签.
    docker tag myweb:v0.3.11 node2.test.com:5000/myweb:v0.3.11

  5. 将自己打好标签的镜像push上去.
    docker push node2.test.com:5000/myweb:v0.3.11    #这里会报错,说我们使用了不安全的http.

  6. 若我们是内网使用, 不想使用HTTPS,可修改配置文件为:
    vim /etc/docker/daemon.conf
      {
      ...
      "insecure-registries": ["node2.test.com:5000"]
      }

    systemctl restart docker

  7. 再次push

  8. 可到其它节点上测试下载.
    docker pull node2.test.com:5000/myweb:v0.3.11

Docker的资源限制:
  Linux Capabilities: Linux Kernel相关的知识

  Memory:
  OOM: 对于比较重要的容器,在启动时就要调整其OOM_adj, 其值调整越小, OOM_score的评分就越低,当内核发现内存不足,发生OOM时,就优先将OOM_score得分高的优先kill掉.
  默认: docker daemon会自动将自己的OOM_adj调整很低,避免内核发生OOM时,被内核kill掉.

可调整容器使用内存的限制:
  -m | --memory=    #限制容器能使用的物理内存大小.单位:k, m, g; 若设置一个容器可用内存为4m,若容器使用超过,将被kill掉.
  --memory-swap=    #要使用它,必须先使用 -m 选项,否则它不生效.
    若设置: -m 7G --memory-swap=10G, 则表示Swap+Ram=10G, Swap=10-7=3G,即可使用3G的Swap内存.
    若设置: -m 7G --memory-swap=7G, 则表示不使用Swap内存.即 若设置这两个参数值相同,表示禁用SWAP.
    若设置: -m 7G --memory-swap=0, 则表示SWAP未设置, 则若DockerHost启用了SWAP,则表示容器可用的SWAP大小=2*RAM的大小.
    若设置: -m 7G --memory-swap=-1, 则表示DockerHost上启用了Swap,则容器可使用的全部的SWAP大小.
   注:
    free : 在容器中使用free看到的swap空间使用情况并非上面这些参数计算出来的实际情况, 也就是说free查看容器使用的内存空间是非常不准确的。
    --memory-swappiness: 设置容器使用SWAP内存的倾向性. 值的范围: 0~100, 0:能不用就不用, 100:只要能需要就使用.
    --memory-reservation: 设置要预留多少内存空间。
    --oom-kill-disable 设置当发生OOM时,是否禁止此容器被kill掉,它要可-m一起使用.

CPU:
  默认所有容器使用CPU资源都没有限制。
  --cpu-shares  #CPU是可压缩性资源,若当前有A,B,C三个容器, 假如分配给他们CPU占用的比例为:1024:512:2048.
        则表示,将CPU资源分2+1+4,即分成7份, 三个容器都需要CPU,则A使用2份CPU时间, B使用1份
        CPU时间, C使用4份CPU时间, 若B和C当前都空闲,则A可使用全部CPU资源; 若此时A和B都需要
        用CPU资源,则按照A使用2份CPU资源, B使用1份CPU时间, 若又新加了D,则再重新分割CPU时间片.
  --cpus=   #限制单个容器最多可使用几核CPU, 即: 假如有4个核心, 还是A,B,C, 若此时B和C都不使用CPU
        在不限制的情况下,A可使用4个核心,即最大可使用400%的计算能力.若设置了单个容器的
        最多可使用CPU核心数,则基本当前所有容器都不用CPU,你也只能使用限制个数的核心数.
  --cpus=1.5 #表示最多可用150%,注意容器最多可使用150%的CPU计算能力,指的是
        只有能限制它最多使用这么多计算能力即可,至于容器在那个CPU核心上
        运行无所谓,随机分配,分到那个核心上就在那个核心上运行。但总量是不会超过150%的。
  --cpuset-cpus=     #这是限制容器能够运行在那个CPU核心上的, 假如:有4核心, 则用0~3来表示4个核心的编号.
  --cpuset-cpus=0,1   # 则表示容器只能运行在核心0和1上,其它上面不行。
  --cpu-period=        #限制最多可用CPU的时间.
  --cpu-quota=

以上这些选项在docker run 时可以设置。

docker压测工具:
  docker pull lorel/docker-stress-ng
  docker run --name stress -it --rm -m 256m lorel/docker-stress-ng:latest stress --help #可查看帮助.
  docker run --name stress -it --rm -m 256m lorel/docker-stress-ng:latest stress --vm 2 #限制其最多使用256M内存.
  docker run --name stress -it --rm --cpus 2 lorel/docker-stress-ng:latest stress --cpu 8 #限制最多使用2个CPU核心的计算资源.

  终端1:
    docker run --name stress -it --rm --cpu-shares 1024 lorel/docker-stress-ng:latest stress --cpu 8

  终端3:
    docker run --name stress -it --rm --cpu-shares 512 lorel/docker-stress-ng:latest stress --cpu 8

  终端2:
    docker top stress #查看容器进程数
    docker stats #查看docker资源的消耗情况。

Docker原理及使用的更多相关文章

  1. 一篇不一样的docker原理解析

    转自:https://zhuanlan.zhihu.com/p/22382728 https://zhuanlan.zhihu.com/p/22403015 在学习docker的过程中,我发现目前do ...

  2. docker原理与上帝进程

    做个笔记, 先水一会. 虚拟机指的是: 在软件的层面上通过模拟硬件进行的输入输出. docker原理:docker就是一个linux系统的进程, 它通过 Linux 的 namespaces 对不同的 ...

  3. Docker原理探究

    问题思考:-------------------------------------Docker浅显原理理解-------------------------------------P1. ubunt ...

  4. docker原理

    Docker原理11 Linux Namespace 11 AUFS文件系统17 重新理解Docker的各种命令18 Docker原理 Linux Namespace docker是一个容器引擎,容器 ...

  5. Docker原理(开发技术分享转发)

    Docker原理Docker是啥Docker是一个程序运行.测试.交付的开放平台,Docker被设计为能够使你快速地交付应用.在Docker中,你可以将你的程序分为不同的 基础部分,对于每一个基础部分 ...

  6. docker原理(转)

    转自:https://zhuanlan.zhihu.com/p/22382728 https://zhuanlan.zhihu.com/p/22403015 在学习docker的过程中,我发现目前do ...

  7. 一篇文章带你吃透 Docker 原理

    容器的实现原理 从本质上,容器其实就是一种沙盒技术.就好像把应用隔离在一个盒子内,使其运行.因为有了盒子边界的存在,应用于应用之间不会相互干扰.并且像集装箱一样,拿来就走,随处运行.其实这就是 Paa ...

  8. Docker系列(4)- run的流程和docker原理

    回顾HelloWorld流程 底层工作原理 Docker是怎么工作的? Docker是一个Client-Server结构的系统,Docker的守护进程运行在宿主机上.通过Socket从客户端访问 Do ...

  9. docker原理(转)

    可能是把Docker的概念讲的最清楚的一篇文章 [编者的话]本文只是对Docker的概念做了较为详细的介绍,并不涉及一些像Docker环境的安装以及Docker的一些常见操作和命令. Docker是世 ...

  10. docker 原理

    docker项目的目标是实现轻量级的操作系统虚拟化,Docker的基础是Linux容器(LXC)等技术. 在LXC的基础上,Docker做了进一步的封装,让用户不关心容器的管理,使得操作更为简单.用户 ...

随机推荐

  1. laravel5.4 orm with 用法

    在laravel orm 中一个with 关联方法,需要在模板中先定义表与表之间的关系 /*一对多的关系 */ public function hasManyTemplate(){ return $t ...

  2. C# Winform 文本框默认提示信息

    private string Notes = "提示文本"; private void textBox1_Leave(object sender, EventArgs e) { / ...

  3. 关于注解sql和动态sql的写法

    注解写sql一般写在mapper层,如果sql语句复杂建议不要写注解sql 拼接容易出错 二动态sql的话要在 main 下面创建一个resource ——mapper—— Mapper.xml 再在 ...

  4. 使用wcftestclient.exe测试时,增加“最大消息大小配额”--maxReceivedMessa

    使用 WcfTestClient.exe工具测试的时候,可能会出现:这样的提示: 已超过传入消息(65536)的最大消息大小配额.若要增加配额,请使用相应绑定元素上的 MaxReceivedMessa ...

  5. pytest之mark功能

    pytest系列(一)中给大家介绍了pytest的特性,以及它的编写用例的简单至极. 那么在实际工作当中呢,我们要写的自动化用例会比较多,不会都放在一个py文件里. 如下图所示,我们编写的用例存放在不 ...

  6. Ablation Study

    We often come across 'ablation study' in machine learning papers, for example, in this paper with th ...

  7. 人脸跟踪开源项目HyperFT代码算法解析及改进

    一.简介 人脸识别已经成为计算机视觉领域中最热门的应用之一,其中,人脸信息处理的第一个环节便是人脸检测和人脸跟踪.人脸检测是指在输入的图像中确定所有人脸的位置.大小和姿势的过程.人脸跟踪是指在图像序列 ...

  8. 前端1-----CSS颜色属性,字体文本和背景属性,边框属性,margin和padding,盒模型,行内块转换,浮动,三大定位

    前端1-----CSS颜色属性,字体文本和背景属性,边框属性,margin和padding,盒模型,行内块转换,浮动,三大定位 一丶css选择器的优先级 行内 > id选择器 > 类选择器 ...

  9. Python - 实现矩阵转置

    有个朋友提出了一个问题:手头上现在有一个二维列表,比如[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]],现在要把该二维列表变成为[[1, 4, 7, 10 ...

  10. 英语apyrite红碧玺apyrite单词

    红碧玺(apyrite)是粉红.桃红.玫瑰红.深红.紫红等以红色调为主的碧玺,矿物学上主要属于锂电气石和镁电气石.红色起因可能与微量锰及锂和铯有关. 红色是碧玺中价值最高的,其中以紫红色和玫瑰红色最佳 ...