前言
因为开发过程中各种环境的部署是一件让人非常头疼的事情,所以容器技术一直是笔者比较感兴趣的技术领域,工作之余找到了一本国人写的容器好书 每天5分钟玩转Docker容器技术,书名看起来比较不靠谱,实际在豆瓣评分中高居前列,评论也纷纷表扬该书是本入门的好书。这系列文章是该书的读书笔记。笔者主要以 问题和解答 作为读书笔记的写作形式,这样可以方便大家准备面试。
容器
- 除了Docker以外,你了解容器的生态系统吗?简单介绍容器的生态系统中都有哪些部分,各自的作用?
容器生态系统包含三大部分:
- 容器核心技术(class字节码协议,JVM运行时环境,java命令行工具,maven仓库,pom文件)
- 容器规范:保证不同厂家开发的容器能够彼此兼容,可以理解为class字节码协议
- 容器runtime:runtime需要跟操作系统合作,为容器提供运行时环境,可以理解为JVM
- 容器管理工具:对内与runtime进行交互,对外与用户进行交互,可以理解为java命令,可以启停应用
- 容器定义工具: 有了容器定义工具,容器就可以被保存共享和重建。
- Registry:容器是通过image构建的,registry就是一个存放各种image的仓库,类似maven仓库
- 容器OS:专门运行容器的操作系统,以提高容器的运行效率。
- 容器平台技术:使容器作为集群在分布式环境下运行
- 容器编排引擎:微服务架构中可以动态弹性的管理容器集群的服务,kubernates
- 容器管理平台:在具体的编排引擎之上的更抽象的层次,屏蔽了底层的不同的编排引擎,为用户提供更加易用的接口。
- 基于容器的PaaS:为企业提供基于容器的开发部署和管理平台
- 容器支持技术
- 容器网络:负责容器与容器之间,容器与其他实体之间的网络连通性和隔离性
- 服务发现和数据管理:这两项都是因为集群的动态伸缩,容器不断地迁移引发的需求
- 日志、监控:基础的运维功能
- 安全性:容器的潜在漏洞
- 容器和虚拟机的共同点和区别是什么?
共同点:两者都为应用提供封装和隔离的运行环境
不同点:
- 传统的虚拟化技术,除了安装应用和依赖以外,还需要安装整个操作系统
- 容器是宿主机的一个进程,与其他进程隔离,因为不需要安装整个操作系统,所以体积更小,部署和启动速度更快,更易迁移。
- 容器的优势是什么?
- 对于开发人员:Build Once,Run Anywhere,容器使得开发人员只需要为应用创建一次运行环境打包成容器后就可以在其他机器上运行。
- 对于运维人员:Configure Once,Run Anything,容器使得运维人员只需要配置一次基础环境,就可以运行任意的容器。
- Docker的架构你了解吗?简单说说
Docker采用的是client/server架构,客户端向服务端发送请求,服务端负责构建运行和分发容器。客户端和服务端可以运行在同一个host中,也可以运行在不同的host中,客户端通过socket或者REST API和服务端通信。
Docker中有以下的核心组件:
- Docker客户端
- Docker daemon
- container容器
- image镜像
- registry镜像仓库
- 什么是Docker的镜像?镜像有什么作用?
镜像是Docker容器的基石,有了镜像才能启动容器,容器是镜像的运行实例。 - 什么是base镜像?
- 不依赖其他镜像,从scratch创建
- 其他镜像可以以此为基础进行扩展
一般被称作base镜像的都是Linux发行版的docker镜像。
- 看下面的镜像列表,为什么一个centos的镜像只有200多M?我们平时安装操作系统不是很大吗?
REPOSITORY TAG IMAGE ID CREATED SIZE
centos latest 0d120b6ccaa8 2 months ago 215MB
Linux的操作系统由rootfs和bootfs组成,bootfs是内核空间的文件系统,rootfs是用户空间的文件系统,对于base镜像来说,底层直接使用Host的kernel,自己只需要提供rootfs就可以了。
- 在容器中是否可以对kernel进行升级?
不可以,因为所有的容器公用同一个host的kernel,所以在容器中无法升级kernel。如果容器对kernel版本有要求,那么不建议用容器,应该用虚拟机实现。 - 镜像分层的作用是什么?
镜像分层指的是可以通过类似继承的方式,从另外一个镜像开始构建自定义镜像,目的就是为了共享。 - 通过镜像分层共享镜像后,不同容器对同一个共享镜像的修改会影响彼此吗?
不会。
当容器启动后,一个可写的容器层被加载到镜像的顶部。所有的增删改操作都发生在可写的容器层,镜像层都是只读的。简单理解就是容器层留有镜像层的副本,所有的操作也只修改自己的副本。 - 构建镜像都有什么方式?你推荐使用哪种方式?
- docker commit的方式:这种方式需要手动启动容器,再容器内部做一些修改,然后再commit
- Docker file的方式:Docker file的方式是通过编写构建指令到一个文本文件,然后docker会帮我们自动构建,它底层用的也是docker commit,针对每一层镜像,都会启动一个临时容器,然后commit。
- 推荐使用Docker file的方式,因为自动嘛
- 如果使用 Docker file,具体构建的指令是什么?
首先创建好docker file,然后通过下面的指令,指定新镜像的名称和dockerfile所在的build context路径即可。
udo docker build -t ubuntu-withvim .
- 你知道镜像的缓存特性吗?
了解。
Docker会缓存已有的镜像层,构建镜像时,如果镜像层已经存在,就会直接使用,无需重新创建。
ging@ubuntu:~/dockerfile$ sudo docker build -t ubuntu-withvim-cache .
[sudo] password for ging:
Sending build context to Docker daemon 2.56kB
Step 1/3 : FROM ubuntu
---> d70eaf7277ea
Step 2/3 : RUN apt-get update && apt-get install -y vim
---> Using cache
---> 8f3d13a6f3c8
Step 3/3 : COPY testfile.txt /
---> cfa8a6fa3fb3
Successfully built cfa8a6fa3fb3
Successfully tagged ubuntu-withvim-cache:latest
- 为什么在Docker file中安装应用,需要写成 RUN apt-get update && apt-get install vim呢?分开成两行写不可以吗?
可以分开成两行写,但是分成两行写,RUN apt-get update这行可能使用很久之前的缓存镜像,导致无法安装到最新的软件。 - CMD指令和ENTRYPOINT指令有什么区别?
- CMD:容器启动后的默认执行指令,如果run命令行中指定了其他的指令,CMD就不会执行。
Dockerfile如下:
FROM ubuntu
CMD ["/bin/echo","Hello World!"]
如果用下面的命令执行,执行后会打印一行Hello World,然后容器就会退出。(退出的原因是,容器的生命周期依存于主应用的生命周期,这个test中主应用是echo,打印完毕后主应用就执行完毕了,所以容器也会退出)
sudo docker run -it ubuntu-cmdtest
- ENTRY:和CMD一样,也可以用于执行指令,并且是一定会被执行。
- exec格式的指令,可以使用CMD来传递参数,并且docker run中指定的参数会动态替换CMD中的参数
- shell格式的指令,会忽略CMD和run中传递过来的参数。