大家好,这依然是一篇个人笔记
本次笔记内容是有关于Java项目在Docker容器的有关知识,对应黑马JavaWeb的197~199集
本篇笔记由workbuddy一同完成,不喜勿喷,谢谢!
一、为什么需要 Docker 部署?
1.1 传统部署方式的问题
|--------|-----------------------|-------------|
| 问题 | 说明 | 影响 |
| 环境不一致 | 开发环境能跑,生产环境报错 | "在我机器上能跑"问题 |
| 依赖冲突 | 不同项目需要不同版本的 JDK/MySQL | 需要复杂的版本管理 |
| 配置繁琐 | 每台服务器都要手动安装环境 | 部署耗时,易出错 |
| 难以扩展 | 新增服务器需要重复配置 | 水平扩展困难 |
1.2 Docker 部署的优势
✅ 环境一致性:容器内包含所有依赖,"一次构建,到处运行"
✅ 快速部署:镜像秒级启动,无需手动配置环境
✅ 资源隔离:每个容器独立运行,互不干扰
✅ 易于扩展:快速复制容器实例,实现水平扩展
1.3 部署前准备清单
|---------|------------------------------|
| 准备项 | 说明 |
| 服务器环境 | 安装 Docker 和 Docker Compose |
| 项目结构 | 准备好 Dockerfile 和相关配置文件 |
| 镜像仓库 | Docker Hub 或私有仓库(如阿里云容器镜像服务) |
| 网络规划 | 容器间通信、端口映射 |
二、手动部署 - 后端(Tlias 项目)
项目背景:Tlias 是一个 Spring Boot 项目,使用 MySQL 数据库,需要部署后端 Jar 包和前端 Nginx 静态资源。

步骤1:修改配置文件 - 数据库连接
目的:让后端应用连接 Docker 容器中的 MySQL
为什么要修改?
之前在本地开发时,配置文件中的数据库连接是 localhost:3306,但现在 MySQL 运行在 Docker 容器中,需要使用容器名进行通信。
修改前(本地开发):
# application.yml (修改前)
spring:
datasource:
url: jdbc:mysql://localhost:3306/tlias?useSSL=false&serverTimezone=UTC
username: root
password: 123456
修改后(Docker 部署):
application.yml (修改后)
spring:
datasource:
url: jdbc:mysql://mysql:3306/tlias?useSSL=false&serverTimezone=UTC
username: root
password: 123456

关键改变:localhost → mysql
这里的 mysql 是 MySQL 容器的名称,因为 Docker 自定义网络支持容器名解析,所以可以直接用容器名通信,不需要 IP 地址。
步骤2:编写 Dockerfile 镜像文件
目的:定义如何构建后端应用的 Docker 镜像
完整的 Dockerfile 内容:
步骤3:准备文件并构建镜像
目的:将 Dockerfile、JAR 包、JDK 放到同一目录,然后构建镜像
文件目录结构:
构建镜像命令:
# 进入到 Dockerfile 所在的目录
cd /opt/tlias
# 构建镜像
docker build -t tlias:1.0 .
# ↑ ↑ ↑
# 标签名 版本 当前目录(Dockerfile 位置)
步骤4:创建并运行容器
目的:根据镜像创建容器,并启动应用
完整命令:
docker run -d \
--name tlias-app \ # 容器名称(方便后续操作)
--network Leaf666 \ # 加入到 Leaf666 网络(与 MySQL 容器通信)
-p 8080:8080 \ # 端口映射:宿主机端口:容器端口
tlias:1.0 # 使用的镜像名称:版本
⚠️ 关键点:--network Leaf666
只有加入到同一个网络的容器,才能通过容器名互相访问。这就是为什么配置文件中可以用 mysql(容器名)而不是 IP 地址。

三、手动部署 - 前端(Nginx 静态资源)
步骤1:准备 Nginx 资源和配置文件
Nginx 配置文件示例(nginx.conf):

