docker|docker详解

初识docker

主机级虚拟化分为两类:第一种是安装再host之上,另一只是直接再硬件上安装一个虚拟化系统 主机级虚拟化与容器级虚拟化异同: 目的相同:都是为了实现进程隔离 主机级虚拟化隔离:为了实现隔离运行进程需要创建一个系统,代价太大 容器级虚拟化隔离:因为进程是在用户空间运行,所以只隔离用户空间容器级虚拟化的实现lxc核心为以下三部分: chroot namespaces名称空间: 域名、主机名(UTS); 文件树(mount) 进程间通信(IPC) 进程树(PID) 用户和组(user) 网络(net) cgroups(系统级资源分配) 把系统级资源分成多个组,然后把每个组内资源量指派给用户空间

docker|docker详解
文章图片

docker|docker详解
文章图片

docker: docker是lxc的增强版或二次发行版,是内核容器技术的前端工具,老版本的docker是把lxc作为其引擎,极大简化了lxc创建用户空间时通过定制模板进行安装的复杂过程,daocker是通过将整个调试部署好的运行环境打包成镜像直接运行镜像进行创建用户空间,优化了批量创建管理功能,后来docker已经抛弃lxc引擎,采用libcontainer引擎,再到目前容器运行时的环境标准化的实现runC引擎 docker底层通过分层构建联合挂载的机制实现,每一底层镜像都是只读和共享的,最上层才是私有的可读写的,这样极大方便了分发效率、过程,程序数据会保存到外挂盘中,这样可以方便迁移,脱离容器实现持久存储 遵循一个容器一个进程的原则: 弊端:但是会占用更大的空间,每个容器都需要自带调试查看工具 优势:极大的方便了开发人员,可以跨平台、系统和开发语言,真正实现了一次编写到处运行,部署方便配置好镜像一条命令就可以运行 编排工具: 作用:实现程序编排(解决程序间依赖关系和启动顺序等)和底层资源调用 docker与k8s都是用go语言研发 实现: machine+swarm+composedocker自带 mesos+marathon 底层资源编排 kubernetes/k8s 主流编排工具 docker架构:C/S,由三部分组成: Daemon:docker主机运行的守护进程 Containers Images 本地镜像仓库 Client:通过http或https协议传输 Registries :注册表,远程镜像仓库,默认为 docker hub(或可以选择一些国内镜像仓库),通过http或https协议传输,默认是https 功能:认证、索引、镜像仓库,不同于yum仓库,Registries里每个不同的应用程序都有一个单独的仓库,仓库名就是应用程序名,镜像名字是仓库名+tag并且一个镜像可以有多个标签,如果下载镜像时不给标签,默认下载最新版镜像(latest标签的镜像),一般下载时可以选在稳定版(stable标签)镜像镜像与容器的关系:类似于执行命令,执行命令需要加载本地文件并启动一个进行,而本地文件可以看作镜像,进程可以看作容器,当命令执行完之后进程就会停止,而本地文件还在,同理容器中应用程序停止后容器也会停止,而镜像还在。docer对象:因为在docer上都是静态风格的接口,所以每一组件都会被当做对象来管理,可单独支持增删改查,对象分别有: images containers networks volumes 存储卷,一般在外部的网络存储之上 plugins

docker安装
清华大学开元镜像版本较新所以配置yum源 cd /etc/yum.repos.d/ wgethttps://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/docker-ce.repo sed s@https://download.docker.com/@https://mirrors.tuna.tsinghua.edu.cn/docker-ce/@gdocker-ce.repo yum repolist 查看是否有包 yum install -y docker-cedocker配置文件 /etc/docker/daemon.json(启动前可以手动创建) docker镜像加速配置:可以用以下三种 docker cn 阿里云加速器 中国科技大学 cn 配置: { "registry-mirrors": ["https://registry.docker-cn.com"] } 查看: docker version 查看docker相关版本信息 docker info查看详细信息如(容器、镜像等)

docker基础命令的使用
docker|docker详解
文章图片

