Docker:项目部署

大家好,这依然是一篇个人笔记

本次笔记内容是有关于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)
  • 容器通信 :服务名(如 mysqlapp)就是容器名,可以直接用来通信

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

  1. Q1:为什么修改配置文件后,需要用容器名而不是 localhost?

答:因为 MySQL 运行在容器中,localhost 指的是容器本身的 localhost,而不是宿主机的 localhost。在同一个 Docker 网络中,应该使用容器名进行通信。

  1. Q2:如何查看容器日志?

手动部署时

docker logs 容器名

Docker Compose 部署时

docker compose logs 服务名

  1. Q3:如果修改了 docker-compose.yml,如何生效?

重新构建并启动

docker compose up -d --build

相关推荐
爱学习 爱分享6 小时前
docker 本地装瀚高 4.5 数据库
数据库·docker·容器
汉得数字平台6 小时前
集星獭 | 编排高频问题・快速排查
运维
codinglf6 小时前
大模型质检盒子实测:7天破解制造质检困局
大数据·运维·人工智能
雅斯驰6 小时前
4Gbit密度+16位总线宽度:H5AN4G6NBJR-UHC在DDR4成熟期的产品定位
运维·单片机·嵌入式硬件·物联网·自动化
Mr数据杨6 小时前
埃姆斯住宅房价预测与自动化估值建模
运维·机器学习·数据分析·自动化·kaggle
Danileaf_Guo6 小时前
手搓KVM虚拟化!Ubuntu 26.04 + KVM 7.0.0,告别VMware的低成本玩法
linux·运维·服务器·ubuntu
孙高飞6 小时前
AI生成接口自动化测试用例最佳实践(附skill设计思路)
运维·自动化·测试用例
中海德--陈顺真6 小时前
HONEYWELL 扫描架控制板 51000398
运维·服务器·人工智能
叶总没有会6 小时前
Docker入门
运维·docker·容器