步骤2:创建并运行 Nginx 容器
docker run -d \
--name nginx-web \
--network Leaf666 \
-p 80:80 \
-v /opt/nginx/html:/usr/share/nginx/html \
-v /opt/nginx/nginx.conf:/etc/nginx/nginx.conf \
nginx:latest

💡 关于数据卷(Volume):
-v 参数实现了宿主机目录 和容器目录 的映射。
好处:修改宿主机的文件,容器内的文件会同步更新,无需重建容器。
验证 Nginx 是否正常运行:
# 浏览器访问 http://服务器IP
# 如果看到前端页面,说明部署成功
# 或者查看容器状态
docker ps
# 应该看到 nginx-web 容器在运行

四、Docker Compose 一键部署
为什么需要 Docker Compose?
手动部署时,需要一层一层捋清楚容器之间的关系(谁依赖谁、网络怎么配置、启动顺序等)。
如果部署的容器多了(如 MySQL + Redis + 后端 + 前端 + Nginx),手动管理会非常麻烦。
Docker Compose 可以一键定义和启动所有容器!
4.1 手动部署 vs Docker Compose 对照表
|------------------------------------|---------------------------------------|-------------|
| 手动部署命令 | Docker Compose 配置 | 说明 |
| docker run --name mysql ... | services: mysql: | 定义 MySQL 服务 |
| --network Leaf666 | networks: - leaf666 | 加入网络 |
| -v mysql-data:/var/lib/mysql | volumes: - mysql-data:/var/lib/mysql | 数据持久化 |
| -e MYSQL_ROOT_PASSWORD=123 | environment: MYSQL_ROOT_PASSWORD: 123 | 环境变量 |
| docker run -d --name tlias-app ... | services: app: depends_on: - mysql | 定义依赖关系 |

4.2 编写 docker-compose.yml 文件
完整的 docker-compose.yml 文件内容:
java
version: '3.8' # Docker Compose 文件版本(根据 Docker 版本选择)
services:
# ========== MySQL 数据库服务 ==========
mysql:
image: mysql:8.0 # 使用 MySQL 8.0 官方镜像
container_name: mysql # 容器名称(其他容器可以通过这个名称访问)
ports:
- "3306:3306" # 端口映射:宿主机3306 → 容器3306
environment: # 环境变量(相当于 docker run -e)
MYSQL_ROOT_PASSWORD: 123456 # MySQL root 用户密码
MYSQL_DATABASE: tlias # 自动创建的数据库名称
volumes:
- mysql-data:/var/lib/mysql # 数据卷:MySQL 数据持久化
- ./mysql/init.sql:/docker-entrypoint-initdb.d/init.sql # 初始化 SQL
networks:
- leaf666 # 加入到 leaf666 网络
# ========== 后端应用服务 ==========
app:
build: # 构建镜像(而不是使用现成的镜像)
context: ./ # Dockerfile 所在的目录
dockerfile: Dockerfile # Dockerfile 文件名
container_name: tlias-app # 容器名称
ports:
- "8080:8080" # 端口映射
depends_on:
- mysql # 依赖 MySQL 服务(会等 MySQL 启动后再启动)
networks:
- leaf666 # 加入到同一个网络
# ========== Nginx 前端服务 ==========
nginx:
image: nginx:latest # 使用 Nginx 官方镜像
container_name: nginx-web # 容器名称
ports:
- "80:80" # 端口映射
volumes:
- ./nginx/html:/usr/share/nginx/html # 挂载静态文件
- ./nginx/nginx.conf:/etc/nginx/nginx.conf # 挂载配置文件
depends_on:
- app # 依赖后端服务
networks:
- leaf666 # 加入到同一个网络
# ========== 定义网络 ==========
networks:
leaf666:
driver: bridge # 使用桥接网络(默认)
# ========== 定义数据卷 ==========
volumes:
mysql-data: # 具名数据卷(MySQL 数据持久化)
为什么这样写?
1. version: '3.8'
Docker Compose 文件版本,不同版本的 Docker Engine 支持不同的 Compose 版本。3.8 是最常用的稳定版本。
2. services(服务定义)
每个服务对应一个容器。Compose 会自动处理:
- 网络创建 :自动创建
leaf666网络,所有服务都加入这个网络 - 启动顺序 :通过
depends_on控制(先启动 MySQL,再启动 app) - 容器通信 :服务名(如
mysql、app)就是容器名,可以直接用来通信
3. volumes(数据卷)
mysql-data:/var/lib/mysql 表示:
mysql-data是 Docker 管理的具名数据卷/var/lib/mysql是 MySQL 容器内的数据目录- 即使容器被删除,数据也不会丢失(数据卷独立于容器)
4. depends_on(依赖关系)
确保启动顺序:MySQL → app → nginx。但注意:
⚠️ depends_on 只保证启动顺序,不保证 MySQL 完全就绪!
如果 MySQL 启动慢,app 可能会在 MySQL 还没完全就绪时就尝试连接。
解决方法:在 app 中添加重试逻辑,或使用 wait-for-it 脚本。
4.3 使用 Docker Compose 部署