docker search搜索远端镜像 -H, --host list远程管理所指定的主机,需修改配置文件 示例: docker -H 10.0.0.2:2347 image ls login登录registry Usage:docker login [OPTIONS] [SERVER] Options: -p, --password stringPassword -u, --username stringUsername image镜像相关命令 pull[registry][:port] /[/]:拉取镜像,[registry][:port}省略时默认为Hub registry,端口省略时默认为https(443端口),[/]省略时默认为顶级仓库 示例: docker image pull quay.io/coreos/flannel:v0.10.0-amd64 push推送本地镜像到registry,注意本地标签一定要与所推送的registry信息一致,并且需要先登录registry才能push Usage:docker image push [OPTIONS] NAME[:TAG] 示例: docker image push cuijian/httpdls[REPOSITORY[:TAG]] 列出本地镜像, inspect 查看镜像详细信息,其中CMD内容为镜像的默认启动的第一个进程命令 rm tag 添加标签,一个镜像可以有多个标签 Usage:docker image tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG] 示例: docker image tag4996f4623cd5 cuijian/nginx:v0.1-1 docker image tagcuijian/nginx:v0.1-1cuijian/nginx:latest build制作镜像 Usage:docker image build [OPTIONS] PATH | URL | - Options: -t, --tag list打标签 --build-arg list设置构建时的变量 container容器相关命令 inspect查看容器详细信息 execUsage:docker container exec [OPTIONS] CONTAINER COMMAND [ARG...] 绕过容器边界,在容器中执行外部命令,并顶替和取代ID为1的进程,但为保障容器中ID为1的进程不变依然能接收容器启动停止等信号,容器内默认又进行exec -it附加终端并交互式登录 示例: docker containerexec -it ngx1 /bin/sh create start -ai 附加交互式接口 stop kill port查看指定容器中的端口映射 log日志直接保存在控制台中 run[OPTIONS] IMAGE [COMMAND] [ARG...] 创建并启动容器 在容器中跑任何程序不能运行在后台,否则容器任务程序不存在而终止容器 -t, --tty附加一个终端 -i交互式访问 --name string容器名称 示例:注意因为busybox默认运行/bin/bash为主进程,shell有交互接口且必须要附加终端进行交互才能使进程在前台运行,否则容器运行即推出,如果默认进程非/bin/bash 可以用exec /bin/bash 替换默认进程进行交互 docker run --name b1 -it busybox:latest -d启动后挂载到后台,与容器外的当前系统的终端剥离 --rm容器停止即删除 --network [bridge/host/none/container:CONTAINER]选择一个网络模型,默认为bridge 示例: 创建联盟式网络模型web2,共享web1的网络相关名称空间 docker --name web2-d --network container:web1 cuijian/nginx:v0.1 -h, --hostname string 从容器外注入主机名 --add-host list(host:ip) 添加本地解析 --dns list 设置自定义的dns列表 -p[ip:][port:] 暴漏容器的指定端口,可以使用多次(bridge网络模型使用的是nat桥模式,所以需要主动把桥内部容器暴露出来,外部主机才能进行访问内部容器,所以一共有4中暴露方式) 示例: 暴漏容器web1的80端口,映射到物理机所有网卡的随机端口上 docker run --name web1 -p 80 cuijian/httpd:v0.2 暴漏容器web1的80端口,映射到物理机所有网卡的8080端口上 docker run --name web1 -p 8080:80 cuijian/httpd:v0.2 暴漏容器web1的80端口,映射到物理机172.16.0.67网卡的随机端口上 docker run --name web1 -p 172.16.0.67::80 cuijian/httpd:v0.2 暴漏容器web1的80端口,映射到物理机172.16.0.67网卡的8080端口上 docker run --name web1 -p 172.16.0.67:8080:80 cuijian/httpd:v0.2 -P 暴漏所有端口 --volumes-from复制另一个容器的存储卷,可以与共享网络同时用 -e, --env list启动容器时设置变量值pause暂停 unpause取消暂停 top 显示资源消耗情况 ls显示运行中的容器 -a 显示所有容器,包括停止的 commit制作镜像 Usage:docker container commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]] Options: -a, --author stringAuthor (e.g., "John Hannibal Smith ") -p, --pause 创建时使容器出于暂停状态 -c, --change list:修改容器内部默认启动时命令 示例:(-f 为运行在前台 -h 为指定根目录) docker container commit-a "cuijian " -c 'CMD ["/bin/httpd","-f","-h","/date/nginx"]' -p box1 cuijian/httpd:v0.3 save 打包导出镜像 Usage:docker image save [OPTIONS] IMAGE [IMAGE...]可一次打包多个 Options: -o, --output stringWrite to a file, instead of STDOUT指定打包的文件 示例: docker image save -o nginx.gz cuijian/nginx:v0.1 cuijian/nginx:v0.2 load镜像导入 Usage:docker image load [OPTIONS] Options: -i, --input stringRead from tar archive file, instead of STDIN 示例: docker image load -inginx.gz network 网络相关命令 inspect 查看网络详细信息 Usage:docker network inspect [OPTIONS] NETWORK [NETWORK...] 示例: docker network inspect bridge ls

