1.基础篇 1.1.容器虚拟化技术 Docker容器是在操作系统层面上实现虚拟化,直接复用本地主机的操作系统,而传统虚拟机则是在 硬件层面实现虚拟化。与传统的虚拟机相比,Docker优势体现为启动速度快、占用体积小 比较了Docker和传统虚拟化方式的不同之处: *传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用 进程 *容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核且也没有进行硬件虚拟,因此 容器要比传统虚拟机更为轻便 *每个容器之间互相隔离,每个容器有自己的文件系统 ,容器之间进程不会相互影响,能区分计算 资源 1.2.一次构建、处处运行 1.2.1.更快速的应用交付和部署 传统的应用开发完成后,需要提供一堆安装程序和配置说明文档,安装部署后需根据配置文 档进行繁杂的配置才能正常运行 Docker化之后只需要交付少量容器镜像文件,在正式生产环境加载镜像并运行即可,应用安 装配置在镜像里已经内置好,大大节省部署配置和测试验证时间 1.2.2.更便捷的升级和扩缩容 随着微服务架构和Docker的发展,大量的应用会通过微服务方式架构,应用的开发构建将变 成搭乐高积木一样,每个Docker容器将变成一块“积木”,应用的升级将变得非常容易。当现 有的容器不足以支撑业务处理时,可通过镜像运行新的容器进行快速 扩容,使应用系统的扩容从原先的天级变成分钟级甚至秒级 1.2.3.更高效的计算资源利用 Docker是内核级虚拟化,其不像传统的虚拟化技术一样需要额外的Hypervisor支持,所以 在一台物理机上可以运行很多个容器实例,可大大提升物理服务器的CPU和内存的利用率 1.3.Docker应用场景 Docker借鉴了标准集装箱的概念。标准集装箱将货物运往世界各地,Docker将这个模型运用到自 己的设计中,唯一不同的是:集装箱运输货物,而Docker运输软件 1.4.前提说明 Docker并非是一个通用的容器工具,它依赖于已存在并运行的Linux内核环境。Docker实质上是 在已经运行的Linux下制造了一个隔离的文件环境,因此它执行的效率几乎等同于所部署的Linux 主机。因此,,Docker必须部署在Linux内核的系统上。如果其他系统想部署Docker就必须安装一 个虚拟Linux环境 目前,CentOS 仅发行版本中的内核支持 Docker。Docker 运行在CentOS 7 (64-bit)上, 要求系统为64位、Linux系统内核版本为 3.8以上,这里选用Centos7.x 1.5.Docker的基本组成 a.镜像 Docker 镜像(Image)就是一个只读的模板。镜像可以用来创建 Docker 容器,一个镜像 可以创建很多容器。它也相当于是一个root文件系统。比如官方镜像 centos:7 就包含了 完整的一套 centos:7 最小系统的 root 文件系统相当于容器的“源代码”,docker镜像文 件类似于Java的类模板,而docker容器实例类似于java中new出来的实例对象 b.容器 1 从面向对象角度 Docker 利用容器(Container)独立运行的一个或一组应用,应用程序或服务运行在容器 里面,容器就类似于一个虚拟化的运行环境,容器是用镜像创建的运行实例。就像是Java 中的类和实例对象一样,镜像是静态的定义,容器是镜像运行时的实体。容器为镜像提供 了一个标准的和隔离的运行环境,它可以被启动、开始、停止、删除。每个容器都是相互 隔离的、保证安全的平台 2 从镜像容器角度 可以把容器看做是一个简易版的 Linux 环境(包括root用户权限、进程空间、用户空间 和网络空间等)和运行在其中的应用程序 c.仓库 仓库(Repository)是集中存放镜像文件的场所。类似于Maven仓库,存放各种jar包的地方 github仓库,存放各种git项目的地方;Docker公司提供的官方registry被称为Docker Hub 存放各种镜像模板的地方 仓库分为公开仓库(Public)和私有仓库(Private)两种形式。 最大的公开仓库是 Docker Hub(https://hub.docker.com/), 存放了数量庞大的镜像供用户下载。国内的公开仓库包括阿里云 、网易云等 d.总结 需要正确的理解仓库/镜像/容器这几个概念: Docker 本身是一个容器运行载体或称之为管理引擎。我们把应用程序和配置依赖打包好形成 一个可交付的运行环境,这个打包好的运行环境就是image镜像文件。只有通过这个镜像文件 才能生成Docker容器实例(类似Java中new出来一个对象)image文件可以看作是容器的模板。 Docker 根据 image 文件生成容器的实例。同一个 image 文件,可以生成多个同时运行的 容器实例 镜像文件 * image 文件生成的容器实例,本身也是一个文件,称为镜像文件 容器实例 * 一个容器运行一种服务,当我们需要的时候,就可以通过docker客户端创建一个对应的 运行实例,也就是我们的容器 仓库 *就是放一堆镜像的地方,我们可以把镜像发布到仓库中,需要的时候再从仓库中拉下来就 可以了 e.Docker工作原理 Docker是一个Client-Server结构的系统,Docker守护进程运行在主机上,然后通过Socket 连接,从客户端访问,守护进程从客户端接受命令并管理运行在主机上的容器。容器,是一 个运行时环境,就是我们前面说到的集装箱 1.6.Docker常用命令 a.docker启动类命令 启动docker: systemctl start docker 停止docker: systemctl stop docker 重启docker: systemctl restart docker 查看docker状态: systemctl status docker 开机启动: systemctl enable docker 查看docker概要信息: docker info 查看docker总体帮助文档: docker --help 查看docker命令帮助文档: docker 具体命令--help b.镜像命令 1.docker images :列出本地主机上的镜像 各个选项说明: REPOSITORY TAG IMAGE ID CREATED SIZE 表示镜像的仓库源 镜像的标签版本号 镜像ID 镜像创建时间 镜像大小 同一仓库源可以有多个 TAG版本,代表这个仓库源的不同个版本,我们使用 REPOSITORY:TAG来 定义不同的镜像如果你不指定一个镜像的版本标签,例如你只使用ubuntu, docker将默认使用ubuntu:latest 镜像 2.docker search [OPTIONS] 镜像名字 (一般pull点赞数量最多的就行) OPTIONS说明:--limit :只列出N个镜像默认25个;docker search --limit 5 redis NAME DESCRIPTION STARS OFFICIAL AUTOMATED 镜像名称 镜像说明 点赞数量 是否是官方的 是否是自动构建的 3.docker pull 镜像名字[:TAG] 没有TAG就是最新版 等价于 docker pull镜像名字:latest(docker pull ubuntu) 4.docker system df 查看镜像/容器/数据卷所占的空间 5.docker rmi -f 镜像ID c.容器命令 1.新建+启动容器 docker run [OPTIONS] IMAGE [COMMAND][ARG...] PTIONS说明(常用):有些是一个减号,有些是两个减号 --name="容器新名字" :为容器指定一个名称; -d: 后台运行容器并返回容器ID,也即启动守护式容器(后台运行); -i:以交互模式运行容器,通常与 -t 同时使用; -t:为容器重新分配一个伪输入终端,通常与 -i 同时使用; 也即启动交互式容器(前台有伪终端,等待交互); -P: 随机端口映射,大写P -p: 指定端口映射,小写p docker run -it centos /bin/bash 参数说明: -i: 交互式操作。 -t: 终端。 centos : centos镜像 /bin/bash:放在镜像名后的是命令,这里我们希望有个交互式Shell, 因此用的是/bin/bash。要退出终端,直接输入exit: 2.列出当前所有正在运行的容器 :docker ps [OPTIONS] OPTIONS说明(常用): -a :列出当前所有正在运行的容器+历史上运行过的 -l :显示最近创建的容器 -n:显示最近n个创建的容器 -q :静默模式,只显示容器编号 3.退出容器 exit————run进去容器,exit退出,容器停止 ctrl+p+q———run进去容器,ctrl+p+q退出,容器不停止 4.启动已停止运行的容器:docker start容器ID或者容器名 5.重启容器———docker restart 容器ID或者容器名 6.停止容器—一——docker stop 容器ID或者容器名 7.强制停止容器———docker kill 容器ID或容器名 8.删除已停止的容器———docker rm 容器ID 9.重点东西 9.1.有镜像才能创建容器,这是根本前提(下载一个Redis6.0.8镜像演示) 9.2启动守护式容器(后台服务器) 在大部分的场景下,我们希望docker的服务是在后台运行的,我们可以过-d指定 容器的后台运行模式,docker run -d 容器名 redis前后台启动演示case: 前台交互式启动:docker run -it redis:6.0.8 后台守护式启动:docker run -d redis:6.0.8 9.3.查看容器日志:docker logs 容器ID 9.3.查看容器内运行的进程: docker top 容器ID 9.4.查看容器内部细节:docker inspect 容器ID 9.5.进入正在运行的容器并以命令行交互 docker exec -it 容器ID /bin/bash 重新进入 docker attach 容器ID 案例演示,用centos或者unbuntu都可以 attach直接进入容器启动命令的终端,不会启动新的进程用exit退出, 会导致容器的停止。 exec是在容器中打开新的终端,并且可以启动新的进程,用exit退出, 不会导致容器的停止。 推荐大家使用docker exec命令,因为退出容器终端,不会导致容器的停止 9.6.从容器内拷贝文件到主机上 容器->主机 公式:docker cp 容器ID:容器内路径 目的主机路径 eg: docker cp fa58343c4:/usr/local/my/container.txt /tmp/c.txt 9.7.导入和导出容器 export导出容器的内容留作为一个tar归档文件:docker export 容器ID >文件名.tar import 从tar包中的内容创建一个新的文件系统再导入为镜像 cat 文件名.tar | docker import - 镜像用户/镜像名:镜像版本号 1.7.Docker镜像 Docker镜像commit操作案例 docker commit 提交容器副本使之成为一个新的镜像 docker commit -m="提交的描述信息" -a="作者" 容器ID 要创建的目标镜像名:[标签名] 案例演示ubuntu安装vim 从Hub上下载ubuntu镜像到本地并成功运行 原始的默认Ubuntu镜像是不带着vim命令的 外网连通的情况下,安装vim 安装完成后,commit我们自己的新镜像 启动我们的新镜像并和原来的对比 1.8.Docker容器数据卷 a.是什么 卷就是目录或文件,存在于一个或多个容器中,卷的设计目的就是数据的持久化,完全独立于 容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷 一句话:有点类似我们Redis里面的rdb和aof文件,将docker容器内的数据保存进宿主机的磁盘 中运行一个带有容器卷存储功能的容器实例 docker run -it --privileged=true -v /宿主机 绝对路径目录:/容器内目录 镜像名 Docker挂载主机目录访问如果出现cannot open directory : Permission denied 解决办法:在挂载目录后多加一个 --privileged=true 参数即可 如果是CentOS7安全模块会比之前系统版本加强,不安全的会先禁止,所以目录挂载的情况被 默认为不安全的行为,在SELinux里面挂载目录被禁止掉了额,如果要开启,我们一般使用 --privileged=true命令,扩大容器的权限解决挂载目录没有权限的问题,也即使用该参数, container内的root拥有真正的root权限,否则,container内的root只是外部的一个普通 用户权限 b.能干嘛 将运用与运行的环境打包镜像,run后形成容器实例运行,但是我们对数据的要求希望是 持久化的Docker容器产生的数据,如果不备份,那么当容器实例删除后,容器内的数据 自然也就没有了,为了能保存数据在docker中我们使用卷 特点: 1:数据卷可在容器之间共享或重用数据 2:卷中的更改可以直接实时生效,爽 3:数据卷中的更改不会包含在镜像的更新中 4:数据卷的生命周期一直持续到没有容器使用它为止 c.数据卷案例 1.宿主vs容器之间映射添加容器卷:直接命令添加 命令:docker run -it --privileged=true -v/宿主机绝对路径目录:/容器内目录 镜像名 查看数据卷是否挂载成功:docker inspect 容器ID(查看Mounts模块) 容器和宿主机之间数据共享: 1 docker修改,主机同步获得 2 主机修改,docker同步获得 3 docker容器stop,主机修改,docker容器重启看数据是否同步 2.读写规则映射添加说明 读写(默认) docker run -it --privileged=true -v/宿主机绝对路径目录:/容器内目录:rw 镜像名 默认同上案例,默认就是rw 只读 容器实例内部被限制,只能读取不能写 docker run -it --privileged=true -v/宿主机绝对路径目录:/容器内目录:ro 镜像名 1.9.本地镜像发布到私有库 a.是什么 官方Docker Hub地址:https://hub.docker.com/,中国大陆访问太慢了且准备被阿里云 取代的趋势,不太主流 Dockerhub、阿里云这样的公共镜像仓库可能不太方便,涉及机密的公司不可能提供镜像 给公网,所以需要创建一个本地私人仓库供给团队使用,基于公司内部项目构建镜像 Docker Registry是官方提供的工具,可以用于构建私有镜像仓库 b.将本地镜像推送到私有库 1.下载镜像Docker Registry :docker pull registry 2.运行私有库Registry,相当于本地有个私有Docker hub docker run -d -p 5000:5000 -v /zzyyuse/myregistry/:/tmp/registry --privileged=true registry 默认情况,仓库被创建在容器的/var/lib/registry目录下,建议自行用容器卷映射, 方便于宿主机联调 3.案例演示创建一个新镜像,ubuntu安装ifconfig命令 4.curl验证私服库上有什么镜像: curl -XGET http://192.168.111.162:5000/v2/_catalog 5.将新镜像zzyyubuntu:1.2修改符合私服规范的Tag 按照公式: docker tag 镜像:Tag Host:Port/Repository:Tag 使用命令 docker tag 将zzyyubuntu:1.2 这个镜像修改为 192.168.111.162:5000/zzyyubuntu:1.2 docker tag zzyyubuntu:1.2 192.168.111.162:5000/zzyyubuntu:1.2 6.修改配置文件使之支持http 上述理由:docker默认不允许http方式推送镜像,通过配置选项来取消这个限制。 ====> 修改完后如果不生效,建议重启docker vim命令新增如下insecure-registries内容:vim /etc/docker/daemon.json registry-mirrors 配置的是国内阿里提供的镜像加速地址,不用加速的话访问官网的 会很慢,2个配置中间有个逗号 ','别漏了,这个配置是json格式的 { "registry-mirrors": ["https://aa25jngu.mirror.aliyuncs.com"], "insecure-registries": ["192.168.111.162:5000"] } 7. push推送到私服库:docker push 192.168.111.162:5000/zzyyubuntu:1.2 8.curl验证私服库上有什么镜像: curl -XGET http://192.168.111.162:5000/v2/_catalog 9.pull到本地并运行:docker pull 192.168.111.162:5000/zzyyubuntu:1.2 2.高级篇 2.1.DockerFile解析 a.是什么 Dockerfile是用来构建Docker镜像的文本文件,是由一条条构建镜像所需的指令和参数 构成的脚本 构建三步骤 编写Dockerfile文件 docker build 命令构建镜像 docker run 依镜像运行容器实例 b.DockerFile构建过程解析 Dockerfile内容基础知识 每条保留字指令都必须为大写字母且后面要跟随至少一个参数 指令按照从上到下,顺序执行 #表示注释 每条指令都会创建一个新的镜像层并对镜像进行提交 Docker执行Dockerfile的大致流程 docker从基础镜像运行一个容器 执行一条指令并对容器作出修改 执行类似docker commit的操作提交一个新的镜像层 docker再基于刚提交的镜像运行一个新容器 执行dockerfile中的下一条指令直到所有指令都执行完成 总结: 从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的 三个不同阶段 * Dockerfile是软件的原材料 * Docker镜像是软件的交付品 * Docker容器则可以认为是软件镜像的运行态,也即依照镜像运行的容器实例 Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维, 三者缺一不可,合力充当Docker体系的基石 Dockerfile,需要定义一个Dockerfile,Dockerfile定义了进程需要的一切东西。 Dockerfile涉及的内容包括执行代码或者是文件、 环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核 进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计 namespace的权限控制)等等; Docker镜像,在用Dockerfile定义一个文件之后,docker build时会产生一个 Docker镜像,当运行 Docker镜像时会真正开始提供服务; Docker容器,容器是直接提供服务的 2.2.Dockerfile常用保留字指令 FROM: 基础镜像,当前新镜像是基于哪个镜像的,指定一个已经存在的镜像作为模板, 第一条必须是from MAINTAINER:镜像维护者的姓名和邮箱地址 RUN: 容器构建时需要运行的命令,RUN是在docker build时运行 两种格式 shell格式:RUN <命令行命令> #<命令行命令>等同于,在终端操作的shell命令 例如: RUN yum -y install vim exec格式: RUN[“可执行文件",“参数1”,“参数2"] #例如: #RUN ["./test.php", "dev", "offline"]等价于RUN ./test.php dev offline EXPOSE: 当前容器对外暴露出的端口 WORKDIR:指定在创建容器后,终端默认登陆的进来工作目录,一个落脚点 USER:指定该镜像以什么样的用户去执行,如果都不指定,默认是root ENV:用来在构建镜像过程中设置环境变量 ENV MY_PATH /usr/mytest 这个环境变量可以在后续的任何RUN指令中使用,这就如同在命令前面指定了 环境变量前缀一样; 也可以在其它指令中直接使用这些环境变量, 比如:WORKDIR $MY_PATH ADD:将宿主机目录下的文件拷贝进镜像且会自动处理URL和解压tar压缩包: add 主机目录 容器目录 COPY: VOLUME:容器数据卷,用于数据保存和持久化工作 通过docker run命令的-v标识创建的挂载点只能对创建的容器有效。 例如:docker run -v 命令是将宿主机上面的/home/data 目录挂载到了 容器中/data目录, 无论在容器里面还是物理机中修改对应目录下面的内容,都会同步; 通过dockerfile的VOLUME指令可以在镜像中创建挂载点,这样只要通过 该镜像创建的容器都有了挂载点。 但在dockerfile中无法指定主机上对应的目录,是自动生成的 CMD:指定容器启动后的要干的事情 CMD容器启动命令,CMD指令的格式和RUN相似,也是两种格式: shell格式: CMD <命令> exec格式:CMD ["可执行文件”,"参数1","参数2”...] 参数列表格式: CMD ["参数1""参数2"...],在指定了ENTRYPOINT 指令后, 用CND指定具体的参数 注意: Dockerfile中可以有多个CMD指令,但只有最后一个生效,CMD会被 docker run之后的参数替换 参考官网Tomcat的dockerfile演示讲解 它和前面RUN命令的区别 CMD是在docker run 时运行 RUN是在docker build时运行 ENTRYPOINT: 也是用来指定一个容器启动时要运行的命令 类似于CMD指令,但是ENTRYPOINT不会被docker run后面的命令覆盖,而且 这些命令行参数会被当作参数送给ENTRYPOINT指令指定的程序 命令格式和案例说明: 命令格式:ENTRYPOINT ["<executeable>" , "<param1>" , " <param2>" ,...] ENTRYPOINT 可以和CMD一起用,一般是变参才会使用CMD ,这里的CMD等于是在 给ENTRYPOINT传参,当指定了ENTRYPOINT后,CMD的含义就发生了变化,不再是 直接运行其命令而是将CMD的内容作为参数传递给ENTRYPOINT指令, 他两个组合会变成,<ENTRYPOINT> "<CMD>" 案例如下:假设已通过Dockerfile 构建了 nginx:test镜像: FROM nginx ENTRYPOINT [ "nginx", "-c"] #定参 CMD["/etc/nginx/nginx.conf"] # 变参 是否传参 按照dockerfile编写执行 传参运行 Docker命令 docker run nginx:test docker run nginx:test -c /etc/nginx/new.conf 衍生出的实际命令 nginx -c /etc/nginx/nginx.conf nginx -c /etc/nginx/new.conf 优点: 在执行docker run的时候可以指定 ENTRYPOINT运行所需的参数 注意: 如果Dockerfile 中如果存在多个ENTRYPOINT 指令,仅最后一个生效 2.3.案列 a.自定义镜像mycentosjava8 要求:Centos7镜像具备vim+ifconfig+jdk8 JDK的下载镜像地址: https://mirrors.yangxingzhen.com/jdk/ 编写: 准备编写Dockerfile文件(Dockerfile大写字母D) FROM centos MAINTAINER zzyy<zzyybs@126.com> ENV MYPATH /usr/local WORKDIR $MYPATH #安装vim编辑器 RUN yum -y install vim #安装ifconfig命令查看网络IP RUN yum -y install net-tools #安装java8及lib库 RUN yum -y install glibc.i686 RUN mkdir /usr/local/java #ADD 是相对路径jar,把jdk-8u171-linux-x64.tar.gz添加到容器中,安装包必须 要和Dockerfile文件在同一位置 ADD jdk-8u171-linux-x64.tar.gz /usr/local/java/ #配置java环境变量 ENV JAVA_HOME /usr/local/java/jdk1.8.0_171 ENV JRE_HOME $JAVA_HOME/jre ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar: $JRE_HOME/lib:$CLASSPATH ENV PATH $JAVA_HOME/bin:$PATH EXPOSE 80 CMD echo $MYPATH CMD echo "success--------------ok" CMD /bin/bash 构建镜像: docker build -t 新镜像名字:TAG. :注意,TAG后面有个空格,有个点 运行容器: docker run -it 新镜像名字:TAG 例如:docker run -it centosjava8:1.5 /bin/bash 案例2:微服务模块的Dockerfile文件 # 基础镜像使用java FROM java:8 # 作者 MAINTAINER zzyy # VOLUME 指定临时文件目录为/tmp,在主机/var/lib/docker目录下创建了一个 临时文件并链接到容器的/tmp VOLUME /tmp # 将jar包添加到容器中并更名为zzyy_docker.jar ADD docker_boot-0.0.1-SNAPSHOT.jar zzyy_docker.jar # 运行jar包 RUN bash -c 'touch /zzyy_docker.jar' ENTRYPOINT ["java","-jar","/zzyy_docker.jar"] #暴露6001端口作为微服务 EXPOSE 6001 2.4.Docker网络 1.网路情况 docker不启动,默认网络情况:ens33 lo virbr0 docker启动后,网络情况:会产生一个名为docker0的虚拟网桥 ens33 lo 2.常用基本命令 docker network --help 查看网络:docker network ls 查看网络源数据:docker network inspect XXX 网络名字 删除网络:docker network rm XXx 网络名字 3.能干嘛 容器间的互联和通信以及端口映射 容器IP变动时候可以通过服务名直接网络通信而不受到影响 3.网络模式 3.1.总体介绍 bridge:为每一个容器分配、设置P等,并将容器连接到一个docker0虚拟网桥, 默认为该模式 host:容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口 none:容器有独立的Network namespace,但并没有对其进行任何网络设置, 如分配veth pair和网桥连接,IP等。 container:新创建的容器不会创建自己的网卡和配置自己的IP,而是和一个 指定的容器共享IP、端口范围等 bridge模式:使用--network bridge指定,默认使用dockerO host模式:使用--network host指定 none模式:使用--network none指定 container模式:使用--network container:NAME或者容器ID指定 3.2.容器实例内默认网络IP生产规则: docker容器内部的ip是有可能会发生改变的 3.3.案例说明 bridge:是docker服务创建一个桥接网络docker0,不是容器或者镜像所创建的 Docker 服务默认会创建一个docker0网桥(其上有一个docker0内部接口) 该桥接网络的名称为docker0,它在内核层连通了其他的物理或虚拟网卡, 这就将所有容器和本地主机都放到同一个物理网络。Docker默认指定了 docker0接口的IP地址和子网掩码,让主机和容器之间可以通过网桥 相互通信 说明: 1 Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥 (docker0)Docker启动一个容器时会根据Docker网桥的网段分配 给容器一个IP地址,称为Container-IP,同时Docker网桥是每个 容器的默认网关因为在同一宿主机内的容器都接入同一个网桥, 这样容器之间就能够通过容器的Container-IP直接通信 2 docker run 的时候,没有指定network的话默认使用的网桥模式就是 bridge,使用的就是docker0。在宿主机ifconfig,就可以看到docker0 和自己create的network eth0,eth1,eth2……代表网卡一,网卡二.. lo代表127.0.0.1,即localhost,inet addr用来表示网卡的IP地址 3 网桥docker0创建一对对等虚拟设备接口,一个叫veth,另一个 叫eth0,成对匹配 3.1 整个宿主机的网桥模式都是docker0,类似一个交换机有一堆 接口,每个接口叫veth,在本地主机和容器内分别创建一个虚拟 接口,并让他们彼此联通(这样一对接口叫veth pair) 3.2 每个容器实例内部也有一块网卡,每个接口叫eth0; 3.3 docker0上面的每个veth匹配某个容器实例内部的eth0, 两两配对,一一匹配 通过上述,将宿主机上的所有容器都连接到这个内部网络上,两个容器 在同一个网络下,会从这个网关下各自拿到分配的ip,此时两个容器的 网络是互通的 host:直接使用宿主机的 IP 地址与外界进行通信,不再需要额外进行NAT转换 说明:容器将不会获得一个独立的Network Namespace, 而是和宿主机 共用一个Network Namespace。容器将不会虚拟出自己的网卡而是使用 宿主机的IP和端口 警告命令:docker run -d -p 8083:8080 --network host --name tomcat83 billygoo/tomcat8-jdk8 问题: docke启动时总是遇见该命令的警告:Published ports are discarded when using host network mode 原因: docker启动时指定--network=host或-net=host,如果还指定了 -p映射端口,那这个时候就会有此警告,并且通过-p设置的参数 将不会起到任何作用,端口号会以主机端口号为主,重复时则递增 解决: 解决的办法就是使用docker的其他网络模式,例如 --network=bridge,这样就可以解决问题,或者直接无视 none: 在none模式下,并不为Docker容器进行任何网络配置,也就是说, 这个Docker容器没有网卡、IP、路由等信息,只有一个lo, 需要我们自己为Docker容器添加网卡、配置IP等,禁用网络功能, 只有lo标识(就是127.0.0.1表示本地回环) container: container⽹络模式:新建的容器和已经存在的一个容器共享一个网络ip配置 而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP, 而是和一个指定的容器共享IP、端口范围等。同样,两个容器除了网络方面 其他的如文件系统、进程列表等还是隔离的 Docker平台架构 整体说明: 从其架构和运行流程来看,Docker 是一个 C/S 模式的架构,后端是一个松耦合 架构,众多模块各司其职 Docker 运行的基本流程为: 1 用户是使用 Docker Client 与 Docker 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 容器运行资源或执行用户指令等操作时,则通过 Execdriver 来完成。 7 Libcontainer是一项独立的容器管理包,Network driver以及Exec driver 都是通过Libcontainer来实现具体对容器进行的操作。 2.5.Docker-compose容器编排 1.是什么:Docker-Compose是Docker官方的开源项目,负责实现对Docker容器集群的快速编排 Compose是Docker公司推出的一个工具软件,可以管理多个 Docker 容器组成一个应用。 你需要定义一个 YAML 格式的配置文件docker-compose.yml,写好多个容器之间的调用 关系,然后只要一个命令,就能同时启动/关闭这些容器 2.能干嘛: docker建议我们每一个容器中只运行一个服务,因为docker容器本身占用资源极少,所以 最好是将每个服务单独的分割开来,但是这样我们又面临了一个问题? 如果我需要同时部署好多个服务,难道要每个服务单独写Dockerfile然后在构建镜像, 构建容器,这样累都累死了,所以docker官方给我们提供了docker-compose多服务部署 的工具,例如要实现一个Web微服务项目,除了Web服务容器本身,往往还需要再加上 后端的数据库mysql服务容器,redis服务器,注册中心nacos,甚至还包括负载均衡 容器等等Compose允许用户通过一个单独的docker-compose.yml模板文件(YAML格式) 来定义一组相关联的应用容器为一个项目(project) 可以很容易地用一个配置文件定义一个多容器的应用,然后使用一条指令安装这个 应用的所有依赖,完成构建。Docker-Compose 解决了容器与容器之间如何管理 编排的问题 3.安装步骤: curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker- compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose docker-compose --version 4.卸载: 如果您使用curl以下方式安装,则卸载Docker Compose : $ sudo rm /usr/local/bin/ docker-compose 5.Compose核心概念: 一个文件:docker-compose.yml 服务(service):—个个应用容器实例,比如订单微服务、库存微服务、mysql容器、 nginx容器或者redis容器 工程(project):由一组关联的应用容器组成的一个完整业务单元, 在docker-compose.yml文件中定义 6.Compose使用的三个步骤 编写Dockerfile定义各个微服务应用并构建出对应的镜像文件 使用docker-compose.yml,定义一个完整业务单元,安排好整体应用中的各个容器服务 最后,执行docker-compose up命令来启动并运行整个应用程序,完成─键部署上线 7.Compose常用命令 docker-compose -h # 查看帮助 docker-compose up # 启动所有docker-compose服务 docker-compose up -d #启动所有docker-compose服务并后台运行 docker-compose down # 停止并删除容器、网络、卷、镜像 docker-compose exec yml里面的服务id #进入容器实例内部 例如:docker-compose exec docker-compose.yml文件中写的服务id /bin/bash docker-compose ps # 展示当前docker-compose编排过的运行的所有容器 docker-compose top # 展示当前docker-compose编排过的容器进程 docker-compose logs yml里面的服务id # 查看容器输出日志 docker-compose config # 检查配置 docker-compose config -q # 检查配置,有问题才有输出 docker-compose restart # 重启服务 docker-compose start # 启动服务 docker-compose stop # 停止服务 8.Compose编排微服务 1.不用compose:单独的mysql容器实例 单独的redis容器实例 微服务工程,这三个 容器实例依次顺序启动成功 2.不用compose成功了,有哪些问题? 先后顺序要求固定,先mysql+redis才能微服务访问成功 多个run命令….... 容器间的启停或宕机,有可能导致IP地址对应的容器实例变化,映射出错,要么生产 IP写死(可以但是不推荐),要么通过服务调用 3.使用compose 服务编排,一套带走 编写docker-compose.yml文件 version: "3" services: microService: image: zzyy_docker:1.6 container_name: ms01 ports: - "6001:6001" volumes: - /app/microService:/data networks: - atguigu_net depends_on: - redis - mysql redis: image: redis:6.0.8 ports: - "6379:6379" volumes: - /app/redis/redis.conf:/etc/redis/redis.conf - /app/redis/data:/data networks: - atguigu_net command: redis-server /etc/redis/redis.conf mysql: image: mysql:5.7 environment: MYSQL_ROOT_PASSWORD: '123456' MYSQL_ALLOW_EMPTY_PASSWORD: 'no' MYSQL_DATABASE: 'db2021' MYSQL_USER: 'zzyy' MYSQL_PASSWORD: 'zzyy123' ports: - "3306:3306" volumes: - /app/mysql/db:/var/lib/mysql - /app/mysql/conf/my.cnf:/etc/my.cnf - /app/mysql/init:/docker-entrypoint-initdb.d networks: - atguigu_net #解决外部无法访问 command: --default-authentication-plugin=mysql_native_password networks: atguigu_net: 4.执行docker-compose up或者执行docker-compose up -d 2.6.Docker容器监控之CAdvisor+InfluxDB+Granfana: CAdvisor监控收集+ lnfluxDB存储数据+Granfana展示图表 CAdvisor: CAdvisor是一个容器资源监控工具,包括容器的内存,CPU,网络IO,磁盘IO等监控, 同时提供了一个WEB页面用于查看容器的实时运行状态。 CAdvisor默认存储2分钟的数据,而且只是针对单物理机。不过,CAdvisor提供了 很多数据集成接口,支持InfluxDB,Redis,Kafka,Elasticsearch等集成, 可以加上对应配置将监控数据发往这些数据库存储起来 CAdvisor功能主要有两点: ·展示Host和容器两个层次的监控数据 ·展示历史变化数据 InfluxDB: InfluxDB是用Go语言编写的一个开源分布式时序、事件和指标数据库,无需外部依赖 CAdvisor默认只在本机保存最近2分钟的数据,为了持久化存储数据和统一收集展示 监控数据,需要将数据存储到InfluxDB中,InfluxDB是一个时序数据库 专门用于存储时序相关数据,很适合存储CAdvisor的数据。而且,CAdvisor本身已经 提供了InfluxDB的集成方法,丰启动容器时指定配置即可 lnfluxDB主要功能: 。基于时间序列,支持与时间有关的相关函数(如最大、最小、求和等); 。可度量性:你可以实时对大量数据进行计算; 。基于事件:它支持任意的事件数据; Granfana Grafana是一个开源的数据监控分析可视化平台,支持多种数据源配置(支持的数据源包括 InfluxDB,MySQL,Elasticsearch,OpenTSDB,Graphite等)和丰富的插件及模板功能,支持 图表权限控制和报警 Grafan主要特性: ·灵活丰富的图形化选项 可以混合多种风格 支持白天和夜间模式 多个数据源
Docker总结
最新推荐文章于 2024-09-05 14:38:09 发布