1. Docker和虚拟机的本质区别是啥?

这问题基本是必问的。很多人会回答“Docker轻量,虚拟机笨重”,但面试官想听的是更深层的技术原理。核心在于资源隔离的实现方式不同。

虚拟机(VM)是通过Hypervisor在物理硬件上虚拟出一整套完整的操作系统环境,包括内核、系统库、应用等,每个VM都有自己的操作系统内核。而Docker容器是使用Linux内核的Cgroups(控制资源使用)和Namespace(隔离资源视图)技术,实现进程级别的隔离,所有容器共享宿主机的内核。

简单比喻:VM是独栋别墅,Docker是合租公寓里的独立房间。别墅有自己的地基和整体结构,而公寓房间共享地基和主体结构,只是内部做了隔断。

2. 解释一下Docker镜像的分层结构

Docker镜像采用Union File System(联合文件系统),将镜像分为多层,每一层都是只读的。当你构建一个新镜像时,会在基础镜像之上添加新的可读层。这种设计的最大好处是资源共享和存储效率。

比如,如果你有10个基于Ubuntu的镜像,那么宿主机只需要存储一份Ubuntu基础层。当容器启动时,Docker会在最顶层添加一个可写的容器层,所有对文件的修改都发生在这个可写层。当容器删除时,这个可写层也会随之删除,底层镜像保持不变。

3. 如何减小Docker镜像的体积?

这是个非常实际的问题。小镜像意味着更快的传输和部署。常用技巧:

使用Alpine Linux等轻量级基础镜像

多阶段构建(Multi-stage build):在Dockerfile中使用多个FROM语句,前一个阶段用于编译构建,后一个阶段只复制必要的运行文件,丢弃中间层

合并RUN指令,减少镜像层数

使用.dockerignore文件排除不必要的文件

清理不必要的安装包和缓存

4. Docker网络模式有哪几种?

Docker默认提供五种网络模式:

bridge:默认模式,为每个容器分配独立的网络命名空间

host:容器直接使用宿主机的网络栈

none:禁用网络功能

container:共享另一个容器的网络命名空间

自定义网络:用户自定义的bridge网络,提供更好的容器间通信

实际生产中,自定义网络用得比较多,因为它提供了自动DNS解析功能,容器间可以通过容器名直接通信。

5. 数据持久化怎么实现?

容器本身是无状态的,数据持久化主要通过:

Bind Mount:直接将宿主机的目录挂载到容器

Volume:由Docker管理的存储卷,生命周期独立于容器

tmpfs mount:将数据存储在宿主机的内存中

Volume是生产环境推荐的方式,因为它不依赖于宿主机的目录结构,更容易备份和迁移。

6. Dockerfile中的COPY和ADD有啥区别?

这问题看似简单,但很多人答不全。两者都用于复制文件,但ADD功能更多:

ADD支持从URL下载文件并复制到镜像

ADD会自动解压tar压缩包

COPY只能从构建上下文复制本地文件

最佳实践是:除非需要自动解压或从URL下载,否则优先使用COPY,因为它更透明、更可预测。

7. 如何查看容器内运行的进程?

命令可以查看,这实际上是通过读取宿主机的/proc文件系统实现的,因为容器内的进程在宿主机上是可见的。

8. Docker Compose和Docker Swarm的区别

Compose主要用于定义和运行多容器应用,适合开发和测试环境。Swarm是Docker原生的集群管理工具,提供容器编排功能,适合生产环境。现在Kubernetes已经成为容器编排的事实标准,但了解Swarm仍然有助于理解编排的基本概念。

9. 容器退出后,如何查看其日志?

使用命令。Docker默认将容器的标准输出和错误输出收集起来,即使容器已退出,只要没有手动删除容器,日志仍然可以查看。

10. 实际工作中遇到的Docker问题

这个问题考察实际经验。可以讲镜像构建优化、网络配置问题、存储驱动选择、资源限制设置等。比如我曾遇到容器内存泄漏导致整个宿主机OOM(Out of Memory)的情况,后来通过设置参数限制容器内存使用解决了问题。

最后给个建议:Docker的知识点比较杂,理解其底层原理比死记硬背命令更重要。面试时如果能结合实际场景讲解,效果会好很多。祝各位面试顺利,拿到心仪的offer!

更多推荐