镜像管理
docker镜像: 含有启动容器所需要的文件系统及内容,因此其用于创建并启动docker容器 采用分层构建机制,最底层为为bootfs,其上层为rootfs(真正用来构建用户空间并运行容器的) bootfs:用于系统引导的文件系统,包括bootloader和kernel,容器启动完成后会被卸载以节约内存资源; rootfs:位于bootfs之上,表现为docker容器的根文件系统; 传统模式中,系统启动时,内核挂载rootfs时会首先将其挂载为”只读“模式,完整性自检完成后将其重新挂载为读写模式; docker中,rootfs由内核挂在为”只读“模式,而后通过”联合挂载“技术额外挂载一个”可写“层; 镜像分层: 基础镜像:docker镜像中最底层 父镜像:位于下层镜像是上层镜像的父镜像 可读写层(启动的容器中生成):最上层为”可读写“层,其下的均为只读层 示例:在一个apache镜像中,底层为bootfs引导层,在上层会有一个非常基础的例如centos系统,在上层是一个vi工具,在上层才是apache,当容器启动完成后会把bootfs从内存中卸载掉,然后在内存中添加一个可读写层(容器删除此层也会被删除包括所有数据),除了读写层是容器私有,其他的相当于本地文件是其他容器可共享的, 存储镜像文件系统:要实现这种镜像分层和联合挂载技术需要依赖于专有的文件系统 aufs:联合文件系统,docker早期使用的文件系统 overlayfs:叠加文件系统,已合并到3.18Linux内核之中,目前为止docker所使用的文件系统驱动,是一种抽象的二级文件系统,需要建构在本地文件系统之上Docker Registry:用于保存docker镜像,包括镜像的层次结构和元数据 分类: Sponsor Registry:第三方的registry,供客户和docker社区使用 Mirror Registry:第三方registry,只让客户使用 Vendor Registry:由发布Docker镜像的供应商提供的registry Private Registry:通过设有防火墙和额外的安全层的私有实体提供的registry,自建registry,可以不消耗网络带宽 组成: Repository: 由某特定的docker镜像的所有迭代版本组成的镜像仓库 一个Registry中可以存在多个Repository Repository可以分为”顶层仓库“和”用户仓库“ 用户仓库名称格式为”用户名/仓库名“ 每个仓库可以包含多个Tag,每个标签对应一个镜像 Index 维护用户账号、镜像的校验以及公共命名空间的信息 相当于为Registry提供了一个完成用户认证等功能的检索接口 云原生:基于单机系统开发的程序在容器中修改维护配置时有诸多不便,因此就基于云环境或接口而开发的程序,例如可以直接传环境变量修改配置docker hub:默认Docker Registry 功能: 镜像仓库: 自动构建:把更新的文件提交到github中,然后docker hub会获取这文件并进行自动构建为新的镜像 Webhooks:钩子,与github关联,当github更新时自动触发钩子进行构建镜像 用户组阿里云registry的使用: 登录阿里云搜索容器镜像服务 找到镜像加速器根据器上的内容添加到配置文件中并重启 进入实例列表的个人实例创建命名空间和仓库 进入仓库中根据其中的操作指南进行上传或拉取代码`在这里插入代码片` 示例: 创建镜像或者打标签: docker image tagcuijian/httpd:v0.3registry.cn-qingdao.aliyuncs.com/cuijian442230/test:v0.1 登录: docker login --username=cuijian442230 registry.cn-qingdao.aliyuncs.com 推送: docker image push registry.cn-qingdao.aliyuncs.com/cuijian442230/test:v0.1镜像制作有三种方式: dockerfile然后build成镜像 基于容器制作(docker commit),会把运行容器中的可写层单独创建一个镜像 docker Hub automated builds (类似于Docker file),docker Hub上的子自动构建镜像功能 (1)基于容器做镜像 示例: 创建镜像:docker container commit-a "cuijian " -c 'CMD ["/bin/httpd","-f","-h","/date/nginx"]' -p box1 cuijian/httpd:v0.3 登录registry:docker login -u cuijian -p 123456 远程推送 :docker image push cuijian/httpd镜像的导入导出: 示例: 导出: docker image save -o nginx.gz cuijian/nginx:v0.1 导入: docker image load -inginx.gz

