兄弟们,上一篇咱们刚聊完 Linux,把服务器上的“生存技能”练了练。但现在去面试,光会 Linux 已经稍微有点不够用了。

只要你的简历上写了“微服务”、“分布式”或者“项目部署”,面试官多半会顺嘴问一句:

“你们项目是怎么部署的?用过 Docker 吗?它和虚拟机有什么区别?”

如果你回答:“就是把 Jar 包传上去,用 nohup java -jar 跑起来”,那这天儿基本就聊死了一半。面试官会觉得你还在用十年前的土办法,完全不懂现代化的云原生部署

今天咱们就来深度聊聊 Docker。作为 Java 后端,你不需要成为运维专家,但你得知道 Docker 到底帮我们解决了什么“痛点”,以及在面试中如何优雅地展示你不仅会用,还懂它的底层逻辑。


一、 痛点:为什么会有 Docker?

在没有 Docker 的年代,程序员最怕听到的一句话就是:“在我的电脑上运行得好好的,怎么一到服务器上就挂了?”

这就是经典的环境不一致问题。可能是服务器的 JDK 版本是 17 而你用的是 8;可能是环境变量少配了一个;也可能是某个特定的 Lib 库版本冲突。

Docker 的出现,本质上是把“运行环境”和“代码”打包在了一起。

我们可以把 Docker 想象成搬家:

  • 以前:零散地搬家具(代码),到了新家(服务器)还得重新组装,发现螺丝丢了或者尺寸不对。

  • Docker:直接把整个房子(容器)装进集装箱,整体吊装过去,落地即住。

“一次构建,到处运行”,这就是 Docker 最大的魅力。


二、 核心命题:Docker vs 虚拟机(必考题)

面试官最爱问:“既然都是隔离环境,我有虚拟机(VM)了,为什么要用 Docker?”

如果你只回答“Docker 更轻量”,那只能给 60 分。要答出深度,得从架构上聊:

特性虚拟机 (VM)Docker 容器
隔离级别硬件级隔离(Hypervisor)进程级隔离(Kernel)
启动速度分钟级(要启动完整的 OS)秒级(就是一个进程)
资源占用极高(每个 VM 都要几十G空间)极低(镜像通常只有几百M)
内核每个 VM 都有自己的内核共享宿主机的内核

面试高分回答:

“虚拟机是硬件层面的隔离,每个 VM 都要跑一个完整的 OS;而 Docker 是进程层面的隔离。它利用了 Linux 内核的 Namespace 机制实现环境隔离,通过 Cgroups 机制实现资源限制。因为不需要加载 OS 内核,Docker 启动是秒级的。一台服务器跑 10 个虚拟机可能就卡了,但跑 100 个 Docker 容器可能还很轻松。”


三、 三个核心概念:用 Java 思维去理解

很多初学者被 Image、Container、Registry 这些词绕晕了。作为 Java 程序员,你用 Java 的类和对象去类比,一秒就懂:

  1. Image (镜像) —— 类 (Class):它是静态的模版,只读。里面装好了 JDK、你的 Jar 包、各种配置。

  2. Container (容器) —— 对象 (Object):它是镜像运行后的实例。你可以根据一个类 new 很多个对象,也可以根据一个镜像跑很多个容器,它们之间互不干扰。

  3. Registry (仓库) —— Maven 仓库:就像 Maven 中央仓库放 Jar 包一样,Docker Hub 放的是镜像。


四、 Java 后端最常用的 Docker “生存”命令

在公司里,你最常用的场景不是写 Docker 引擎,而是通过命令排查问题

1. 查看与排查(最高频)

  • docker ps:看看我的 Java 服务起没起来?状态是不是 Up

  • docker logs -f --tail 200 [ID]最常用。实时看 Spring Boot 的启动日志,报错了全靠它。-f 是实时追踪,--tail 200 是看最后 200 行。

  • docker exec -it [ID] /bin/bash:进入容器内部。比如你想看看容器里的 /config 目录下配置文件到底对不对,就得进去敲命令。

2. 管理与清理

  • docker stop/start [ID]:重启大法,解决 90% 的玄学问题。

  • docker rm -f [ID]:删掉废弃的容器。

  • docker system prune:一键清理没用的镜像和缓存(当服务器磁盘满了的时候,这一招简直是救命稻草)。


五、 实战:如何把 Spring Boot 项目打成镜像?

面试官可能会问:“你是怎么部署你的 Java 项目的?”

这时候,你得能口述出 Dockerfile 的几个关键指令。假设你有一个 mall.jar:

# 1. 基础镜像:得有运行环境。 alpine 版极小,推荐。
FROM openjdk:8-jdk-alpine

# 2. 设置容器内的工作目录
WORKDIR /app

# 3. 将打好的 Jar 包拷贝进镜像
COPY target/mall.jar app.jar

# 4. 声明暴露的端口
EXPOSE 8080

# 5. 启动程序
ENTRYPOINT ["java", "-jar", "app.jar"]

进阶点(必考):镜像分层原理

面试官问:“为什么 Docker 镜像下载很快?”

答:因为镜像是分层的。如果你本地已经有了 OpenJDK 的层,下次下载你业务代码层时,基础层就不用重复下载了。这叫层缓存机制。


六、 进阶:数据卷 (Volume) 与网络 (Network)

这两个概念决定了你是不是真的玩过实战。

1. 数据卷 (Volume):别让数据随容器“猝死”

容器是“用完即丢”的。如果你把 MySQL 跑在 Docker 里,容器一删,里面的数据全丢了。

解决方案:用 Volume。把宿主机的文件夹挂载到容器内。让数据独立于容器的生命周期。

2. 网络 (Network):容器间怎么通信?

如果你一个容器跑 Spring Boot,一个跑 Redis。Spring Boot 怎么连 Redis?

  • 千万别写 127.0.0.1,因为每个容器的 127.0.0.1 都是它自己。

  • 正确做法:把它们加入同一个 Docker Network,然后直接通过容器名互连,Docker 内部会自动做 DNS 解析。


七、 总结:如何优雅地回答面试题?

当面试官问:“你对 Docker 了解多少?”

请不要只说“我会写命令”。你可以这样分层次总结:

“我觉得 Docker 核心解决了环境一致性资源隔离的问题。

  1. 开发阶段:我们通过 Docker 快速启动 MySQL、Redis 等中间件,降低了搭建环境的成本。

  2. 部署阶段:通过编写 Dockerfile 将 Spring Boot 应用打包成镜像,实现‘一次构建,到处运行’,避免了生产环境不一致导致的 Bug。

  3. 实战排查:我熟练使用 docker logs 查看堆栈,或者 exec 进入容器排查配置。

  4. 底层原理:我也了解 Docker 是利用 Linux 的 Namespace 做空间隔离,通过 Cgroups 做资源限制,比传统的虚拟机更加高效和轻量。”

更多推荐