Docker原理及使用

Docker原理及使用

2023年7月6日发(作者:)

Docker原理及使⽤  虚拟化系统:  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-->简称k8slibcontainer:

  ⼜称为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镜像仓库地址: ,当然国内也有很多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/      { "registry-mirrors": [""] }  查看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 :为启动的容器名⼀个名字.    --network :将容器加⼊⼀个指定的⽹络中.  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/    / #httpd -f -h /data/httpd      #在busybox中启动⼀个httpd进程,并指明其web根⽬录.    / #exit              #执⾏exit就退出了sh终端,也就终⽌了容器.  终端2:    docker ps    docker inspect b1   #可查看b1这个容器的详细信息.    curl 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 /coreos/flannel:v0.10.0-amd64

     #下载 这个⽹站的coreos名称空间下的flannel仓库中的tag为v0.10.0-amd64 的镜像。默认docker使⽤https去下载. 是docker镜像很有名的第三⽅提供者. ⽰例1:  #基于busybox创建⼀个测试镜像:    docker run --name bx1 -it busybox    / #mkdir -p /data/html    / #vi /data/html/      

Hello busybox HTTP Server

  终端2:    docker commit -p bx1    #-p是让bx1容器先暂停,避免有⼈访问镜像,导致镜像创建不完成.    docker image ls      #可看到刚创建的镜像.    docker tag 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 " -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 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 tom/bbox:v0.1 tom/bbox:v0.2    #这样即可将两个镜像打包成。

    #登录到另⼀台docker上就可以执⾏:    docker load -i #就可以导⼊镜像了    docker image ls  ⽰例6:    docker exec -it --name bx1    / #wget -O - -q 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 127.0.0.0.1/    终端2:      docker run --name bx2 -it --network container:bx1 --rm busybox      / #echo "hello world." > /tmp/      / #httpd -f -h /tmp  ⽰例2:    vim /etc/docker/ #以下仅供参考,新版本有些参数以不⽀持!!    {      "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监听在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 --rm busybox:latest    docker run --name t1 -it --network bridge -h --dns 114.114.114.114 --rm busybox:latest    docker run --name t1 -it --network bridge -h --dns 114.114.114.114 --add-host :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.2Docker的数据卷(Data Volume):  为避免关闭再重启容器,其数据不受影响,但删除Docker容器,则其更改将会全部丢失.  存在的问题:

    1. 存储于联合⽂件系统中的数据,宿主机不易访问.    2. 容器间数据共享不⽅便.    3. 删除容器其数据会丢失.  解决⽅案:"卷(Volume)":    卷是容器上的⼀个或多个⽬录(即:多个卷),此类⽬录可绕过联合⽂件系统,与宿主机上的某⽬录绑定(即关联)Docker有两种类型的卷:  1. Bind mount volume(绑定挂载卷):这是有⽤户⾃定义指定docker中的某⽬录挂载到宿主机的某个指定⽬录.  2. Docker-managed volume(docker管理的卷): 这是由docker⾃⼰维护,⽤户需要在/etc/docker/中指定启⽤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/      #接着在容器中查看.      # 再尝试删除容器,再关联相同⽬录,查看数据是否依然可访问。    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 {{.ess}} 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 <仓库名>[:] 或 FROM <仓库名>@  使⽤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 或 COPY ["",...""]    #注:Src若为⽬录,复制时,是仅复制⽬录中⽂件,⽽不复制⽬录本⾝的.  ⽰例:    mkdir /dockerfile/    cd /dockerfile    vim Dockerfile    #注: ⽂件名⾸字母必须⼤写.      #注: Dockerfile中的每条指令都是⼀层,层数越多挂载效率越差!!      #Description: test image      FROM busybox:latest      MAINTAINER "Tom "      # LABEL maintainer="Tom "   #功能和上⾯⼀样.      COPY /data/web/html/        #需要将放到/dockerfile中      COPY .d /etc/.d/      #注: 先将.d 复制党/dcokerfile中, 然后在写此命令.                  ADD /download/ /usr/local/src/    #它会⾃动在打包时下载该URL指定的⽂件.      ADD /usr/local/src      #打包时,会⾃动将展开放⼊/usr/local/src/的⽂件.      WORKDIR /usr/local/src    #将它做为⼯作⽬录.      ADD ./       #这⾥引⽤的相对路径就是WORRDIR所设定的⽬录.      WORKDIR /etc/.d/      ADD ./      #这⾥的相对路径就是/etc/.d/了。      #VOLUME ["/dir_1", "/dir_2" ..]    #设置容器挂载主机⽬录      VOLUME /data/mysql/        #指定Docker⾃动管理的卷。      #EXPOSE /      EXPOSE 80/tcp     

        #指定要对外暴露TCP的80端⼝,但这⾥指定暴露,实际并不会直接暴露,⽽是需要在启动容器时,使⽤ “-P” 才会真正暴露此端⼝给外部⽤户.       # docker port 容器名 #在不加"-P"时,可使⽤它来验证是否暴露了80端⼝.      #ENV        #此格式定义的变量,会将空格后⾯的所有字符串都当做keyname的值.      #ENV = = ... #此格式可创建多个环节变量. 若值中有空格,需要⽤""转义, 或⽤引号引起来.      ENV DOC_ROOT /data/web/html      COPY *.html $DOC_ROOT      COPY *.jsp ${JSP_ROOT:-/data/web/jsp/} #注:这些环境变量,是可以在启动容器时,指定"-e JSP_ROOT=/data/jsp" 来修改的.      #RUN && ... #RUN执⾏命令是在docker build时执⾏命令.      WORKDIR /usr/local/src      ADD / ./      RUN cd ./ &&       tar xf      #仅做多⾏写命令的测试     #RUN ["","",....]

     #RUN的第⼆种语法格式.它使⽤JSON数组,Executable为要运⾏的命令,后⾯为命令的参数,可有多个.此格式启动的命令不会以/bin/sh -c 的⽅式启动,因此它不能使⽤sh的命令语法,如:变量替换,通配符等. 若想使⽤shell特性的话,可⽤以下⽅式:    RUN ["/bin/sh","-c","","Param1",...]    注:      RUN 和 CMD 及 ENTRYPOINT 若使⽤中括号来表⽰数组时,其中不能使⽤单引号.必须使⽤双引号.    docker build --tag tinyhttpd:v0.1 ./  测试:    docker run --name tinyweb1 --rm tinyhttpd:v0.1 cat /data/web/html/    docker run --name tinyweb1 --rm tinyhttpd:v0.1 ls /etc/.d/  #启动镜像时,传递参数:    Dockerfile:    FROM java:8    ADD /root    ENV PARAMS=""    ENTRYPOINT ["sh","-c","java $PARAMS -jar /root/"]    测试:      docker run -d -e PARAMS="-=8080" -p 2000:8080 镜像名称Docker私有仓库的构建:  1. 安装docker的仓库构建程序包.    yum install docker-distribution  2. vim /etc/docker-distribution/registry/    services: registry #表⽰运⾏的服务为registry    layerinfo: inmemory #表⽰缓存在内存中.    addr: :5000 #没有指定地址,表⽰使⽤0.0.0.0:5000  3.启动服务:    systemctl start docker-distribution

  4. 给⾃⼰做的镜像打上⾃⼰的仓库地址的标签.    docker tag myweb:v0.3.11 :5000/myweb:v0.3.11  5. 将⾃⼰打好标签的镜像push上去.    docker push :5000/myweb:v0.3.11    #这⾥会报错,说我们使⽤了不安全的http.  6. 若我们是内⽹使⽤, 不想使⽤HTTPS,可修改配置⽂件为:    vim /etc/docker/      {      ...      "insecure-registries": [":5000"]      }    systemctl restart docker  7. 再次push  8. 可到其它节点上测试下载.    docker pull :5000/myweb:v0.3.11Docker的资源限制:  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资源的消耗情况。

发布者:admin,转转请注明出处:http://www.yc00.com/news/1688594315a153206.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信