容器虚拟化网络概述
补充内容
VMware虚拟机三种网络模式:桥接模式,NAT模式,仅主机模式
brctl命令:网桥管理,安装包:yum install bridge-utils -y
ip netns 配置网络名称空间
网络名称空间:主要用于实现协议栈、网络设备等的隔离 docker*安装完成之后会自动生成一个bridge(nat桥,可以用docker network ls 查看)网络和一个docker0接口,它既可以当交换机使用又可以当网卡使用,每当创建一个容器时就会自动生成一对虚拟网卡,其中一段在容器中,另一端就在docker0这个交换机上。(docker0和与交换机相连的虚拟接口可以ifconfig查看,网桥可以用brctl show 查看),所以同一台主机上的创建的容器都在同一个bridge上时是可以直接通信的,而所在的物理机是直接把docker0这个虚拟交换机直接当网卡用了,默认IP为172.17.0.1,所以也可以直接跟容器通信,但是在创建容器时因为是nat'桥,默认进行了地址伪装(SNAT,可以在物理机iptables -nL 查看),所以其他外部主机是访问不到此物理机上的容器的,想要被访问需要主动暴漏发布端口(DNAT),但是用这种网络模型,如果有多个容器都使用80端口,并且物理机上只有一个网卡,就导致只能有一个容器在对外暴漏时的端口是80,其他的需要选择其他端口,并且如果双方都是容器都要经过nat转换导致通信效率低下。解决方法:叠加网络。当然还有物理桥桥接,不过这种在大型环境上容易出现网络风暴 Overlay Network(叠加网络):基于隧道,在原有IP报文之上在封装一层IP报文,通信时首先外层IP报文通信,在找到对应主机后,在通过内层IP报文找到真正要访问的物理主机之上的虚拟主机服务器,因此容器可以直接暴漏端口不在需要DNAT映射docker中有4种网络模型 bridge(默认)使用虚拟网卡nat桥到虚拟交换机docker0上 开放式容器(host):共享物理网卡(容器共享主机的网络相关的名称空间),对容器中的网络有修改权限,在容器中创建的进程可以直接通过物理机网卡接口网访问 封闭式容器(none):无网络只有一个lo(本地回环)接口 (bridge/host/none 网络模型启动时可以直接用 run --network 指定 ) 联盟式网络:一台物理机的多个容器其中6个名称空间的User、PID、Mount为私有,但是UTS、IPC、NETWORK共享一个名称空间,lo本地回环接口可以直接访问共享一个网络相关名称空间的所有容器,启动时需要docker run container:CONTAINER参数 例如:dockercontainer run --name b2--network container:b1busybox:latest 自定义docker0桥的网络属性信息 核心选项为bip,即bridge ip之意,用于指定docker0桥自身的IP地址;其它选项可通过此地址计算得出。 vim /etc/docker/daemon.json文件 { "bip": "192.168.1.5/24", "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:abcd::89", "dns": ["10.20.1.2","10.20.1.3"] } 远程管理 dockerd守护进程的C/S,其默认仅监听Unix SOcket格式的地址,/var/run/docker.sock(只监听在本地),如果想要守护进程监听在TCP套接字上需要修改配置文件并重启docker: vim /etc/docker/daemon.json "hosts": ["tcp://0.0.0.0:2375", "unix:///var/run/docker.sock"] 配置完成之后可以远程连接命令测试示例: docker -H 10.0.0.2:2347 image ls 创建虚拟桥 docker network create: Usage:docker network create [OPTIONS] NETWORK Options: -d, --driver [bridge/host/ipvlan/macvlan/null/overlay] 选择网络模型/驱动,默认为bridge --subnet子网掩码 --gateway 示例: docker networkcreate -d bridge --subnet "172.16.0.0/16" --gateway "172.16.0.1" bridge2 查看网络: docker network ls 查看接口:ifconfig 改接口名: ifdown br-34a62d88abbe && ip link set dev br-34a62d88abbe nameeth1 补充:想在同一个docker中的两个网络(网桥)内的容器进行通信只需要打开宿主机的网络转发并且开通自动生成的防火墙规则即可

Docker 存储卷
读写层: Docker镜像由多个只读层叠加而成,启动容器时docker会加载只读镜像层并在镜像栈顶部(内存中)添加一个读写曾 写实复制: 如果运行中的容器修改了现有的一个已经存在的文件,那该文件将会从读写层下面的只读层复制该文件到读写层,该文件的只读版本仍然存在,只是已经被读写层中该文件的副本所隐藏,此即“写实复制”机制 缺点,I/O效率低下,在对I/O要求较高的服务例如:mysql、redis ,满足不了其对性能的需求 解决实现技术:存储卷存储卷:docker容器的文件系统是分层构建联合挂在,因为结构的复杂使得io效率很慢,这时就可以把宿主机或NFS服务器等的一个目录挂在到容器中读写层的一个目录中从而绕过容器的文件系统提高io效率 优点: 可以实现脱离容器的生命周期而使数据持久 易于容器间数据共享 宿主机访问数据方便 docker的存储卷目前默认是本机的文件系统,容器只能在同一台主机上才能调度存储卷,如果有状态分布式服务想要实现跨主机存储就需要找到之前的持久数据,这个docker本身无法实现需要运维人员通过NFS等共享存储和编排工具等实现 创建存储卷有两种方式,用docker run -v 实现: 第一种:只需要指定容器中的一个路径即可,容器驱动会根据规则自动关联到宿主机目录 示例: docker container run -it --name t1 -v data busybox 第二种:需要指定宿主机目录和容器中目录(甚至可以两个容器共享一个宿主机目录) docker container run -it -v HOSTDIR:VOLUMEDIR --name t1 busybox 查看命令: docker container inspect CONTAINERNAME docker containerinspect-f {{.Mounts}} web2用go模板进行过滤 查看Volumes值和Mounts值启动容器并复制另一个容器的存储卷 前置:生产中经常把一个容器不启动当作底层支撑容器(模板),让其他容器复制它的配置 示例: docker run --name bbox2 --volumes-from bbox1 busybox

