Docker 是什么,有什么作用
书面笔记版
Docker 是一种容器化技术,用来把应用程序和它依赖的运行环境一起打包、分发和运行。它解决的核心问题是:开发、测试、生产环境不一致导致“我本地能跑,线上跑不了”。
常见概念:
| 概念 | 作用 |
|---|---|
| 镜像 Image | 应用和依赖环境的只读模板,比如 JDK、应用 Jar、启动脚本 |
| 容器 Container | 镜像运行起来后的进程实例 |
| 仓库 Registry | 存放和分发镜像,比如 Docker Hub、Harbor |
| Dockerfile | 描述如何构建镜像 |
| 数据卷 Volume | 持久化容器数据,避免容器删除后数据丢失 |
| 网络 Network | 让容器之间、容器和宿主机之间通信 |
Docker 的主要作用:
- 环境一致:把应用依赖打进镜像,减少环境差异。
- 部署简单:一条命令启动应用和依赖环境。
- 隔离性好:容器有独立文件系统、进程、网络视图。
- 资源开销小:容器共享宿主机内核,比虚拟机更轻量。
- 方便扩缩容:镜像标准化后可以快速拉起多个实例。
Docker 不是虚拟机。虚拟机会虚拟完整操作系统内核,容器共享宿主机内核,启动更快、占用更少,但隔离强度通常弱于虚拟机。
面试口述版
Docker 是容器化技术,作用是把应用和依赖环境打包成镜像,再通过容器运行。它主要解决环境不一致、部署复杂和应用隔离的问题。镜像可以理解成模板,容器是镜像运行起来的实例,数据卷负责持久化数据,网络负责容器通信。和虚拟机比,Docker 共享宿主机内核,所以启动更快、资源占用更小。
Docker 部署有什么好处
书面笔记版
Docker 用来部署应用时,最大的好处不是“命令变少”这么简单,而是把部署对象从“服务器上的一堆环境配置”变成“一个可版本化、可分发、可重复运行的镜像”。
Docker 部署的主要好处:
- 环境一致:应用依赖的 JDK、Node.js、系统库、启动脚本等都可以固化到镜像里,开发、测试、生产环境使用同一套镜像,减少“我本地能跑,线上跑不了”的问题。
- 部署流程标准化:传统部署可能要手动安装运行环境、复制文件、改配置、写启动脚本;Docker 部署通常是拉取镜像、传入配置、启动容器,流程更固定。
- 迁移方便:镜像可以推送到镜像仓库,在另一台服务器上拉下来就能运行,不太依赖某台机器上提前装好的环境。
- 回滚简单:镜像天然有版本,比如
demo-app:1.0、demo-app:1.1。新版本出问题时,可以重新启动旧版本镜像。 - 启动快、资源开销小:容器共享宿主机内核,比虚拟机轻量,启动速度通常更快,适合快速发布和扩缩容。
- 隔离性更好:不同应用可以运行在不同容器里,文件系统、进程、网络视图相对隔离,依赖冲突更少。
- 方便配合自动化部署:镜像标准化以后,可以结合 Docker Compose、Kubernetes、CI/CD 实现批量部署、滚动发布、弹性扩缩容。
举个例子:一个 Spring Boot 项目依赖 JDK 17,同时还需要 MySQL 和 Redis。
传统部署方式一般是:
- 在服务器上安装 JDK 17。
- 上传 Jar 包。
- 配置环境变量、启动脚本、日志目录。
- 再单独安装和配置 MySQL、Redis。
- 如果换一台服务器,还要重复安装这些环境。
Docker 部署方式可以先给应用写一个 Dockerfile,把运行环境和 Jar 包打成镜像:
FROM eclipse-temurin:17-jre
COPY target/demo.jar /app/demo.jar
ENTRYPOINT ["java", "-jar", "/app/demo.jar"]
然后构建并运行:
docker build -t demo-app:1.0 .
docker run -d -p 8080:8080 demo-app:1.0
这样服务器不需要手动配置 JDK 和应用启动脚本,只要能运行 Docker,就可以通过镜像启动应用。如果还要一起启动 MySQL、Redis、Nginx,就可以再用 Docker Compose 把多个容器统一编排起来。
需要注意:Docker 主要解决的是应用打包、运行和单机容器管理问题。多机器调度、服务自愈、滚动发布、服务发现等更完整的生产级编排能力,通常交给 Kubernetes。
面试口述版
Docker 部署的好处是把应用和运行环境一起打包成镜像,让开发、测试、生产环境尽量一致。部署时服务器只需要拉镜像、启动容器,不用手动安装一堆依赖,迁移和回滚也更方便。比如一个 Java 应用原来要在服务器上装 JDK、传 Jar、配启动脚本,用 Docker 后可以把 JDK 和 Jar 打进镜像,用同一个镜像在不同环境运行。如果项目依赖 MySQL、Redis,还可以配合 Docker Compose 或 K8s 一起部署和管理。
Docker 和 Docker Compose 的区别
书面笔记版
Docker 和 Docker Compose 都属于 Docker 生态,但定位不同。
| 对比点 | Docker | Docker Compose |
|---|---|---|
| 定位 | 容器运行和镜像管理工具 | 单机多容器编排工具 |
| 配置方式 | 常用 docker run 参数启动单个容器 |
用 compose.yml 描述多个服务 |
| 管理对象 | 镜像、容器、网络、数据卷 | 一组相关服务、网络和数据卷 |
| 典型场景 | 启动一个 MySQL、Redis、应用容器 | 一次启动 app + MySQL + Redis + Nginx |
| 适用范围 | 单容器或手动管理多个容器 | 开发、测试、小规模单机部署 |
文件关系可以这样理解:
Dockerfile解决的是“镜像怎么构建出来”。比如一个 Java 项目要把 JDK、Jar 包、启动命令打进镜像,就需要写 Dockerfile。docker run解决的是“一个容器怎么运行起来”。比如根据某个镜像启动一个应用容器,并指定端口、环境变量、数据卷等。compose.yml或旧写法docker-compose.yml解决的是“多个容器怎么一起运行起来”。比如一次性启动后端应用、MySQL、Redis、Nginx,并声明它们的网络、端口、数据卷、依赖关系。
所以不能简单理解成“Docker 只需要 Dockerfile,Docker Compose 必须需要 Dockerfile”。更准确地说:
| 场景 | 常见文件 | 说明 |
|---|---|---|
| 只构建自己的应用镜像 | Dockerfile |
用 docker build 构建镜像,再用 docker run 启动容器 |
| 用 Docker Compose 启动现成服务 | compose.yml |
如果直接使用 mysql:8、redis:7、nginx:latest 这类现成镜像,可以不写 Dockerfile |
| 用 Docker Compose 启动自己的应用和依赖服务 | Dockerfile + compose.yml |
Compose 通过 build 字段引用 Dockerfile 构建应用镜像,再同时启动 MySQL、Redis 等服务 |
Docker Compose 的价值是把多容器启动参数写成声明式配置。例如一个后端项目需要 MySQL、Redis、RabbitMQ 和应用服务,如果只用 docker run,要手动创建网络、启动多个容器并维护参数;用 Compose 可以写在一个 compose.yml 里,用 docker compose up -d 一次拉起。
例如只用 Docker 部署一个后端应用时,通常是:
docker build -t demo-app:1.0 .
docker run -d --name demo-app -p 8080:8080 demo-app:1.0
如果这个后端还依赖 MySQL 和 Redis,就可以写成 Compose:
services:
app:
build: .
ports:
- "8080:8080"
depends_on:
- mysql
- redis
mysql:
image: mysql:8
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: demo
redis:
image: redis:7
然后执行:
docker compose up -d
这时 Compose 会根据 app 的 build: . 找到当前目录下的 Dockerfile 构建应用镜像,同时拉起 MySQL 和 Redis。对于 MySQL、Redis 这种直接使用现成镜像的服务,就不需要单独写 Dockerfile。
需要注意:Compose 主要解决单机多容器编排,不负责跨机器调度、自愈、滚动发布和大规模服务治理。这类能力通常交给 Kubernetes。
面试口述版
Docker 主要负责构建镜像、运行容器;Docker Compose 是在 Docker 之上的单机多容器编排工具。比如只启动一个 Redis,用 docker run 就够了;如果一个项目要同时启动后端、MySQL、Redis、Nginx,就适合用 Compose 写成一个 compose.yml,一条命令启动。Compose 更适合开发测试和小规模单机部署,不像 K8s 那样做跨机器调度和自愈。
Kubernetes 和 K8s 是什么
书面笔记版
Kubernetes 简称 K8s,是容器编排平台。Docker 解决“怎么把应用打包成容器并运行”,K8s 解决“很多容器在多台机器上如何部署、调度、发现、扩缩容和故障恢复”。
常见核心对象:
| 对象 | 作用 |
|---|---|
| Pod | K8s 最小调度单位,通常包含一个主容器 |
| Deployment | 管理 Pod 副本、滚动更新和回滚 |
| Service | 给一组 Pod 提供稳定访问入口和负载均衡 |
| Ingress | 管理 HTTP/HTTPS 入口路由 |
| ConfigMap | 管理普通配置 |
| Secret | 管理密码、证书、Token 等敏感配置 |
| Namespace | 做资源隔离和环境划分 |
K8s 的主要能力:
- 调度:根据资源、节点状态和策略把 Pod 分配到合适节点。
- 自愈:Pod 挂了自动重建,节点异常时迁移。
- 服务发现:通过 Service 屏蔽 Pod IP 变化。
- 负载均衡:把请求分发到多个 Pod。
- 弹性伸缩:根据副本数或指标扩缩容。
- 滚动发布:逐批替换旧版本,支持回滚。
- 配置管理:通过 ConfigMap、Secret 解耦配置。
面试口述版
Kubernetes 简称 K8s,是容器编排平台。Docker 更关注单个容器怎么运行,K8s 关注一堆容器在多台机器上怎么部署、调度、扩缩容、自愈和服务发现。K8s 里最小调度单位是 Pod,Deployment 管理副本和发布,Service 提供稳定访问入口,Ingress 做 HTTP 入口路由,ConfigMap 和 Secret 管理配置。
K8s 服务暴露和访问链路
书面笔记版
K8s 里外部请求通常不是直接访问 Pod。因为 Pod 会重建、漂移,Pod IP 不稳定,所以一般会通过 Service 提供稳定入口,再根据是否需要对外暴露选择 NodePort、LoadBalancer 或 Ingress。
常见三层可以这样记:
Pod / Deployment -> Service -> Ingress / NodePort / LoadBalancer
| 层级 | 作用 |
|---|---|
| Pod / Deployment | Pod 真正运行容器;Deployment 管理 Pod 副本、滚动发布和自愈 |
| Service | 给一组 Pod 提供稳定访问入口,并做集群内负载均衡 |
| Ingress / NodePort / LoadBalancer | 把服务暴露给集群外部访问 |
Service 常见类型:
| 类型 | 访问范围 | 说明 |
|---|---|---|
ClusterIP |
集群内部 | 默认类型,只能在集群内通过 Service 名或 ClusterIP 访问 |
NodePort |
集群外部可访问 | 在每个节点暴露一个端口,通过 NodeIP:NodePort 访问 Service |
LoadBalancer |
集群外部可访问 | 通常依赖云厂商负载均衡,把公网入口转发到 Service |
Ingress 负责 HTTP/HTTPS 七层路由,常用于按域名、路径转发:
用户 -> 域名/公网入口 -> Ingress Controller -> Ingress 规则 -> Service -> Pod
需要注意:
Ingress不是ipress,正确名称是Ingress。Ingress本身只是规则,必须有Ingress Controller才能真正接流量和转发。Ingress常和域名一起用,生产环境一般会配域名和 HTTPS;但从概念上说,它核心是 HTTP/HTTPS 路由规则,不是“必须有域名才能存在”。- 标准 K8s 不一定默认自带外部网关或 Ingress Controller,需要自己安装 Nginx Ingress Controller、Traefik 等。
- K3s 默认常带 Traefik 作为 Ingress Controller,所以学习或小规模部署时会觉得“默认有网关”。
- 不用 Ingress 也能暴露服务,简单场景可以用
NodePort,直接访问节点IP:端口。
几种方式的选择:
| 方式 | 适合场景 | 优缺点 |
|---|---|---|
ClusterIP |
服务只在集群内部被其他服务调用 | 安全简单,但外部不能直接访问 |
NodePort |
临时测试、小规模暴露服务 | 简单直接,但端口范围固定,生产管理不够优雅 |
LoadBalancer |
云环境生产暴露服务 | 使用方便,但依赖云厂商负载均衡资源 |
Ingress |
多个 HTTP 服务共用入口、域名、路径和 HTTPS | 适合生产 Web/API 入口,但需要 Ingress Controller |
所以,NodePort 和 Ingress 都可以让外部访问服务,但层次不同:NodePort 是四层端口暴露;Ingress 是七层 HTTP/HTTPS 路由,通常更适合统一入口、域名、路径和证书管理。
面试口述版
K8s 里一般不是直接访问 Pod,因为 Pod IP 会变化。通常是 Deployment 管理 Pod,Service 给一组 Pod 提供稳定入口,然后再决定怎么对外暴露。ClusterIP 是默认类型,只能集群内部访问;NodePort 会在每个节点开一个端口,可以直接用 NodeIP:NodePort 访问,所以不用 Ingress 也能暴露服务;LoadBalancer 一般依赖云厂商负载均衡。Ingress 是 HTTP/HTTPS 七层入口,常按域名或路径转发到 Service,但它本身只是规则,必须有 Ingress Controller,比如 Nginx Ingress 或 Traefik。K3s 默认常带 Traefik,所以会感觉它有一个默认网关。
K8s 和 K3s 的区别
书面笔记版
K3s 是 Rancher 推出的轻量级 Kubernetes 发行版,可以理解成“瘦身版、易安装版 K8s”。它仍然兼容 Kubernetes API,但对组件、依赖和默认配置做了简化。
| 对比点 | K8s | K3s |
|---|---|---|
| 定位 | 标准 Kubernetes 集群 | 轻量级 Kubernetes 发行版 |
| 资源占用 | 相对更高 | 更低,适合小机器和边缘节点 |
| 安装复杂度 | 组件多,搭建和维护成本更高 | 单二进制,安装更简单 |
| 默认组件 | 原生组件更完整,选择更灵活 | 内置轻量组件,如 SQLite、Traefik 等默认选项 |
| 适用场景 | 中大型生产集群、云原生平台 | 学习、测试、边缘计算、小规模部署 |
选择上可以这样理解:
- 公司标准生产环境、复杂网络和多团队平台化:优先标准 K8s 或云厂商托管 K8s。
- 个人学习、小项目、边缘设备、低资源服务器:K3s 更轻更快。
- K3s 不是另一个完全不同的技术,它本质仍是 Kubernetes 生态。
面试口述版
K8s 是标准 Kubernetes,适合生产级、大规模容器编排;K3s 是轻量级 Kubernetes 发行版,兼容 K8s API,但安装更简单、资源占用更低。一般大公司生产环境会用标准 K8s 或云厂商托管 K8s,小机器、边缘节点、个人学习和小规模部署可以用 K3s。简单说,K3s 是更轻量、更易用的 K8s。