从零理解容器化:Docker 核心原理与 Kubernetes 初探
系统梳理 Docker 的诞生背景、基本概念、常用命令与 Dockerfile 实践,并初步了解 Kubernetes 的设计哲学,帮助 Java 开发者快速建立容器化思维体系。
1 为什么需要 Docker?
Docker 出现之前的困境
在 Docker 出现之前,软件的开发、交付与部署面临着一个长久以来没有彻底解决的问题:「在我的机器上明明是好的!」
软件运行依赖于操作系统、JDK 版本、环境变量、配置文件等一系列条件。开发者在本地搭建好环境、跑通测试,但一旦交付给运维或者部署到生产服务器,往往因为环境不一致导致各种莫名其妙的故障。
- 软件交付方式繁琐:需要附带厚重的部署文档,逐步指导运维重建环境
- 部署过程耗时:在新机器上安装依赖、配置参数,动辄耗费数小时
- 不同应用之间的依赖冲突难以隔离
Docker 带来了什么?
| 能力 | 说明 |
|---|---|
| 环境一致性 | 保证开发、测试、交付、部署全链路的运行环境完全一致,彻底消灭「环境差异」导致的 Bug |
| 资源隔离 | 每个容器拥有独立的网络、文件系统和进程空间,互不干扰,安全可靠 |
| 用完即弃 | 快速启动临时环境用于测试或 CI/CD,使用完毕直接销毁,零污染 |
| 秒级弹性扩容 | 相比虚拟机分钟级启动,容器可以在秒级内完成超大规模部署与扩缩容 |
2 Docker 核心概念:镜像与容器
镜像(Image)
镜像是一个预定义好的模板文件,Docker 引擎可以按照这个模板启动无数个一模一样、互不干扰的容器。
类比: 镜像就像蛋糕的模具,容器就是用这个模具做出来的蛋糕。同一个模具可以做出无数个一样的蛋糕,每个蛋糕相互独立,你吃了这个不影响另一个。
镜像在结构上是分层的(Layered) ,这是为了最大化复用------多个镜像可以共享相同的底层,节省存储空间与下载时间。
容器(Container)
容器是镜像运行后的实例,本质上是一台「虚拟的计算机」,拥有独立的:
- 网络:独立的 IP 地址与端口空间
- 文件系统:与宿主机完全隔离
- 进程:容器内的进程对外不可见
⚠️ 注意: 容器默认与宿主机不发生任何交互,这意味着容器内的数据是没有持久化的 !容器一旦被删除,其内部数据随之消失。如果需要持久化数据,必须通过 -v 参数挂载宿主机目录。
3 Docker 常用命令详解
拉取与查看镜像
bash
# 拉取指定版本的镜像
docker pull mysql:5.7.28
# 查看本地已有的所有镜像
docker images
# 删除指定镜像
docker rmi <镜像ID或镜像名>
镜像名称由三部分组成:
markdown
registry.cn-beijing.aliyuncs.com/dr1/ hcsp :0.0.16
|____________镜像仓库地址_____________| |镜像名| |Tag|
启动容器
ini
# 交互式启动(前台运行,Ctrl-C 退出)
docker run -it <镜像名> <命令>
# 后台 daemon 模式运行
docker run -d <镜像名>
# 完整示例:启动一个 MySQL 容器
docker run -d \
--name mysql-dev \
--restart=always \
-p 3306:3306 \
-v /data/mysql:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=secret \
mysql:5.7.28
docker run 的常用参数说明:
| 参数 | 说明 |
|---|---|
--name <名字> |
为容器指定一个可读的名称,便于后续引用 |
--restart=always |
容器异常退出时自动重启,适用于生产服务 |
-v <本地路径>:<容器路径> |
挂载宿主机目录到容器,实现数据持久化 |
-p <本地端口>:<容器端口> |
端口映射,将容器内端口暴露给宿主机 |
-e NAME=VALUE |
设置环境变量,如 MySQL 密码、Redis 配置等 |
-d |
以 daemon 后台模式运行,不占用当前终端 |
容器生命周期管理
| 命令 | 说明 |
|---|---|
docker ps |
查看正在运行的容器;加 -a 查看所有容器(含已停止) |
docker start / stop |
启动 / 停止一个容器,类比为「开关机」操作 |
docker rm |
删除一个容器,类比「把电脑丢掉」,数据随之丢失 |
docker exec |
进入运行中的容器执行命令,类比 SSH 登录 |
docker logs |
查看容器输出;加 -f 参数可实时跟踪日志 |
docker inspect |
查看容器的详细状态(网络、挂载点、环境变量等) |
bash
# 进入容器内部(调试必备)
docker exec -it <容器ID> bash
# 实时跟踪容器日志
docker logs -f <容器ID>
💡 调试必备: docker exec -it <容器ID> bash 是排查容器内部问题的核心手段,配合 docker logs -f <容器ID> 实时查看日志,几乎可以定位 90% 的容器运行问题。
4 Dockerfile 与镜像构建
手动拉取现成镜像固然方便,但更多时候我们需要将自己的应用打包成镜像。这就需要编写 Dockerfile------一个描述「如何构建镜像」的配置文件。
一个典型的 Java 应用 Dockerfile
bash
# 指定基础镜像(分层结构的起点)
FROM eclipse-temurin:17-jre-alpine
# 设置工作目录
WORKDIR /app
# 将编译好的 jar 包复制进镜像
COPY target/myapp.jar app.jar
# 声明容器对外暴露的端口
EXPOSE 8080
# 容器启动时执行的命令
ENTRYPOINT ["java", "-jar", "app.jar"]
编写好 Dockerfile 后,在同目录执行构建命令:
bash
# 构建镜像,. 代表使用当前目录的 Dockerfile
docker build -t myapp:1.0.0 .
构建完成后,每个镜像会生成一个唯一的 ID,也可以通过 -t 参数为其指定一个更易读的 tag 名称。
5 镜像仓库与 Tag 管理
类似于 Maven 的 Nexus 私服,Docker 也有自己的镜像仓库体系。Tag 操作决定了镜像的归属与存储位置。
bash
# 为镜像打 Tag,指向私有仓库
docker tag myapp:1.0.0 registry.cn-beijing.aliyuncs.com/myorg/myapp:1.0.0
# 推送到远程仓库
docker push registry.cn-beijing.aliyuncs.com/myorg/myapp:1.0.0
# 从私有仓库拉取
docker pull registry.cn-beijing.aliyuncs.com/myorg/myapp:1.0.0
生产环境中,通常会搭建私有镜像仓库,通过以下 Docker 启动参数配置:
--registry-mirror:配置镜像加速源(如阿里云加速器),解决拉取 Docker Hub 镜像慢的问题--insecure-registry:允许使用 HTTP 协议连接私有仓库(非 HTTPS),适用于内网环境
6 Kubernetes 概念简介
有了 Docker,我们可以在单台机器上轻松管理容器。但当服务规模扩展到数十台、数百台机器时,如何统一调度和管理这些容器?这正是 Kubernetes(K8s) 解决的问题。
宠物与家畜:理解运维哲学的转变
| 类比 | 特点 | |
|---|---|---|
| 传统服务器 | 养宠物 | 每台服务器都有名字、独特的配置,出了问题要仔细修复,不能轻易替换,珍贵而脆弱 |
| Docker 容器 | 变成家畜 | 容器是标准化、可替换的。一个挂了,直接启动一个新的,完全一样,无需留恋 |
| Kubernetes | 牧场主 | K8s 是自动化牧场:自动决定把容器跑在哪台机器上,自动扩缩容,自动故障恢复 |
这个比喻深刻揭示了云原生时代运维思维的转变:我们不再关心某一台具体的服务器,而是声明「我需要 10 个 MySQL 实例」,由 K8s 自动完成调度、部署与运维。
学习路径建议
Docker 基础 → Dockerfile 实践 → 镜像仓库管理 → Kubernetes 核心概念(Pod / Service / Deployment)→ K8s 实战部署
Docker 是 K8s 的基石,打好 Docker 基础后,K8s 的很多设计会豁然开朗。