Dockerfile基础
dockerfile:是构建镜像的文本文件,在用镜像启动容器时会先启动另一个程序用来读取dockerfile的配置和传递的参数,然后再用容器中的进程替换此程序实现按需配置启动 优点:可以一次编写多节点传递参数并生效 格式: #注释 form指令(第一个非注释行为form指令来指定做当前镜像是用哪个基础镜像) 指令+ 参数 :从上往下顺序执行,因此如果有依赖关系,被依赖的指令应该在上面行 要求: 找一个专门的dockerfile目录 dockerfile文件名首字母必须大写 如果要给镜像加入工具包,必须把相关文件或者包放在dockefile目录的当前目录或子目录中 dockeringore(隐藏文件):所有写在这个文件中的路径,打包时都不会被包含进来docker build 进行镜像构建镜像,构建时执行的命令是基于镜像中程序的命令而不是宿主机上的命令 Usage:docker build [OPTIONS] PATH | URL | - Options: -t, --tag list 支持的环境变量,用法与bash中类似:以下两种特殊用法 ${NAME:-tom}:设置变量默认值,若变量为空则值为tom ${NAME:+tom}:若变量有值则赋值为tom

dockerfile 指令:
注意:dockerfile中每一条命令都会生成一个镜像层,所以尽量简化命令
from: FROM指令是最重的一个且必须为Dockerfile文件开篇的第一个非注释行,用于为映像文件构建过程指定基准镜像,后续的指令运行于此基准镜像所提供的运行环境 实践中,基准镜像可以是任何可用镜像文件,默认情况下,docker build会在docker主机上查找指定的镜像文件,在其不存在时,则会从Docker Hub Registry上拉取所需的镜像文件 如果找不到指定的镜像文件,docker build会返回一个错误信息Syntax: FROM [:] 或 FROM @ (@<哈希码>) :指定作为base image的名称; :base image的标签,为可选项,省略时默认为latest; label:标签指令向镜像添加元数据 syntax:LABLE == =... 示例: LABLE maintainer="cuijian"copy:用于从Docker主机复制文件至创建的新映像文件 Syntax COPY... 或 COPY ["",... ""] :要复制的源文件或目录,支持使用通配符 :目标路径,即正在创建的image的文件系统路径;建议为使用绝对路径,否则,COPY指定则以WORKDIR为其起始路径; 注意:在路径中有空白字符时,通常使用第二种格式 文件复制准则 必须是build上下文中的路径,不能是其父目录中的文件 如果是目录,则其内部文件或子目录会被递归复制,但目录自身不会被复制 如果指定了多个,或在中使用了通配符,则必须是一个目录,且必须以/结尾 如果事先不存在,它将会被自动创建,这包括其父目录路径 示例:把当前yum.repos.d目录下的文件复制到镜像中 COPY yum.repos.d/etc/yum.repos.d/ ADD:ADD指令类似于COPY指令,ADD支持使用TAR文件和URL路径 Syntax ADD... 或 ADD ["",... ""] 操作准则 同COPY指令 如果为URL且不以/结尾,则指定的文件将被下载并直接被创建为;如果以/结尾,则文件名URL指定的文件将被直接下载并保存为/ 如果是一个本地系统上的压缩格式的tar文件,它将被展开为一个目录,其行为类似于“tar -x”命令;然而,通过URL获取到的tar文件将不会自动展开; 如果有多个,或其间接或直接使用了通配符,则必须是一个以/结尾的目录路径;如果不以/结尾,则其被视作一个普通文件,的内容将被直接写入到;WORKDIR: 用于为Dockerfile中所有的RUN、CMD、ENTRYPOINT、COPY和ADD指定设定工作目录 Syntax WORKDIR 在Dockerfile文件中,WORKDIR指令可出现多次,其路径也可以为相路径,不过其是相对此前一个WORKDIR指令指定的路径,另外WORKDIR也可调用由ENV指定定义的变量 例如 WORKDIR /var/log WORKDIR $STATEPATHVOLUME: 用于在image中创建一个挂载点目录,以挂载Docker host上的卷或其它容器上的卷 只能指定image中的目录,但在宿主机或其他容器上的关联目录会通过docker驱动自动选择生成无法自定义 Syntax VOLUME 或 VOLUME [""] 如果挂载点目录路径下此前有文件存在,docker run命令会在卷挂载完成后将此前的所有文件复制到新挂载的卷中EXPOSE: 用于为容器打开指定要监听的端口以实现与外部通信 只能指定暴露的端口,容器动态绑定宿主机的随机端口和所有地址 注意:EXPOSE只是指定待暴漏端口,制作镜像运行容器后并没有真正暴漏,需要启动容器时的选项-P配合,会自动暴漏镜像中指明的要暴漏的端口 Syntax EXPOSE [/] [[/] ...]用于指定传输层协议,可为tcp或udp二者之一,默认为TCP协议 EXPOSE指令可一次指定多个端口,例如 EXPOSE 11211/udp 11211/tcp ENV: 用于为镜像定义所需的环境变量,并可被Dockerfile文件中位于其后的其它指令(如ENV、ADD、COPY等)所调用 调用格式为$variable_name或${variable_name} Syntax ENV 或 ENV = ... 第一种格式中,之后的所有内容均会被视作其的组成部分,因此,一次只能设置一个变量; 第二种格式可用一次设置多个变量,每个变量为一个"="的键值对,如果中包含空格,可以以反斜线(\)或引号进行转义,也可通过对加引号进行标识;另外,反斜线也可用于续行;定义多个变量时,建议使用第二种方式,以便在同一层中完成所有功能 可以启动镜像容器时直接赋值,但只是在启动过程中赋予变量值,已经编译好的镜像无法改变,示例: docker container run --name web -e DIR="/usr/src/" cuijian/nginx:v0.1CMD与RUN: 补充知识: (1)shell进程:只有运行在shell子进程下的程序才能使用shell相关命令【例如:通配符*管道|】,这些进程都与终端相关联,终端退出shell就会退出,其中运行在shell子进程下的程序也会停止,所以可以使用nohup把父进程shell替换成init从而脱离终端限制 (2)守护进程:与终端无关,由父进程ini管理并且都会存在于/etc/rc.d下可以由system启动的进程 注意:json数组中,要使用双引号RUN: 当基于Dockerfile制作镜像时执要运行的命令(注意必须在基础镜像中支持这个命令)有多个命令可以用&&符号,将在docker build时运行 ,注意:CMD是设置镜像的默认启动命令,启动时给run传递启动命令参数可以把CMD覆盖; Syntax RUN 或 RUN ["", "", ""] 第一种格式中,通常是一个shell命令,且以“/bin/sh -c”来运行它,这意味着此进程在容器中的PID不为1,不能接收Unix信号,因此,当使用docker stop 命令停止容器时,此进程接收不到SIGTERM(启停)信号,(如果要设置容器PID为1可以在/bin/sh 下直接执行exec )而这种格式启动的容器,为了能接收容器外的停启信号会在启动时自动在容器中执行exec命令,所以在容器外能查看到是/bin/sh启动的子进程,容器中只能看到启动的程序PID为1的进程是子进程本身,而不能看到/bin/bash这个父进程 第二种语法格式中的参数是一个JSON格式的数组,其中为要运行的命令,后面的【docker|docker详解】为传递给命令的选项或参数;然而,此种格式指定的命令不会以“/bin/sh -c”来发起,因此常见的shell操作如变量替换以及通配符(?,*等)替换将不会进行;不过,如果要运行的命令依赖于此shell特性的话,可以将其替换为类似下面的格式。RUN ["/bin/bash", "-c", "", ""]CMD 是用于定义把镜像启动为容器时指定默认要运行的程序或命令,可以启动时使用命令docker container run后加启动命令来取代默认运行命令 在Dockerfile中可以存在多个CMD指令,但仅最后一个会生效 Syntax CMD 或 CMD ["", "", ""]或 CMD ["",""] 前两种语法格式的意义同RUN 第三种则用于为ENTRYPOINT指令提供默认参数ENTRYPOINT: 类似CMD指令的功能,用于为容器指定默认运行程序,从而使得容器像是一个单独的可执行程序与CMD不同的是,由ENTRYPOINT启动的程序不会被docker run命令行指定的参数所覆盖,而且,这些命令行参数会被当作参数传递给ENTRYPOINT指定指定的程序不过,docker run命令的--entrypoint选项的参数可覆盖ENTRYPOINT指令指定的程序 Syntax ENTRYPOINT ENTRYPOINT ["", "", ""] docker run命令传入的命令参数会覆盖CMD指令的内容并且附加到ENTRYPOINT命令最后做为其参数使用 Dockerfile文件中也可以存在多个ENTRYPOINT指令,但仅有最后一个会生效 注意:如果CMD与ENTRYPOINT同时存在,那么CMD会被当做ENTRYPOINT的默认参数,如果这时在命令行传递参数会覆盖CMD 示例1: CMD ["/bin/httpd","-f","-h" ${WEB_ROOT}] ENTRYPOINT ["/bin/sh","-c"] 实际启动容器的进程为: /bin/sh -c "/bin/httpd -f -h /date/root/" 示例2:设置一个模板并可以在启动时传变量 先准备一个可以生成配置文件的脚本 vim entrypoint.sh #!/bin/bash cat > /etc/nginx/conf.d/www.conf << EOF server { server_name ${HOSTNAME}; listen ${IP:-0.0.0.0}:${port:-80}; root ${ROOT:-/usr/share/nginx/html}; } EOFexec "$@"再准备一个静态页面 echo "HELLOW" >index.html 然后开始编写Dockerfile vim Dockerfile FROMnginx:1.14-alpine LABEL maintainer='CJ ' ENV ROOT='/data/web/html/' ADD index.html ${ROOT} ADD entrypoint.sh /bin/ CMD ["/usr/sbin/nginx","-g","daemon off; "] (注释:-g为global:全局变量daemon off 为放在前台) ENTRYPOINT["/bin/entrypoint.sh"]最后编译成镜像然后启动时赋予变量参数 docker image build-t myweb:v0.1-1 ./ docker run --name myweb --rm -P -e "PORT=8080" myweb:v0.1-1USER 用于指定运行image时的或运行Dockerfile中任何RUN、CMD或ENTRYPOINT指令指定的程序时的用户名或UID默认情况下,container的运行身份为root用户 Syntax USER | 需要注意的是,可以为任意数字,但实践中其必须为/etc/passwd中某用户的有效UID,否则,docker run命令将运行失败HEALTHCHECK健康状态检测 HEALTHCHECK可以定义一个CMD用来检查容器是否仍然正常运行。 HEALTHCHECK指令有两种形式: HEALTHCHECK [OPTIONS] CMD命令(通过在容器内运行一个命令来检查容器健康状况,可以定义时间间隔) HEALTHCHECK NONE(禁止健康状态检测) options: --interval=DURATION (default: 30s) --timeout=DURATION (default: 30s) --start-period=DURATION (default: 0s) 容器启动后多长时间(容器初始化完成后)开始进行健康状态检测 --retries=N (default: 3) 检测多少次失败后触发失败操作 返回状态: 0: success 1: unhealthy不健康的 For example HEALTHCHECK --interval=5m --timeout=3s CMD curl -f http://localhost/ I| exit 1SHELL 设置运行shell时的解释器,Linux系统默认为["/bin/sh", "-c"],Windows系统默认为["cmd", "/S", "/C"] SHELL在Dockefile中必须写成JSON格式 Syntax: SHELL ["executable", "parameters"] 可以多次,会覆盖之前的SHELL并影响后续指令STOPSIGNAL 修改容器的停止信号 Syntax:STOPSIGNAL signalARG ARG定义了一个变量类似于ENV,区别在于可以通过构建镜像命令参数--build-arg = flag在构建时传递变量 示例:默认maintainer="MageEdu ",传参后maintainer="CJ " vim Dockefile ARG author="MageEdu " LABEL maintainer=$uthor docker image build --build-arg author="CJ "-t nginx:v0.1-1 ./ ONBUILD 用于在Dockerfile中定义一个触发器,当Dockerfile中定义了ONBUILD,自己在构建镜像时不会被执行,但当在拿这个 Syntax ONBUILD 尽管任何指令都可注册成为触发器指令,但ONBUILD不能自我嵌套,且不会触发FROM和MAINTAINER指令 使用包含ONBUILD指令的Dockerfile构建的镜像应该使用特殊的标签,例如ruby:2.0-onbuild 在ONBUILD指令中使用ADD或COPY指令应该格外小心,因为新构建过程的上下文在缺少指定的源文件时会失败

