【Docker】Docker基础知识(面试一箩筐)

文章目录

一、前言

二、为什么需要Docker

2.1 工具和中间件 + 开发与运维使用Docker

工具和中间件

工具:因为Maven,所以统一依赖管理、统一项目结构
因为Git,所以版本管理、团队协作
因为Docker,所以微服务部署,容器化部署

中间件:因为mysql集群,所有读写分离、主从同步
因为消息队列,所有 异步、解耦、限流
因为redis集群 主从同步
因为高并发 后端微服务系统

Docker 是世界领先的软件容器平台,企业利用 Docker 可以更好的在 Linux 和 Windows 服务器上发布应用新功能。
开发人员利用 Docker 可以消除协作编码时“在我的机器上可正常工作”的问题,即环境不同造成重新添加依赖的问题,这是Docker的第一个功能;
运维人员利用 Docker 可以在隔离容器中并行运行和管理应用,获得更好的计算密度,即隔离应用之间资源的问题,这是Docker的第二个功能。

开发人员是否需要学习Docker?
Docker,开发人员不需要涉及(比较鸡肋):小公司不需要涉及多个环境,不需要Docker,大公司需要涉及多个环境,但是有自己的运维团队;
Docker,开发人员需要涉及:很多项目,开发完之后,就把开发人员抽调走了,然后留一个开发人员做运维,所以,开发人员会被做运维,需要使用Docker
小结:Java开发人员需要懂一些Docker的操作和原理,面试中能将出一个12345)

2.2 不使用Docker遇到的问题(同一个项目的更换一个环境运行就好重新部署好各种依赖、不同项目在同一Linux服务器上相互硬件资源和软件资源的影响)

环境(切换/配置)麻烦
一般我们写程序的,能接触到好几个环境:
开发环境:自己写代码的环境叫做开发环境。
测试环境:给测试去跑的环境叫做测试环境。
生产环境:测试完可以对外使用的叫做生产环境。
其实我们在学习编程中,很多时间都浪费在“环境”上:
如果我现在重装了系统,我想要跑我的war/jar包,我得去安装一下JDK、Tomcat、MySQL等配置各种的环境变量才能跑起来。
开开心心地跟着博主给出的步骤去写Demo,但总是有Bug。(这里我将版本/依赖也归纳在环境的范畴里边)。
好不容易在测试环境下跑起来了,在生产环境就各种出错!
跟着教学视频做分布式/集群的项目,跑一堆的虚拟机,每个虚拟机都要安装对应的环境。

