《微服务架构实战》读书笔记四----Docker
文章目录
《微服务架构实战》读书笔记四----Docker
Docker原理
Docker是一个客户端-服务端(C/S)架构的程序,Docker客户端只需要向Docker服务端或守护进程发出请求,服务器或守护进程将完成所有工作并返回结果。Docker提供了一个命令行工具Docker及一整套RESTful API 可以在同一台宿主机器上运行Docker守护进程和客户端,也可以从本地的Docker客户端连接到运行在另一台宿主机远程的Docker守护进程
Docker依赖的Linux的内核特性包括Namespaces命名空间和Control groups控制组。
Namespace命名空间
- PID 进程ID隔离
- NET 管理网络端口
- IPC 进程间通信
- 管理跨进程通信的访问
- MNT 管理挂载点
- UTS 隔离内核和版本标识
- Control groups 控制组
Control groups控制组
- 资源限制
- 优先级设定
- 资源度量
- 资源控制及资源分配
Docker 容器的能力包括
- 文件系统隔离----每个容器都在自己的root文件系统,可以独立挂载外部文件系统
- 进程隔离----每个容器都运行在自己的进程环境中,相互之间互不干扰
- 网络隔离----容器间的虚拟网络接口和IP地址都是分开的
- 资源隔离和分钟----使用Control groups将CPU和内存等资源独立分配给每个Docker容器
更轻量级的虚拟化
Docker 项目的目标是实现轻量级的操作系统虚拟化解决方案
虚拟机的架构
- 基础设施:一般是服务器或者云主机
- 虚拟机管理系统:利用Hypervisor,可以在主操作系统之上运行多个不同的从操作系统,可以构建在基础设施之上,也可以构建在操作系统上
- 客户端操作系统:假设运行3个相互隔离的应用,则需要用Hypervisor启动3个客户机操作系统,也就是3个虚拟机,这些虚拟机都非常大
- 各种依赖:每一个客户机操作系统都需要安装许多依赖
- 应用:安装依赖后,就可以在各个客户机操作系统分别运行应用了,这样各个应用就是相互隔离的
Docker架构
- 基础设施
- 主操作系统:所有主流的系统都行对Docker支持
- Docker守护进程:Docker守护进程代替了Hypervisor,它是运行在操作系统之上的后台进程,负责管理Docker容器
- 各种依赖:对于Docker,应用的所有依赖都打包在Docker镜像中,Docker容器是基于Docker镜像创建的
- 应用:应用的源代码与它的依赖度打包在Docker镜像中,不同的应用需要不同的Docker镜像,不同的应用运行在不同的Docker容器中,它们是相互隔离的
虚拟机和Docker对比
- Docker容器可以秒级启动
- Docker对系统资源利用高,一台主机可以运行千个Docker容器
- 容器除了应用,基本不消耗额外系统资源,所使用资源完全是使用宿主机上的资源
- 传统虚拟机10个应用要10个虚拟机,而Docker只需要10个隔离应用
- Docker可以跨平台,不需要额外操作系统支持
三个概念理解Docker
Docker有三个概念,镜像、容器和仓库
我们可以从镜像仓库把镜像下载到本地,然后将镜像启动就能创建一个容器
Docker之所以这么吸引人,除了新颖的技术,在官方的Registry的生态圈也是相当吸引人球的地方,在Docker Hub中可以下载大量容器化好的应用镜像
Dockerfile 定制一切
Docker为我们提供一套非常强大的语法,可以利用简单的编写程序构建出任何你想要的环境,同时可以跟业务代码相结合,快速构建和生成所需要的应用
Dockerfile用来创建一个自定义的Image,包含了用户指定的软件依赖等,使用Docker的build命令可以直接构建新的Image,它简化了从头到尾的流程并极大地简化了部署工作
Dockerfile命令
FROM
FROM命令可能是最重要的Dockerfile命令,此命令定义了使用哪个基础镜像启动构建流程,基础镜像可以为任意镜像,如果基础镜像没有被发现,则Docker将试图从Docker image index来查找该镜像
格式为 FROM image 或者 FROM image tag
第一条指令必须是FROM指令,并且在同一个Dockerfile中创建多个镜像时,可以使用多个FROM命令
MAINTAINER
格式为MAINTAINER name,指定维护者信息,其实就是类似javadoc注释中的@author,用户声明作者,一般都放在文件比较靠上的位置
RUN
从名称上就可以看出,RUN是执行或运行的意思
格式为RUN command 或 RUN [“executable”,“paraml”,“param2”]
前者将在Shell终端中运行命令,即/bin/sh -c; 后者则使用exec执行。指定使用其他终端可以通过第二种方式实现,例如,RUN ["/bin/bash","-c",“echo hello”]
每条RUN指令将在当前镜像基础上执行指定命令,并提交为新镜像。当命令较长时可以使用“\”来换行
EXPOSE
格式EXPOSE port
告诉Docker服务端容器暴露的端口号
CMD
支持格式有三种
CMD [“executable”,“param1”,“param2”] 使用exec执行
CMD command param1 parma2 在/bin/sh,提供给需要交互的应用
CMD [“param1”,“param2”] 提供给ENTRYPOINT的默认参数
指定启动容器时执行的命令,每个Dcokerfile只能有一条CMD命令,如果指定了多条命令,则只有最后一条会被执行
如果用户启动容器时指定了运行的命令,则会覆盖CMD指定的命令
ENTRYPOINT
两种格式
ENTRYPOINT [“executeable”,“param1”,“param2”]
ENTRYPOINT command,param1,param2
配置容器启动后执行的命令,并且不可被Docker RUN 提供的参数覆盖
每个Dockerfile中只能有一个ENTRYPOINT,当指定多个时,只有最后一个生效
ENV
格式为ENV key value 指定一个环境变量,会被后续RUN指令使用,并在容器运行时保持
ADD
格式为 ADD src dest
该命令将复制指定的src到容器中的dest,其中src可以是Dockerfile所在目录的一个相对路径,也可以是一个URL,还可以是一个tar文件
COPY
格式为COPY src dest
复制本地主机的 src到容器中的dest
当使用本地目录为源目录时,推荐使用COPY
VOLUME
格式为VOLUME["/data"]
创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保存的数据等
WORKDIR
格式为WORKDIR /path/to/workdir
为后续的RUN、CMD、ENTRYPOINT指令配置工作目录
可以使用多个WORKDIR指令,后续命令如果参数是相对路径,则会基于之前命令指定路径
例如:
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
最终路径为 /a/b/c
USER
格式为USER daemon
指定运行容器时的用户名或者UID,后续的RUN也会使用指定用户。
当服务不需要管理员权限的时候,可以通过该命令指定运行用户,并且可以在之前创建所需要的用户,例如,RUN groupadd -r postgres && useradd -r -g postgres postgres 要临时获取管理员权限可以使用gosu,而不推荐sudo
ONBUILD
格式为ONBUILD [INSTRUCTION]
配置当前创建镜像作为其他新创建镜像的基础镜像的基础镜像时,所执行的操作指令
Dockerfile构建过程
Dockerfile其实可以看做一个命令集,每行第一个均为一条命令,每行第一个单词就是命令,后面的字符串是该命令所有接收的参数
docker build的流程
- 提取Dockerfile(evaluator.go/RUN)
- 将Docker按行进行分析(parse/parser.go/Parse),每行第一个单词叫做command,根据command对之后的字符串进行解析
- 根据分析的command,在dispatchers.go中选择对应的函数进行处理(dispatchers.go)
- 处理完所有的命令,如果需要打标签,则给最后的镜像打上tag,结束
Dockerfile逆向
通过docker history image 可以看到该镜像的历史来源,即使没有Dockerfile 也可以通过history来逆向产生Dockerfile