Private Registry
Docker Distribution (比较简陋) yum-y install docker-registry 修改registry配置(也可以用默认配置) vim /etc/docker-distribution/registry/config.yml 启动 systemctl start docker-distribution 客户端(docker配置文件)配置为可以使用不安全的registry,因为默认只能使用https协议,配置为可以使用不安全的registry后可以支持http协议 vim /etc/docker/daemon.json { "insecure-registries":["10.0.0.2:5000"] } 修改完需重启服务 systemctl restart docker 打标签 docker image tag nginx:v0.3-11 10.0.0.2:5000/nginx:v0.3-11 推送: docker image push nginx:v0.3-11 10.0.0.2:5000/nginxvmware harbor Harbor官方网站:http://vmware.github.io/harbor/ Harbor源码地址:https://github.com/vmware/harbor Harbor简介 Harbor是一个用于存储和分发Docker镜像的企业级Registry服务器,通过添加一些企业必需的功能特性,例如安全、标识和管理等,扩展了开源Docker Distribution。作为一个企业级私有Registry服务器,Harbor提供了更好的性能和安全。提升用户使用Registry构建和运行环境传输镜像的效率。Harbor支持安装在多个Registry节点的镜像资源复制,镜像全部保存在私有Registry中, 确保数据和知识产权在公司内部网络中管控。另外,Harbor也提供了高级的安全特性,诸如用户管理,访问控制和活动审计等。 Harbor的功能 基于角色的访问控制:用户与Docker镜像仓库通过“项目”进行组织管理,一个用户可以对多个镜像仓库在同一命名空间(project)里有不同的权限。 镜像复制:镜像可以在多个Registry实例中复制(同步)。尤其适合于负载均衡,高可用,混合云和多云的场景。 图形化用户界面:用户可以通过浏览器来浏览,检索当前Docker镜像仓库,管理项目和命名空间。 AD/LDAP:-Harbor可以集成企业内部已有的AD/LDAP,用于鉴权认证管理。 审计管理:所有针对镜像仓库的操作都可以被记录追溯,用于审计管理。 国际化:已拥有英文、中文、德文、日文和俄文的本地化版本。更多的语言将会添加进来。 RESTful API: 提供给管理员对于Harbor更多的操控, 使得与其它管理软件集成变得更容易。 部署简单:提供在线和离线两种安装工具, 也可以安装到vSphere平台(OVA方式)虚拟设备。 vmware harbor 需要基于docker单机编排工具 docker compose 安装: 下载并解压包 wget https://github.com/goharbor/harbor/releases/download/v2.5.2/harbor-offline-installer-v2.5.2.tgz tar -xvf harbor-offline-installer-v2.5.2.tgz cd harbor 编辑配置文件 vim harbor.cfg 安装并启动 yum -y install docker-compose ./install.sh 访问页面 初始密码 admin/Harbor12345 同Distribution docker 配置非安全端口并重启 镜像打tag 登录: docker login 推送 停止/启动 docker-compose --help 查看 需要在docker-compose.yml 所在目录中执行