应用之间需要隔离(小结:两个应用部署到同一个服务器上,硬件资源不隔离会冲突,一个应用将CPU用到100%会影响另一个应用,软件资源不隔离会冲突,一个应用的依赖可能会影响另一个应用的运行
比如我写了两个应用(网站),这两个应用部署在同一台服务器上,那可能会出现什么问题?
第一,硬件资源不隔离会冲突:如果一个应用出现了问题,导致CPU占100%。那另一个应用也会受到关联,跟着一起凉凉了。
第二,软件资源不隔离会冲突:这两个应用是完全不同技术栈的应用,比如一个PHP,一个.NET。这两个应用各种的依赖软件都安装在同一个服务器上,可能就会造成各种冲突/无法兼容,这可能调试就非常麻烦了。

2.3 Docker是如何解决上述的问题的

解决环境(切换/配置)
什么是镜像?
回答:
第一,镜像就是把想要的环境构建成一个镜像,推送到网上去:其中,你早已认识镜像了,在电脑重装系统的时候,重装windows系统需要到网上下载iso镜像,在vmware上安装centos 7.0,需要下载centos的iso镜像,有了这个镜像,我们就可以运行这个镜像,来进行安装系统的操作(此处省略N个下一步),于是我们的系统就装好了。一般来说,我们去官方渠道下载的镜像,都是纯净的。比如去官方下载Windows镜像,装完后之后桌面只有一个回收站。
第二,镜像分层的
2.1 对于安全windows系统,从系统之家下载的镜像,镜像装完可能还有360这些软件,但系统的的确确是变了。简单来说,就是这些镜像添加了其他的东西(比如360软件、腾讯、千千静听等等软件)。因为在windows镜像中家里其他东西;
2.2 对于安装centos镜像,分为最小化安装(安装完之后只能命令行)和图形化界面安装(安装完之后有图形界面),两种都是镜像,后者是对前者的加强。

上面第一点,对于windows系统和linux系统,我们只是使用别人发布在网上的镜像,下载下来使用,有了Docker,我们可以自己制作镜像了,镜像就是把想要的环境构建成一个镜像,推送到网上去
对,Docker也是这种思路,可以将我们的想要的环境构建(打包)成一个镜像,然后我们可以推送(发布)到网上去。想要用这个环境的时候,在网上拉取一份就好了。
有了Docker,我们在搭环境的时候,跟以前的方式就不一样了。
之前:在开发环境构建出了一个war包,想跑到Linux下运行。我们得先在Linux下载好Java、Tomcat、MySQL,配置好对应的环境变量,将war包丢到Tomcat的webapps文件夹下,才能跑起来。
现在:在Linux下直接从DockerHub下,拉取一份镜像(各种环境都配好了,DockerHub提供了很多镜像),将镜像运行起来,把war包丢进去就好了。将Docker的镜像运行起来就是一两秒的事情而已,十分方便。

解决应用之间隔离
说到这里,就得提出一个大家可能不认识的概念:LXC(Linux Containers)—>Linux容器。

Linux容器
第一,Linux内核,提供了cgroups功能,来达成资源的区隔;
第二,Linux内核,提供了名称空间(namespace)区隔化的功能,使应用程序看到的操作系统环境被区隔成独立区间,包括进程树,网络,用户id,以及挂载的文件系统。

小结:LXC是一个为Linux内核包含特征的用户接口。通过强大的API和简单的工具,它可以让Linux用户轻松的创建和托管系统或者应用程序容器。
问题:LXC与Docker有什么关系?
标准答案:在linux系统下,Docker就是通过lxc来实现资源隔离的。
解释:lxc是早期版本docker的一个基础组件,docker 主要用到了它对 Cgroup 和 Namespace 两个内核特性的控制。新的Docker版本已经移除了对LXC的support。

Docker在Windows和Mac
问题:在windows/mac系统下,docker如何实现资源隔离?
之前,Windows和Mac使用Docker实际上就是跑了一层Linux虚拟机。
比如在Windows下安装的是Docker Toolbox,它需要Oracle Virtual Box来跑Docker
现在,Windows和Mac都已经原生支持Docker了。

2.4 从(物理机时代到)虚拟机时代到容器化时代 (Docker实现容器化)

从(物理机时代到)虚拟机时代到容器化时代 (Docker实现容器化)
物理机时代:略过,就是一个系统部署到一个物理机上,有四个缺点,Docker博客中有讲到。
虚拟机时代:虚拟机也能实现对应用的隔离,安装特定的镜像也能跑出我们想要的环境。
虚拟化与容器化比对:虚拟机已经发展了很久了,为什么我们还需要Docker呢?
在这里插入图片描述
容器:容器是一个应用层抽象,用于将代码和依赖资源打包在一起,多个容器可以在同一个机器上运行,共享操作系统内核,但各自作为独立的进程在用户空间中运行,与虚拟机相比,单个容器占用的空间比单个虚拟机占用的空间少(一个虚拟机需要一个操作系统,但是所有容器共用一个操作系统),瞬间就可以启动。
虚拟机:虚拟机是物理硬件层的抽象,管理程序允许多个虚拟机在同一个物理服务器上运行,从而将一个物理服务器变为多个物理服务器,每个虚拟机都包含一个操作系统,一个或多个应用进程,必要的而二进制文件和库资源(容器包含必要的二进制文件和库资源,但不包含操作系统),占用空间大,不能瞬间启动。
小结1(包含):容器包含应用和应用运行必要二进制文件和库资源;虚拟机包含操作系统、应用和应用运行必要二进制文件和库资源,区别三个:是否包含操作系统,重量还是轻量,启动快还是启动慢。
小结2(以什么为单位):Docker容器比虚拟机更加轻量,容器以进程为单位,虚拟机以操作系统为单位,单个容器瞬间就可以启动,但是单个虚拟机就不行了。

2.5 面试金手指

Docker两个功能
功能1:将一整套环境打包封装成镜像,无需重复配置环境,解决环境带来的种种问题。
功能2:Docker容器间是进程隔离的,谁也不会影响谁。
从虚拟化到容器化:
小结1(包含):容器包含应用和应用运行必要二进制文件和库资源;虚拟机包含操作系统、应用和应用运行必要二进制文件和库资源,区别三个:是否包含操作系统,重量还是轻量,启动快还是启动慢。
小结2(以什么为单位):Docker容器比虚拟机更加轻量,容器以进程为单位,虚拟机以操作系统为单位,单个容器瞬间就可以启动,但是单个虚拟机就不行了。

三、Docker两种方式

3.1 Docker处理环境问题

问题:一个新项目要发布上线。结果测试环境跑得好好的,生产环境死活跑不起来。
标准答案:使用docker,将 项目代码 + 需要的依赖 全部放到生产环境中去,就解决不同环境的问题了。
附:docker的两大优点
第一,docker对于常见的工具,提供了基础镜像的方式,docker官方的镜像仓库里有很多镜像,可以直接拉下来用,然后新的镜像可以以它们为基础,在上面commit新的东西。
第二,层与层之间的复用,减少占用大小:docker使用了镜像分层的技术,新的commit会产生新的层,可以复用一部分老的层。这样一来制作新镜像的速度还是挺快的。

在这里插入图片描述

3.2 把整个环境放到另外一个机器部署,提交代码的时候带上dockerfile

问题:如果我要把整个环境放到另外一个机器部署,还是要拷贝整个大的镜像过去吧?
标准答案:整个环境复制到另外一个机器上,通过使用dockerfile,提交代码的时候带上dockerfile,dockerfile就是docker的源代码,记录着docker的组织方式,
dockerfile第一行指定基础镜像:这个镜像基于ubuntu基础镜像,
dockerfile第二行指定镜像维护者:这个镜像的维护者的信息,
dockerfile第三行RUN指定镜像启动前依次执行的命令:RUN就是要执行的shell命令,比如这里,是在ubuntu的基础镜像上安装一些额外的东西,
dockerfile第4行CMD指定镜像启动后执行的初始命令:是镜像启动之后执行的初始命令。
总之,镜像就是一个包,把需要的东西包装起来。
在这里插入图片描述
实践:其实在网络好的情况下,下载一个镜像一般来说比重新打一个镜像更快,所以最终部署都是基于镜像去部署,不会重新打镜像了。

3.3 docker三个概念 镜像、容器和远程镜像仓库

【docker三个概念 镜像、容器和远程镜像仓库】
镜像和容器:镜像有点像代码,容器有点像进程。代码是存放在硬盘上的东西,而把代码运行起来,就会形成一个进程,进程才是跑起来的程序。只不过在docker中,我们可以进入容器,做一些操作,然后再把容器中的改动提交形成一个新的镜像。镜像就是镜像,我们重装系统/搞虚拟机的时候都要用镜像,没镜像哪来系统,我们安装完镜像,就可以跑起来一个系统(Windows也好、Centos也好),于是我们就可以愉快地使用我们通过镜像安装好的系统了。
在Docker中,通过镜像运行起来的东西叫做容器
远程镜像仓库:远程镜像仓库是存放镜像的地方,制作好的镜像,就把它放到远程镜像仓库,方便其他人直接用镜像部署。

3.4 面试金手指

1、docker处理环境问题:容器技术docker的思考方式是,将环境一起打包镜像,避免部署时的环境问题。
2、docker:dockerfile记录镜像的制作步骤
3、docker中的三个概念:镜像、容器、仓库的概念可以类比代码、进程、github

四、使用层面:docker常见命令

4.1 安装Docker与HelloWorld

4.1.1 查看当前centos版本 7.0

// 查看当前linux版本
cat /etc/redhat-release

// 结果
CentOS Linux release 7.3.1611 (Core)

4.1.2 安装Docker

首先我们需要安装GCC相关的环境:

// 安装GCC相关的环境

yum -y install gcc

yum -y install gcc-c++

如果曾经安装过Docker(旧版本)的话,得先卸载,如果没有安装过,跳过这一步:

// 卸载旧Docker版本

yum -y remove docker docker-common docker-selinux docker-engine

安装Docker需要的依赖软件包:

// 安装Docker需要的依赖软件包:

yum install -y yum-utils device-mapper-persistent-data lvm2

设置stable镜像仓库(注意:我们这里使用国内的镜像地址【因为Docker 官网给出的地址在国外,太慢了!】)

// 设置stable镜像仓库:

yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

更新yum软件包索引:

// 更新yum软件包索引:

yum makecache fast

安装DOCKER CE(注意:Docker分为CE版和EE版,一般我们用CE版就够用了)

// 安装DOCKER CE:

yum -y install docker-ce

启动Docker

// 启动Docker

systemctl start docker

4.1.3 接上面,启动好docker,HelloWorld

到上面为止,我们已经启动了Docker,下面我们检验一下我们运行的Docker是否正常。

首先,我们可以看看下载回来的Docker版本:

// 查看Docker的版本

docker version   // 版本查到了,说明Docker是运行起来的啦。

我们来一发HelloWorld:

// docker的HelloWorld

docker run hello-world   // 将一个镜像Image直接变为一个运行态容器Container

运行结果:docker run hello-world这条命令指示Docker去运行hello-world这个镜像,但是我们本地没有这份镜像啊。所以Docker就去DockerHub拉取了一份hello-world镜像,然后生成容器,最后运行容器(docker run命令 = docker create + docker start)。这个hello-world容器的功能就是一句话:Hello from Docker!。所以我们在屏幕上就可以看到这句话了。

4.2 Docker启动tomcat

之前,没有docker,要在一台全新的系统上将Tomcat跑起来。我们需要做以下的事:
安装Java,配置环境变量
安装Tomcat
有了docker,直接在仓库里拉一份tomcat的镜像下来,将docker run镜像跑起来就,就完事了!
步骤一:拉取Tomcat镜像:docker pull tomcat
步骤二:docker images查看是否有拉取到的tomcat:docker image ls
步骤三:docker run运行这个Tomcat镜像,生成运行态容器 docker run -it -p 9999:8080 tomcat

4.3 下载镜像,优先使用阿里镜像

由于安装的Docker默认是去Docker Hub找我们想要的镜像的,官网镜像太慢,直接用阿里云给我们提供的镜像
第一,我们到下面链接搜索一下镜像,比如Tomcat (这就需要我们注册/登录一个阿里云账号)
https://promotion.aliyun.com/ntms/act/kubernetes.html
第二,我们可以在镜像加速器上找到我们的url:
我们依照阿里云给出的教程,就可以配置加速器了。
mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-‘EOF’
{
“registry-mirrors”: [“https://cubmirje.mirror.aliyuncs.com”]
}
EOF
第三,让配置生效,并重启Docker
systemctl daemon-reload
systemctl restart docker

4.4 Docker命令:都是对Image和Container的操作

Docker的命令无非就是对镜像、对容器进行增删改查,没有什么太多新鲜的,列入如下:

3.5 Docker命令(启动)
3.5.1 docker create 将一个静态Image变为一个容器Container
3.5.1.1 docker create 命令的作用
3.5.1.2 docker create 命令的原理
3.5.2 docker start 将一个容器Container变为一个运行态容器Container
3.5.2.1 docker start 命令的作用
3.5.2.2 docker start 命令的底层
3.5.3 docker run 将一个镜像Image直接变为一个运行态容器Container

3.6 Docker命令(列出)
3.6.1 docker ps
3.6.1.1 docker ps 列出所有运行中的容器,但是隐藏了非运行态容器的存在
3.6.1.2 docker ps -a 列出所有容器(运行态容器 + 非运行态容器)
3.6.2 docker images
3.6.2.1 docker images 列出了所有顶层(top-level)镜像
3.6.2.2 docker images -a 列出了所有可读层read layer

3.7 Docker命令 停止、暂停、删除、commit
3.7.1 停止与暂停
3.7.1.1 docker stop 停止运行中的容器
3.7.1.2 docker kill 停止运行中的容器
3.7.1.3 docker pause 暂停运行中的容器
3.7.2 删除
3.7.2.1 docker rm 移除非运行态容器的读写层
3.7.2.2 docker rmi 移除镜像的可读层
3.7.3 docker commit 将读写层变为只读层,将容器变为镜像

3.8 Docker命令 其他
3.8.1 docker build 重复执行命令,生成新的层
3.8.2 docker exec 在运行中的容器执行一个新进程
3.8.3 docker inspect or 提取出容器或者镜像最顶层的元数据
3.8.4 docker save 创建一个镜像的压缩文件,这个文件能够在另外一个主机的Docker上使用
3.8.5 docker export 创建一个tar文件,并且移除了元数据和不必要的层,将多个层整合成了一个层,只保存了当前统一视角看到的内容
3.8.6 docker history 递归地输出指定镜像的历史镜像

五、dockerfile中包含基础镜像依赖

容器包含应用和应用运行必要二进制文件和库资源;虚拟机包含操作系统、应用和应用运行必要二进制文件和库资源

问题1:镜像依赖:我们知道Tomcat运行起来需要Java的支持,那么我们在Docker拉取下来的Tomcat镜像是不是也有Java环境呢?
问题2:容器数据保存:容器退出了(好比Linux进程退出了),容器的数据就没了,我们想要保留容器内的数据,怎么办?
问题3:创建镜像的方式:从上面我们可以看出,通过commit可以在原有的容器基础上,创建出属于我们自己的镜像,还有其他方式创建新的镜像吗?

5.1 问题1:镜像依赖:我们知道Tomcat运行起来需要Java的支持,那么我们在Docker拉取下来的Tomcat镜像是不是也有Java环境呢?标准答案:dockerfile都为我们考虑好了

dockerfile
Dockerfile是用来构建Docker镜像的文件,是由一系列命令和参数构成的脚本。简单来说:Dockerfile是镜像的源码。

以tomcat为例,看一下tomcat的Dockerfile长的什么样:
我们在Dockerfile的第一行就可以发现FROM openjdk:8-jre,所以可以确定的是:在DockerHub拉取下来的Tomcat镜像一定有Java环境!

对于dockerfile,基本要求是大致看懂dockerfile文件(),然后知道dockerfile是镜像的源码即可、通过Dockerfile文件我们可以知道拉取下来的镜像究竟是怎么构建的。

5.2 问题2:为什么tomcat镜像比centos镜像大?标准答案:镜像是分层的,tomcat在centos上层,依赖的基础镜像当然比centos多

Docker Hub有很多常用的镜像,比如说Centos。我们去pull一个下来看看Docker中的Centos长啥样:
我们可以发现的是:Tomcat的SIZE竟然比Centos还要大!但按我们常规的想法,Centos的镜像可能是3或4GB(现在200M),Tomcat的镜像可能就200M(现在400M)。这是为什么呢??

如果我们在pull的时候观察得比较仔细的话,可以发现pull会拉下很多层镜像:
完全pull下来的之后,我们如果使用docker images只能查看到最终的镜像,但是只能看到最终我们拉下来的镜像
如果我们使用docker images -a命令的话,可以把中间层镜像都查出来:

理想效果:(在镜像列表里边除了tomcat和centos应该还夹杂着名为的镜像)

我们可以使用history命令来看看,可以发现Tomcat包含很多个镜像层,使用history命令可以发现Tomcat包含很多个镜像层
还可以发现一点:Dockerfile有多少条命令,那就有多少个镜像层(不信你数数)

说了那么多,就想让大家知道:我们拉取下来的镜像实际上是由很多中间层镜像组成的。

对于pull下来的镜像由很多层镜像组成【这些镜像都是精简过的(甚至连vi命令都不支持)】,我们可以使用cd, ls等基础命令,但无法使用vi命令(需要我自己去下载)。

因为镜像分层,所以可以可以知道,因为Tomcat镜像要的基础环境比Centos镜像要多,所以Tomcat镜像的SIZE比Centos要大

5.3 Docker镜像的三个特点

关于Docker镜像,有三个特点:
1、Docker镜像是由Dockerfile生成
2、Docker镜像层级结构,镜像层级结构造成两种镜像复用
3、每层Docker镜像包含两部分:镜像文件 + 镜像json元数据信息

5.3.1 Docker镜像是由Dockerfile生成

Docker镜像示意图

5.3.2 Docker镜像层级结构,镜像层级结构造成两种镜像复用

镜像呈现层级结构
联合文件系统(UnionFS)是实现Docker镜像的技术基础。在Docker中一般使用是AUFS(Another Union File System或Advanced Multilayered Unification File System)【具体还是得看宿主机用的什么系统】。
Docker的镜像的基础是联合文件系统,它支持将文件系统中的修改信息作为一次提交,并层层叠加,外界看到的是最外层的镜像。(比如外界只看到Tomcat镜像,而中间叠加了很多层镜像)

镜像继承(共享)
Docker镜像可以通过分层来进行继承。

第一,高级镜像共享基础镜像:hello-world的Dockerfile镜像FROM scratch镜像,scratch在Docker中是一个基础镜像
FROM scratch
COPY hello /
CMD ["/hello"]
Centos的Dockerfile镜像也是FROM scratch镜像:
FROM scratch
ADD centos-7-docker.tar.xz /
LABEL org.label-schema.schema-version=“1.0”
org.label-schema.name=“CentOS Base Image”
org.label-schema.vendor=“CentOS”
org.label-schema.license=“GPLv2”
org.label-schema.build-date=“20181205”
CMD ["/bin/bash"]
那么Centos镜像和hello-world共享同一个基础镜像层scratch,提高了存储效率。

第二,基于COW,centos镜像中放入tomcat镜像,磁盘占用会小点:比如我们有一个Centos镜像大小是202M,然后,我们基于Centos镜像手动往里边添加一个Tomcat(假设这个Tomcat的大小是300M),生成一个镜像,总大小就是502M了。
如果仅仅是单纯的累加这两个镜像的大小:202M+502M=704M,但是由于镜像复用的存在,实际占用的磁盘空间大小是:202M+300M=502M
AUFS uses the Copy-on-Write (CoW) strategy to maximize storage efficiency and minimize overhead。

5.3.3 每层Docker镜像包含两部分:镜像文件 + 镜像json元数据信息

json文件
Docker每一层镜像的json文件,都扮演着一个非常重要的角色,其主要三个作用:
(1)记录 Docker 镜像中与容器动态信息相关的内容
(2)记录父子 Docker 镜像之间真实的差异关系
(3)弥补 Docker 镜像内容的完整性与动态内容的缺失
所以,Docker镜像的json文件可以认为是镜像的元数据信息

六、面试金手指

略。

七、小结

Docker基础知识(面试一箩筐),完成了。

天天打码,天天进步!!!

猜你喜欢

转载自blog.csdn.net/qq_36963950/article/details/108994038