Docker 是什么?
Docker 是一个工具,能把你的程序和它需要的环境(比如 JDK、配置、依赖)打包成一个"集装箱"(叫容器),在任何装了 Docker 的电脑上都能直接运行,不用再配环境。
✅ 解决问题:
"在我电脑能跑,你电脑跑不了" → 一次打包,到处运行!
核心名词
| 名词 | 是什么 | 一句话理解 |
|---|---|---|
| 镜像(Image) | 程序的"安装包" | 只读模板,不能运行,但可以用来启动容器(如 mysql、nginx) |
| 容器(Container) | 正在运行的程序 | 镜像启动后的实例,能运行、能停止、能删除 |
| Dockerfile | 打包说明书 | 一个文本文件,告诉 Docker 怎么把你的代码做成镜像 |
| 卷(Volume) | 持久化存储 | 容器删了数据也不丢(比如数据库文件存这里) |
| 网络(Network) | 容器之间的"对讲机" | 同一网络下的容器可以用名字 互相访问(如 mysql、redis) |
✅ 问题 1:Dockerfile 是用来构建项目运行的 JDK 环境是吧?
答:不完全是。
- Dockerfile 不是专门用来装 JDK 的 ,而是基于已有的 JDK 镜像(如
eclipse-temurin:17-jre-alpine) ,把你的 Spring Boot JAR 包打包进去,形成一个完整的可运行应用镜像。 - JDK 环境由
FROM指令直接复用官方镜像,你无需手动安装。 - 所以:Dockerfile = 官方 JDK + 你的代码 + 启动命令
✅ 问题 2:COPY u2vd_cloud.jar app.jar 为什么有两个 jar?Spring Cloud 项目也这样部署吗?
答:
- 这行命令的意思是:把虚拟机当前目录下的
u2vd_cloud.jar复制到容器里,并改名为app.jar。- 左边是源文件名(你上传的 JAR)
- 右边是容器内的目标文件名 (可自定义,通常简化为
app.jar)
- Spring Cloud 项目完全一样部署 :
- 每个微服务(user-service、order-service 等)各自打成一个 JAR
- 每个服务单独写自己的 Dockerfile
- 各自构建镜像、各自运行容器
- 通过
--network加入同一网络,用服务名互相调用
✅ 核心原则:一个 JAR → 一个容器
✅ 问题 3:我的环境是本地开发 + 虚拟机跑 Docker,用 MobaXterm 连接,操作流程是什么?
答:四步极简流程:
-
本地打包 :IDEA 执行 Maven
package,得到xxx.jar -
上传 JAR :用 MobaXterm 左侧 SFTP 面板,把 JAR 拖到虚拟机目录(如
/root/app/) -
写 Dockerfile :在虚拟机同目录下创建 Dockerfile,内容包含:dockerfile
FROM eclipse-temurin:17-jre-alpine WORKDIR /app COPY 你的真实文件名.jar app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "app.jar"] -
构建并运行 :
FROM eclipse-temurin:17-jre-alpine WORKDIR /app COPY 你的真实文件名.jar app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "app.jar"]⚠️ 关键提醒 :Docker 只能访问虚拟机上的文件,必须先上传 JAR 到虚拟机!
高频命令速查表
| 场景 | 命令 | 说明 |
|---|---|---|
| 镜像 | docker images |
列出本地镜像 |
docker build -t myapp . |
用当前目录 Dockerfile 构建 | |
docker rmi 镜像名 |
删除镜像 | |
| 容器 | docker ps |
运行中的容器 |
docker ps -a |
所有容器(含停止的) | |
docker run -d --name xx 镜像 |
后台启动新容器 | |
docker start/stop/restart xx |
管理已有容器 | |
docker logs -f xx |
实时看日志(调试神器) | |
docker exec -it xx bash |
进入容器调试 | |
| 网络 | docker network ls |
列出网络 |
docker network create net |
创建自定义网络 | |
docker network inspect net |
查看哪些容器连入 | |
| 卷 | docker volume ls |
列出命名卷 |
docker volume inspect xx |
查看卷存储位置 | |
| 清理 | docker system prune -a |
清理无用资源(慎用) |
# 启动 MySQL 容器
docker run -d \ # 后台运行(detached 模式)
--name mysql \ # 给容器起名为 "mysql"
-p 3306:3306 \ # 将虚拟机的 3306 端口映射到容器的 3306 端口(供外部连接)
-e TZ=Asia/Shanghai \ # 设置容器时区为上海(避免时间差8小时)
-e MYSQL_ROOT_PASSWORD=123 \ # 设置 MySQL root 用户密码(必须设置!)
-v /root/mysql/data:/var/lib/mysql \ # 挂载数据卷:持久化数据库文件(删容器不丢数据)
-v /root/mysql/conf:/etc/mysql/conf.d \ # 挂载配置目录:可放入自定义 my.cnf 配置文件
-v /root/mysql/init:/docker-entrypoint-initdb.d \ # 挂载初始化脚本目录:首次启动时自动执行 .sql 或 .sh 文件
--network net \ # 加入自定义网络 "net",便于与其他容器(如 Java 应用)通过容器名通信
mysql # 使用官方 mysql 镜像(默认 latest)
# 启动 RabbitMQ 容器(带管理界面)
docker run \
-e RABBITMQ_DEFAULT_USER=itheima \ # 设置默认用户名(覆盖 guest)
-e RABBITMQ_DEFAULT_PASS=123321 \ # 设置默认密码
-v mq-plugins:/plugins \ # 挂载命名卷:持久化已安装的插件(重启不丢失)
--name mq \ # 容器名称设为 "mq"
--hostname mq \ # 设置容器内主机名为 "mq"(RabbitMQ 对 hostname 敏感,建议显式指定)
-p 15672:15672 \ # 映射 Web 管理界面端口(浏览器访问 http://IP:15672)
-p 5672:5672 \ # 映射 AMQP 协议端口(Java 应用通过此端口连接)
--network net \ # 加入同一自定义网络 "net",可被其他服务用 "mq" 名称访问
-d \ # 后台运行
rabbitmq:3.8-management # 使用带 management 插件的 RabbitMQ 3.8 版本镜像
本机(Windows)有 MySQL 占用 3306,Docker 在虚拟机也用 -p 3306:3306,会冲突吗?
✅ 答案:不会冲突!
原因:
- Windows 的 3306 和 虚拟机的 3306 是两台不同机器的端口,互不影响。
- 你在 Windows 访问:
localhost:3306→ 连的是 本机 MySQL虚拟机IP:3306→ 连的是 Docker 里的 MySQL
⚠️ 但注意:
如果虚拟机自己也装了 MySQL(非 Docker) ,再运行 docker run -p 3306:3306 就会端口冲突!
解决方法:
-
推荐 :停掉虚拟机本地的 MySQLbash
sudo systemctl stop mysqld sudo systemctl disable mysqld -
或改 Docker 映射端口(如
-p 3307:3306),但需连虚拟机IP:3307
✅ 最佳实践:
- 虚拟机只跑 Docker 容器,不装原生数据库/中间件
- 本机服务和虚拟机 Docker 服务完全隔离,放心共存
💡 记住:端口冲突只发生在同一台机器上,跨机器(Windows ↔ 虚拟机)永远不冲突!