Docker 资源限制
docker容器默认没有资源限制,可以使用宿主机上所有资源 memory: 调整了docker daemon 的OOM优先级但未调整容器的,这就导致主机内存耗尽时可能会kill占用内存较多的容器,可以在容器启动时限制容器资源: docker container run Options: 内存限制: -m, --memory bytesMemory limit --memory-swap bytes要限制swap使用大小前提必须先限制内存使用大小 --memory与--memory-swap 结合起来用有四种情况: --memory-swap为正数S;--memory为正数M;则容器可用总空间为S,其中ram(可用物理内存)为M,swap为S-M,若S=M则无可用swap --memory-swap为0;--memory为正数M;相当于未设置swap(unset) --memory-swap为unset;--memory为正数M;若主机(Docker Host)启用了swap,则容器可用swap为2*M --memory-swap为-1(无限大);--memory为正数M;若主机(Docker Host)启用了swap,则容器可使用主机上的所有swap资源 注意:容器内使用free命令显示的swap没有意义 --oom-kill-disable True 在主机内存耗尽时禁止kill此容器,提前需要有-m选项 --oom-score-adj intTune host's OOM preferences (-1000 to 1000) (补充:Docker host系统内存资源不足时。OOM killer 给进程打分,把 oom_score 最大的进程先杀死,打分主要有两部分组成: 一是系统根据该进程的内存占用情况打分,进程的内存开销是变化的,所以该值也会动态变化。 二是用户可以设置的 oom_score_adj,范围是 -1000到 1000,所以数值越小越不容易被杀死,默认为0设定成 -1000,表示禁止OOM killer 杀死该进程 )cpu限制 (补充: 优先级NICE: 进程的优先级为100-139,默认NICE为0也就是优先级为120,可以把NICE在-20,19直接进行调整 内核优先级为0,99 ) -c, --cpu-shares intCPU shares (relative weight)设置CPU弹性共享比例,例如一个容器配置为512,另一个为1024,他们所分配的cpu资源为1比2,当然是弹性的:例如如果一个容器在空闲中,另一个容器就可以使用所有资源 --cpus=数值可以是正数也可以是小数 --cpuset-cpus stringCPUs in which to allow execution (0-3, 0,1)限制容器用在哪个cpu核心上

    推荐阅读