想象一下在没有 Docker 之前,你的代码在本地运行良好,但发给服务器就报错,就像你在北方穿羽绒服很舒服,到了南方(不同的系统环境)就中暑了。
Docker 就是为了解决了这个问题。
一、镜像 vs. 容器
你可以用**“游戏安装包”和“运行中的游戏实例”**来完美类比这两者:
1. 镜像 (Image)
镜像就是一个只读的压缩包。它不仅包含你的 Java 代码 (Jar包),还包含了运行代码所需的全家桶:
- 基础运行环境 (Base Image):比如 Alpine 或 Ubuntu 的用户态文件系统(不含内核)。
- 运行时支撑 (Runtime):比如 JDK 17 或 Python 环境。
- 应用本体:你的 Java 代码 (Jar包)。
- 配置与元数据:环境变量(TZ)、端口声明(EXPOSE)、启动命令(ENTRYPOINT)。
一句话理解:镜像就是“没跑起来的程序”,是静态的文件,一旦构建完成就不会再变。
2. 容器 (Container)
容器是从镜像启动的一个进程。如果你把镜像看作“月饼模具”,那容器就是“压出来的月饼”。
- 你可以从同一个镜像启动 10 个容器。
- 每个容器都是独立的、隔离的“小隔间”。
- 你在容器里修改文件,不会影响镜像,也不会影响其他容器。
一句话理解:容器就是“跑起来的镜像”,它有自己的生命周期(启动、停止、删除)。
二、面向对象思想的理解
如果用开发者更熟悉的面向对象编程来比喻:
镜像 = 类 (Class):定义了属性和行为,是模板。
容器 = 对象 (Object):是类的一个具体实例。你可以根据一个类 new 出成千上万个对象。
三、Docker 的基本操作流程:
- Build(构建):根据
Dockerfile把你的代码和环境“打包”成一个 镜像。 - Push(推送):把镜像传到云端仓库(比如 阿里云 ACR)。
- Pull(拉取):服务器从云端下载这个 镜像。
- Run(运行):Docker 引擎根据镜像“解压”并启动一个 容器。
四、为什么 Docker 这么快?
- 虚拟机:模拟一整套硬件和一整个操作系统(Windows/Linux),非常笨重,启动要几分钟。
- Docker 容器:直接借用宿主机的操作系统内核,它只是一个受保护的进程。
- 启动速度:秒级(你的 Java 程序转圈的时间其实占了大半)。
- 资源占用:极低(一个 2G 内存的服务器能跑几十个容器,但只能跑 1-2 个虚拟机)。