告别“本地跑得通,换台机器就报错”的噩梦,把你的 AI 系统打包成标准镜像
01 引子
经过前二十篇的实战,你的 MyAI 项目已经非常强大了:
-
有 Spring Boot 应用
-
有 PostgreSQL + pgvector 向量数据库
-
有 Redis 缓存服务
在本地 IDEA 里,它跑得完美无缺。但这存在一个致命问题:它离不开你的电脑。
如果让你把项目发给同事,或者部署到云服务器上,你需要对方手动安装 JDK 21、装 PostgreSQL、装 Redis,还要配置各种网络和密码。稍微有一个环节版本不对,系统就会崩溃。
这一篇的目标:使用 Docker 和 Docker Compose,把应用、数据库、缓存打包成一个整体。别人拿到你的代码,只需一行命令,就能在世界上任何一台装了 Docker 的机器上完美运行。
02 为什么是 Docker Compose?
对于单体应用,用 Dockerfile 打个镜像就够了。但 AI 应用是一个微服务集群:
-
应用需要连接数据库
-
应用需要连接 Redis
-
数据库和 Redis 需要在同一个内部网络中互相通信
docker-compose 就是用来编排多容器的神器。我们只需要写一个 YAML 文件,就能把这三个组件一键拉起,并自动配置好内部的局域网。
03 核心实现
第一步:编写多阶段 Dockerfile
在项目根目录新建 Dockerfile。为了减小最终镜像的体积(从 800MB 降到 200MB),我们采用多阶段构建:
# ========================================== # 阶段一:构建阶段 (用 Maven 编译代码) # ========================================== FROM maven:3.9-eclipse-temurin-21 AS builder WORKDIR /app # 先复制 pom.xml 并下载依赖(利用 Docker 缓存,代码变了依赖不用重新下) COPY pom.xml . RUN mvn dependency:go-offline -B # 再复制源码并打包 COPY src ./src RUN mvn clean package -DskipTests # ========================================== # 阶段二:运行阶段 (只保留 JRE 和打好的 jar 包) # ========================================== FROM eclipse-temurin:21-jre-alpine WORKDIR /app # 从构建阶段把 Fat JAR 复制过来 COPY --from=builder /app/target/myai-0.0.1-SNAPSHOT.jar app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "app.jar"]
第二步:编写 docker-compose.yml
在项目根目录新建 docker-compose.yml。这是整个微服务集群的“总指挥”:
services:
# 1. Spring Boot AI 应用
myai-app:
build: .
container_name: myai-app
ports:
- "8080:8080"
environment:
# 关键:容器内网络通信,指向下方的服务名
- SPRING_DATASOURCE_URL=jdbc:postgresql://pgvector-db:5432/myai
- SPRING_DATA_REDIS_HOST=redis-cache
# 从 .env 文件中读取 API Key,避免代码明文泄露
- SPRING_AI_DASHSCOPE_API_KEY=${DASHSCOPE_API_KEY}
depends_on:
pgvector-db:
condition: service_healthy
networks:
- myai-network
# 2. 向量数据库
pgvector-db:
image: pgvector/pgvector:pg16
container_name: pgvector-db
ports:
- "5432:5432"
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: 123456
POSTGRES_DB: myai
volumes:
- pgdata:/var/lib/postgresql/data # 数据持久化
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d myai"]
interval: 5s
timeout: 5s
retries: 5
networks:
- myai-network
# 3. Redis 缓存
redis-cache:
image: redis:alpine
container_name: redis-cache
ports:
- "6379:6379"
volumes:
- redisdata:/data
networks:
- myai-network
volumes:
pgdata:
redisdata:
networks:
myai-network:
driver: bridge
第三步:安全注入 API Key(.env 文件)
千万不要把 API Key 写死在 docker-compose.yml 或 application.yml 里,否则代码传到 GitHub 上会立刻被盗刷。
在根目录新建一个名为 .env 的文件,写入真实 Key:
DASHSCOPE_API_KEY=sk-你的真实APIKey
⚠️ 务必注意:打开 .gitignore 文件,加上一行 .env。
04 踩坑记录(实战避坑)
在这一步,很多 Java 开发者会踩两个极其经典的坑:
坑一:no main manifest attribute, in app.jar
现象:容器启动瞬间退出,日志报错找不到主清单属性。
原因:你的 pom.xml 中 spring-boot-maven-plugin 的 <configuration> 里,可能写了 <skip>true</skip>。这会导致 Maven 只打了一个普通 JAR,而不是可执行的 Fat JAR。
解决:删掉 <skip>true</skip>,或者确保包含 <goal>repackage</goal>。
坑二:DashScope API key must be set
现象:应用启动报错,说环境里找不到 API Key。
原因:Spring Boot 的环境变量映射机制要求非常严格。在 docker-compose.yml 中注入的变量名,必须全大写,且用下划线。
解决:Spring Boot 会将 SPRING_AI_DASHSCOPE_API_KEY 自动映射为 spring.ai.dashscope.api-key。千万不要写成别的奇奇怪怪的名字。
05 一键启动!
修改完代码和配置后,在 IDEA 的终端里执行:
docker-compose up -d --build

你会看到什么?
-
Docker 会按照
Dockerfile的步骤,自动下载 Maven 环境,编译你的代码,打包镜像。 -
自动去云端拉取 PostgreSQL 和 Redis 镜像。
-
创建内部网络。
-
依次启动三个容器。
等终端出现绿色的 Running后,打开 Docker Desktop,你会看到三个容器整整齐齐地跑在 myai-network 下。

此时你访问 http://localhost:8080/api/thread/info,接口完美响应!
06 成果总结
到这一步,你已经彻底打通了 Java AI 应用交付的“最后一公里”:
| 能力 | 状态 |
|---|---|
| 多阶段构建 | ✅ 镜像瘦身 |
| 环境隔离 | ✅ 容器化部署 |
| 网络互通 | ✅ 服务名互连 |
| 数据持久化 | ✅ Volume 挂载 |
| 密钥安全 | ✅ .env 注入 |
现在,你的项目已经是一个开箱即用的开源级作品。任何人下载你的代码,只需 docker-compose up -d,无需任何复杂配置,就能完美体验你的智能体。
07 下期预告
部署上线后,应用是跑起来了,但你怎么知道它跑得好不好?
如果用户的某次提问卡了 10 秒,或者调用的 Token 突然暴增,你在本地终端是看不到这些数据的。
下一篇:AI 应用的可观测性——链路追踪与监控告警。 我们将引入 Micrometer 和 Prometheus,把你的 AI 应用彻底变成“透明”的。
📌 我是超超不吵吵,10年 Java 全栈,正在转型 AI 应用开发。
每周一篇实战笔记,不贩卖焦虑,只分享能落地的技术。
全网同名,欢迎关注。
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/shizhewan_2/article/details/168655775