java
进入到 docker-compose.yml 所在的目录
cd /opt/tlias-compose
# 一键启动所有服务
docker compose up -d
# ↑
# -d 表示后台运行(detached 模式)
命令详解:
| 命令 | 说明 |
|---|---|
docker compose up |
启动所有服务(会构建镜像、创建容器、启动容器) |
-d |
后台运行 |
docker compose down |
停止并删除所有容器、网络(数据卷默认保留) |
docker compose ps |
查看所有服务的状态 |
docker compose logs |
查看所有服务的日志 |
执行过程示例:
$ docker compose up -d
[+] Running 4/4
✔ Network tlias-compose_leaf666 Created # 自动创建网络
✔ Container mysql Started # 启动 MySQL 容器
✔ Container tlias-app Started # 启动后端容器
✔ Container nginx-web Started # 启动 Nginx 容器
✅ 就这么简单!一个命令启动了 3 个容器,并自动配置了网络、数据卷、依赖关系。
4.4 Docker Compose 常用命令
| 命令 | 说明 | 示例 |
|---|---|---|
docker compose up -d |
启动所有服务(后台运行) | docker compose up -d |
docker compose down |
停止并删除所有容器、网络 | docker compose down |
docker compose down -v |
停止并删除容器、网络、数据卷 | docker compose down -v |
docker compose ps |
查看所有服务的状态 | docker compose ps |
docker compose logs [服务名] |
查看日志(所有服务或指定服务) | docker compose logs mysql |
docker compose build |
只构建镜像,不启动容器 | docker compose build |
docker compose restart [服务名] |
重启服务 | docker compose restart app |
docker compose stop [服务名] |
停止服务(不删除容器) | docker compose stop app |
docker compose start [服务名] |
启动已停止的服务 | docker compose start app |
⚠️ 注意: docker compose down 不会删除数据卷(除非加 -v 参数)。
这意味着:即使删除容器,MySQL 中的数据也不会丢失。
五、手动部署 vs Docker Compose 对比总结
| 对比项 | 手动部署 | Docker Compose |
|---|---|---|
| 部署步骤 | 需要手动执行多个 docker run 命令 |
一个 docker compose up -d 搞定 |
| 网络配置 | 需要手动创建网络,并让每个容器加入 | 自动创建网络,所有服务自动加入 |
| 依赖管理 | 需要手动控制启动顺序 | 通过 depends_on 自动管理 |
| 配置管理 | 命令参数复杂,容易出错 | YAML 文件清晰易读,便于版本管理 |
| 适用场景 | 简单项目、学习测试 | 生产环境、多容器项目 |
附录:常见问题 FAQ
- Q1:为什么修改配置文件后,需要用容器名而不是 localhost?
答:因为 MySQL 运行在容器中,localhost 指的是容器本身的 localhost,而不是宿主机的 localhost。在同一个 Docker 网络中,应该使用容器名进行通信。
- Q2:如何查看容器日志?
手动部署时
docker logs 容器名
Docker Compose 部署时
docker compose logs 服务名
- Q3:如果修改了 docker-compose.yml,如何生效?
重新构建并启动
docker compose up -d --build