1.1 Docker概述,建立现代化部署体系初印象
1. Docker的核心定义
Docker是基于Linux容器(LXC)的轻量级虚拟化技术,核心是将应用及其所有依赖(库、配置、运行时)打包成“容器镜像”,使得应用可以在任何支持Docker的环境中“一次构建,处处运行”,解决了传统部署的“环境地狱”问题。
2. Docker的核心价值(针对全栈项目)
| 价值维度 | 具体体现 |
|---|---|
| 环境一致性 | Java后端、Vue.js前端、数据库、Redis、Kafka依赖打包成镜像,开发/测试/生产环境完全一致 |
| 轻量级高效 | 容器基于宿主机内核运行,无需虚拟操作系统,启动秒级(对比VMware快10倍以上) |
| 资源隔离与可控 | 为容器分配指定CPU/内存/GPU资源,避免单应用占用全部资源 |
| 快速迭代部署 | 镜像版本化管理,更新应用仅需替换镜像并重启容器,回滚仅需切换镜像版本 |
| 规模化适配 | 配合编排工具(Compose/K8s),快速实现服务的多实例部署、扩缩容 |
3. Docker与传统部署/虚拟机的对比
| 部署方式 | 环境一致性 | 启动速度 | 资源占用 | 扩缩容难度 | 场景适配性 |
|---|---|---|---|---|---|
| 传统物理机/虚拟机 | 差(依赖手动配置) | 分钟级 | 高(占用完整OS资源) | 高(需手动部署) | 差(GPU分配复杂) |
| Docker容器 | 优(镜像打包所有依赖) | 秒级 | 低(共享宿主机内核) | 低(编排工具一键扩缩容) | 优(支持GPU容器、模型挂载) |
1.2 Docker安装与环境搭建,快速完成开发环境标准化
Docker支持Linux、Windows、macOS,以下聚焦生产环境主流的Linux(CentOS 7/8) 安装,及开发环境的Docker Desktop安装。
1. Linux(CentOS)安装Docker
(1)前置准备:卸载旧版本(如有)
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
(2)安装依赖包
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
(3)配置阿里云镜像源(加速安装)
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
(4)安装Docker CE(社区版)
sudo yum install -y docker-ce docker-ce-cli containerd.io
(5)启动并设置开机自启
# 启动Docker
sudo systemctl start docker
# 设置开机自启
sudo systemctl enable docker
# 验证安装
docker --version
# 运行测试容器(hello-world)
sudo docker run hello-world
(6)配置镜像加速(解决拉取镜像慢的问题)
国内访问Docker Hub速度慢,需配置阿里云/网易云镜像加速:
# 创建配置目录
sudo mkdir -p /etc/docker
# 写入镜像加速配置
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://你的阿里云镜像加速地址.mirror.aliyuncs.com"]
}
EOF
# 重启Docker服务
sudo systemctl daemon-reload
sudo systemctl restart docker
2. Windows/macOS安装Docker Desktop
- 下载地址:Docker官方下载;
- 安装要点:
- Windows需开启“Hyper-V”和“容器功能”(Win10/11专业版),家庭版需安装WSL2;
- 安装后在设置中配置国内镜像加速(同Linux的daemon.json配置);
- 验证:打开终端执行
docker --version和docker run hello-world。
3. 开发环境标准化:一键搭建全栈项目基础环境
以“Spring AI+Redis+Milvus”为例,通过Docker Compose一键搭建环境:
(1)编写docker-compose.yml
version: '3.8'
services:
# Redis:存储对话上下文
redis:
image: redis:7.0-alpine
ports:
- "6379:6379"
volumes:
- redis-data:/data
restart: always
# Milvus:向量数据库(用于RAG)
milvus:
image: milvusdb/milvus:v2.3.0
ports:
- "19530:19530"
volumes:
- milvus-data:/var/lib/milvus
environment:
- MILVUS_MODE=standalone
restart: always
volumes:
redis-data:
milvus-data:
(2)启动环境
# 启动所有服务(后台运行)
docker-compose up -d
# 查看容器状态
docker-compose ps
# 停止服务
docker-compose down
新人入职仅需执行上述命令,5分钟即可完成Redis+Milvus环境搭建,无需手动安装配置,实现开发环境标准化。
1.3 Docker核心概念深度解析:避免90%的容器化设计陷阱
Docker的核心概念是理解容器化设计的关键,错误的认知会导致镜像臃肿、容器隔离失效、数据丢失等问题,以下解析核心概念及避坑要点:
1. 镜像(Image):容器的“只读模板”
- 定义:镜像是打包了应用代码、依赖、运行时、配置的只读文件,是创建容器的基础;
- 特性:
- 分层存储:镜像由多个只读层叠加而成(如基础层JDK24、应用层业务代码),分层可复用,减少镜像体积;
- 不可修改:镜像构建后只读,如需修改需重新构建新镜像;
- 避坑陷阱: ❌ 陷阱1:镜像分层过多/过大(如在镜像中安装无关工具、未清理构建缓存)→ 导致镜像体积GB级,拉取/部署慢; ✅ 解决方案:使用多阶段构建(Multi-stage Build),仅保留运行时依赖;构建后清理yum/apk缓存; ❌ 陷阱2:使用最新版镜像(latest tag)→ 生产环境镜像版本不可控,易引发兼容性问题; ✅ 解决方案:镜像指定具体版本(如redis:7.0-alpine,而非redis:latest);
2. 容器(Container):镜像的“运行实例”
- 定义:容器是镜像的可运行实例,在镜像只读层之上添加一层“可写层”,实现应用运行;
- 特性:
- 隔离性:容器拥有独立的网络、进程、文件系统空间,与宿主机/其他容器隔离;
- 临时性:默认情况下,容器内的可写层数据在容器删除后丢失;
- 避坑陷阱:
❌ 陷阱1:将AI模型文件、业务数据存储在容器可写层→ 容器删除后数据丢失;
✅ 解决方案:通过“数据卷(Volume)”或“绑定挂载(Bind Mount)”将数据存储到宿主机;
❌ 陷阱2:容器启动时未配置“重启策略”→ 宿主机重启后容器无法自动恢复;
✅ 解决方案:启动容器时指定
--restart=always(始终重启)或--restart=on-failure:3(失败时重启3次); ❌ 陷阱3:容器占用端口与宿主机/其他容器冲突→ 启动失败; ✅ 解决方案:使用动态端口映射(如-p 0:8080),或通过编排工具管理端口。
3. 数据卷(Volume):容器的数据“持久化方案”
- 定义:数据卷是宿主机文件系统的专用目录,用于存储容器数据,独立于容器生命周期;
- 特性:
- 持久化:容器删除后,数据卷中的数据仍保留;
- 可共享:多个容器可挂载同一个数据卷,实现数据共享;
- 避坑陷阱:
❌ 陷阱:使用“绑定挂载”替代数据卷,且挂载路径权限配置错误→ 容器无权限读写数据;
✅ 解决方案:优先使用命名数据卷(如
docker volume create ai-data),挂载时指定权限(如-v ai-data:/app/data:rw)。
4. 网络(Network):容器间的“通信桥梁”
- 定义:Docker网络用于容器间、容器与宿主机的通信,默认包含bridge(桥接)、host(主机网络)、none(无网络)三种模式;
- 避坑陷阱:
❌ 陷阱1:所有容器使用默认bridge网络→ 容器间只能通过IP通信,IP变化后无法访问;
✅ 解决方案:创建自定义网络(如
docker network create ai-network),容器接入后可通过容器名通信; ❌ 陷阱2:生产环境使用host网络→ 容器与宿主机共享网络命名空间,失去隔离性; ✅ 解决方案:仅在特殊场景(如需要高性能网络)使用host网络,生产环境优先自定义bridge网络。
5. Dockerfile:构建镜像的“脚本文件”
- 定义:Dockerfile是文本文件,包含构建镜像的一系列指令(如FROM、RUN、COPY、CMD);
- 避坑陷阱:
❌ 陷阱1:RUN指令过多(如每个命令单独RUN)→ 镜像分层过多,体积增大;
✅ 解决方案:将多个RUN指令合并为一个,用
&&连接,且清理缓存(如RUN yum install -y xxx && yum clean all); ❌ 陷阱2:使用ROOT用户运行容器→ 存在安全风险; ✅ 解决方案:在Dockerfile中创建普通用户(RUN useradd -m aiuser),并通过USER aiuser切换用户; ❌ 陷阱3:CMD与ENTRYPOINT混用不当→ 容器启动命令执行异常; ✅ 解决方案:ENTRYPOINT定义固定执行命令,CMD传递默认参数(如ENTRYPOINT ["java", "-jar"],CMD ["app.jar"])。
2.1 镜像操作实战:斩获让环境部署效率提升80%的秘籍
镜像操作是Docker的核心实战技能,掌握镜像的构建、优化、推送、拉取,能大幅提升全栈项目部署效率,以下聚焦高频实战场景:
验证安装
运行 docker --version 检查版本,确保 Docker 可用
设置Docker国内镜像仓库
镜像仓库是Docker的必经之路,Docker Hub是官方提供的公共镜像仓库,但Docker Hub在国内无法访问或者速度慢。因此需要设置国内镜像仓库,提升镜像拉取效率。
临时:
docker pull docker.xuanyuan.me/hello-world
{
// ...
"registry-mirrors": ["https://docker.1ms.run"]
}
1. 基础镜像操作:拉取/查看/删除
# 查找镜像
docker search nginx
# 拉取镜像(指定版本)
docker pull hello-world:latest
docker pull nginx:latest
# 查看本地镜像
docker images # 列出所有镜像
docker images -q # 仅列出镜像ID
# 删除镜像(需先停止/删除依赖该镜像的容器)
docker rmi 镜像ID/镜像名:版本
# 强制删除
docker rmi -f 镜像ID
# 清理未使用的镜像(悬空镜像)
docker image prune -a
2. 实战:编写全栈项目Dockerfile
以“Spring AI集成通义千问”的Java项目为例,编写优化后的Dockerfile:
# 阶段1:构建应用(多阶段构建,仅保留运行时依赖)
FROM maven:3.8.5-openjdk-17 AS builder
# 设置工作目录
WORKDIR /app
# 复制pom.xml并下载依赖(利用缓存,依赖不变时无需重新下载)
COPY pom.xml .
RUN mvn dependency:go-offline -B
# 复制源码并打包
COPY src ./src
RUN mvn package -DskipTests
# 阶段2:运行应用(使用轻量级基础镜像)
FROM openjdk:17-jdk-slim
# 创建普通用户
RUN useradd -m aiuser && chown -R aiuser /app
USER aiuser
# 设置工作目录
WORKDIR /app
# 从构建阶段复制打包后的jar包
COPY --from=builder /app/target/*.jar app.jar
# 暴露端口
EXPOSE 8080
# 启动命令(ENTRYPOINT+CMD组合)
ENTRYPOINT ["java", "-jar", "-Xmx512m"] # 限制内存
CMD ["app.jar"]
优化要点:
- 多阶段构建:构建阶段用maven镜像,运行阶段用轻量级openjdk镜像,减少镜像体积;
- 依赖缓存:先复制pom.xml下载依赖,源码变更时无需重新下载依赖;
- 资源限制:启动时指定
-Xmx512m限制内存,避免占用过多资源; - 安全加固:使用普通用户运行,避免ROOT权限。
3. 构建镜像:从Dockerfile到可运行镜像
# 构建镜像(-t指定标签:名称:版本)
docker build -t rn-nginx:1.0 .
# 构建时指定Dockerfile路径(非当前目录)
docker build -t rn-nginx:1.0 -f ./docker/Dockerfile .
4. 镜像优化:将体积从GB级降到百MB级
全栈项目镜像易臃肿,以下是核心优化技巧:
| 优化手段 | 具体操作 |
|---|---|
| 多阶段构建 | 分离构建/运行阶段,仅保留运行时依赖 |
| 选择轻量级镜像 | 使用alpine/slim版本镜像(如openjdk:17-jdk-slim vs openjdk:17) |
| 清理构建缓存 | RUN指令后清理yum/apk/mvn缓存(如RUN mvn package && rm -rf ~/.m2) |
| 合并RUN指令 | 将多个RUN指令合并为一个,减少分层(如RUN apt update && apt install -y xxx && apt clean) |
| 排除无关文件 | 编写.dockerignore文件(排除.git、target、logs等),避免复制无关文件 |
5. 镜像推送:上传到阿里云镜像仓库(企业级)
(1)登录阿里云镜像仓库
docker login --username=你的阿里云账号 registry.cn-hangzhou.aliyuncs.com
(2)为镜像打标签(符合仓库规范)
docker tag rn-nginx:1.0 registry.cn-hangzhou.aliyuncs.com/你的命名空间/rn-nginx:1.0
(3)推送镜像
docker push registry.cn-hangzhou.aliyuncs.com/你的命名空间/rn-nginx:1.0
(4)拉取私有镜像(部署时)
docker pull registry.cn-hangzhou.aliyuncs.com/你的命名空间/rn-nginx:1.0
6. 效率秘籍:镜像复用与版本管理
- 制作基础镜像:将全栈项目通用依赖制作成基础镜像,所有子项目基于该镜像构建,减少重复构建;
- 版本语义化:镜像版本遵循“主版本.次版本.补丁”(如1.0.0),避免随意命名;
- 镜像缓存策略:开发环境保留常用镜像,生产环境仅拉取指定版本镜像,定期清理无用镜像。
2.2 容器操作实战,建立标准化启停与监控机制
容器操作是将镜像转化为运行服务的核心,需建立“启动-运行-监控-停止”的标准化流程,保障AI服务稳定运行。
1. 容器启动:标准化启动参数(以Spring AI为例)
# 启动容器(核心参数)
docker run -d \
--name rn-nginx \ # 容器名称(标准化命名:服务名-环境)
-p 80:80 \ # 端口映射(宿主机:容器)
nginx # 镜像名称
2. 容器运行监控:实时掌握AI服务状态
(1)基础监控命令
# 查看运行中的容器
docker ps
# 查看所有容器(包括停止的)
docker ps -a
# 查看容器日志(实时跟踪)
docker logs -f rn-nginx
# 查看容器资源占用(CPU/内存/网络)
docker stats rn-nginx
# 进入容器内部(调试用)
docker exec -it rn-nginx /bin/bash
# 查看容器详细信息
docker inspect rn-nginx
(2)AI场景进阶监控:日志与指标收集
- 日志标准化:将Spring AI日志输出到stdout(Docker默认收集),配合ELK栈收集分析;
- 指标暴露:通过Spring Boot Actuator暴露监控指标(/actuator/prometheus),Prometheus采集容器指标;
- GPU监控(AI推理场景):安装nvidia-docker,通过
docker stats监控GPU使用率。
3. 容器运维:常用操作(标准化流程)
# 重启容器
docker restart rn-nginx
# 暂停/恢复容器
docker pause rn-nginx
docker unpause rn-nginx
# 更新容器配置(如重启策略)
docker update --restart=always rn-nginx
# 停止容器
docker stop rn-nginx
# 删除容器(需先停止)
docker rm rn-nginx
# 批量停止/删除容器(运维批量操作)
docker stop $(docker ps -q --filter name=spring-ai-)
docker rm $(docker ps -aq --filter name=spring-ai-)
4. 故障排查:容器化AI服务常见问题定位
| 问题现象 | 排查步骤 |
|---|---|
| 容器启动失败 | 1. 执行docker logs 容器名查看日志;2. 检查端口是否被占用;3. 检查镜像是否存在 |
| AI服务响应慢 | 1. 执行docker stats查看资源占用;2. 检查容器网络是否通畅;3. 查看模型调用日志 |
| 数据丢失 | 1. 检查数据卷是否正确挂载;2. 执行docker volume inspect查看数据卷路径;3. 检查容器内文件权限 |
| API Key失效 | 1. 执行docker inspect查看环境变量;2. 重新启动容器并传递新的API Key |
5. 容器停止与清理:标准化下线流程
# 步骤1:停止容器
docker stop rn-nginx
# 步骤2:备份数据卷(如有必要)
cp -r /var/lib/docker/volumes/ai-data/_data /backup/ai-data-$(date +%Y%m%d)
# 步骤3:删除容器(如需下线)
docker rm rn-nginx
# 步骤4:清理无用容器/镜像/数据卷
docker system prune -a
3.1 容器编排全面解析,快速实现一键式的容器编排和部署
单容器部署无法满足全栈项目“多服务依赖”的需求,容器编排工具可实现多容器的“一键部署、依赖管理、扩缩容”,核心工具为Docker Compose(单机)和Kubernetes(K8s,集群),以下聚焦AI全栈工程师入门必备的Docker Compose。
1. 容器编排核心价值(AI场景)
- 一键部署:编写
docker-compose.yml定义所有服务,执行docker-compose up -d一键启动; - 依赖管理:自动处理服务启动顺序(如先启动Redis,再启动后端服务);
- 配置统一:所有服务的配置集中在一个文件,便于管理;
- 扩缩容简单:执行
docker-compose up -d --scale rn-nginx=3快速扩缩容; - 环境一致性:编排文件可提交到代码库,团队成员使用相同配置。
services:
nginx-server-1:
image: nginx:latest
hostname: nginx-server-1
container_name: nginx-server-1
deploy:
resources:
limits:
memory: 1G
ports:
- "80:81"
nginx-server-2:
image: nginx:latest
hostname: nginx-server-2
container_name: nginx-server-2
deploy:
resources:
limits:
memory: 1G
ports:
- "80:82"
2. Docker Compose vs Kubernetes:选型建议
| 特性 | Docker Compose | Kubernetes | 适用场景 |
|---|---|---|---|
| 部署规模 | 单机 | 集群 | Compose:中小规模全栈项目(单机);K8s:大规模/高可用AI服务 |
| 学习成本 | 低 | 高 | 入门选Compose,进阶学K8s |
| 扩缩容 | 简单(--scale) | 自动化(HPA) | Compose适合手动扩缩容,K8s支持自动扩缩容 |
| AI场景适配 | 基础(单机GPU) | 高级(集群GPU调度) | 开发/测试用Compose,生产集群用K8s |
3.2 容器编排文件编写技巧解读,掌握让部署配置效率提升 200% 的黄金法则
4-2 容器编排文件编写技巧解读:掌握让部署配置效率提升 200% 的黄金法则
docker-compose.yml是容器编排的核心,掌握编写技巧能大幅提升部署配置效率,以下结合全栈项目场景拆解黄金法则:
1. 黄金法则1:版本与结构标准化
- 使用最新稳定版本(如3.8),避免兼容问题;
- 结构分层:按
version→services→volumes→networks编写,逻辑清晰; - 服务命名标准化:
服务名-环境(如spring-ai-prod)。
2. 黄金法则2:利用依赖与启动顺序(AI多服务依赖)
全栈项目中Spring AI需依赖Redis/Milvus启动,通过depends_on控制顺序:
version: '3.8'
services:
spring-ai-qwen:
build: .
depends_on:
- redis
- milvus
# 其他配置...
redis:
image: redis:7.0-alpine
milvus:
image: milvusdb/milvus:v2.3.0
进阶:depends_on仅保证启动顺序,不保证服务就绪,需在Spring AI中添加健康检查(如等待Redis端口开放)。
3. 黄金法则3:环境变量与配置分离(避免硬编码)
通过env_file加载环境变量文件,不同环境使用不同文件:
# docker-compose.yml
services:
spring-ai-qwen:
env_file:
- .env.prod # 生产环境变量文件
environment:
- SPRING_PROFILES_ACTIVE=prod # 覆盖或新增变量
# .env.prod
SPRING_AI_ALIBABA_DASHSCOPE_API_KEY=你的APIKey
REDIS_HOST=redis
REDIS_PORT=6379
MILVUS_HOST=milvus
MILVUS_PORT=19530
4. 黄金法则4:资源限制与健康检查(保障AI服务稳定)
services:
spring-ai-qwen:
# 资源限制
deploy:
resources:
limits:
cpus: '1'
memory: 1g
reservations: # 预留资源
cpus: '0.5'
memory: 512m
# 健康检查(AI服务就绪判断)
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
interval: 30s # 检查间隔
timeout: 10s # 超时时间
retries: 3 # 重试次数
start_period: 60s # 启动后等待时间(AI服务启动可能较慢)
5. 黄金法则5:数据卷与网络复用(减少重复配置)
# 定义全局数据卷(所有服务可复用)
volumes:
redis-data:
milvus-data:
ai-log:
# 定义全局网络
networks:
ai-network:
driver: bridge
services:
spring-ai-qwen:
volumes:
- ai-log:/app/logs
networks:
- ai-network
redis:
volumes:
- redis-data:/data
networks:
- ai-network
6. 实战:全栈项目完整docker-compose.yml
version: '3.8'
# 全局网络
networks:
ai-network:
driver: bridge
# 全局数据卷
volumes:
redis-data:
milvus-data:
ai-log:
services:
# Redis:对话上下文存储
redis:
image: redis:7.0-alpine
networks:
- ai-network
volumes:
- redis-data:/data
restart: on-failure:3
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 3
# Milvus:向量数据库
milvus:
image: milvusdb/milvus:v2.3.0
networks:
- ai-network
volumes:
- milvus-data:/var/lib/milvus
environment:
- MILVUS_MODE=standalone
- ETCD_USE_EMBED=true
- MINIO_USE_EMBED=true
ports:
- "19530:19530"
restart: on-failure:3
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9091/healthz"]
interval: 30s
timeout: 10s
retries: 3
start_period: 120s
# Spring AI后端服务
spring-ai-qwen:
build: .
networks:
- ai-network
ports:
- "8080:8080"
volumes:
- ai-log:/app/logs
env_file:
- .env.prod
depends_on:
- redis
- milvus
restart: on-failure:3
deploy:
resources:
limits:
cpus: '1'
memory: 1g
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
3.3 容器编排常用命令深度解析,掌握规模化容器调度技巧
Docker Compose命令是规模化管理容器的核心,掌握以下命令能实现“一键部署、批量运维、扩缩容”,适配全栈项目的规模化部署需求。
1. 基础命令:启动/停止/查看(高频使用)
# 启动所有服务(后台运行,-d)
docker-compose up -d
# 启动指定服务(如仅启动Redis+Milvus)
docker-compose up -d redis milvus
# 查看服务状态
docker-compose ps
# 查看服务日志(指定服务+实时跟踪)
docker-compose logs -f spring-ai-qwen
# 停止所有服务
docker-compose stop
# 停止指定服务
docker-compose stop spring-ai-qwen
# 停止并删除容器、网络(保留数据卷)
docker-compose down
# 停止并删除容器、网络、数据卷(谨慎使用)
docker-compose down -v
2. 规模化调度:扩缩容(应用服务水平扩展)
# 扩缩容(如启动3个Spring AI实例)
docker-compose up -d --scale spring-ai-qwen=3
# 注意:需确保服务无状态(如会话存储在Redis),端口映射避免冲突(可使用动态端口:-p 0:8080)
3. 镜像更新:一键更新应用服务(无停机)
# 步骤1:重新构建镜像
docker-compose build spring-ai-qwen
# 步骤2:重启服务(使用新镜像)
docker-compose up -d --force-recreate spring-ai-qwen
4. 配置更新:无需重启的配置生效
# 重新加载配置(仅支持部分配置,如环境变量)
docker-compose up -d --no-deps --force-recreate spring-ai-qwen
# --no-deps:不重启依赖服务;--force-recreate:强制重建容器
5. 运维排查:批量操作与状态监控
# 查看所有服务的资源占用
docker-compose stats
# 进入指定服务容器
docker-compose exec spring-ai-qwen /bin/bash
# 查看服务依赖关系
docker-compose top
# 验证编排文件语法
docker-compose config
# 清理未使用的资源(容器、网络、镜像)
docker-compose down --rmi all --volumes
6. 规模化部署技巧:结合脚本实现一键运维
编写deploy.sh脚本,实现全栈项目的一键部署/更新/回滚:
#!/bin/bash
# deploy.sh:全栈项目一键部署脚本
# 部署环境(prod/test)
ENV=$1
if [ -z "$ENV" ]; then
echo "请指定环境:prod/test"
exit 1
fi
# 步骤1:验证配置文件
docker-compose -f docker-compose-$ENV.yml config
# 步骤2:构建镜像
docker-compose -f docker-compose-$ENV.yml build
# 步骤3:启动服务
docker-compose -f docker-compose-$ENV.yml up -d
# 步骤4:查看服务状态
docker-compose -f docker-compose-$ENV.yml ps
echo "部署完成!日志查看:docker-compose -f docker-compose-$ENV.yml logs -f"
使用方式:
# 部署生产环境
./deploy.sh prod
# 部署测试环境
./deploy.sh test
7. 生产环境进阶:结合CI/CD实现自动化编排
将Docker Compose命令集成到Jenkins/GitLab CI中,实现“代码提交→镜像构建→自动部署”:
# .gitlab-ci.yml示例
stages:
- build
- deploy
build:
stage: build
script:
- docker-compose build
- docker-compose push
deploy:
stage: deploy
script:
- docker-compose down
- docker-compose up -d
only:
- main # 仅主分支触发部署
总结
Docker容器化是AI全栈工程师突破部署运维瓶颈的核心技能,其核心价值在于环境标准化、部署高效化、运维规模化。掌握本文的核心内容:
- 从认知层理解Docker解决的全栈项目部署痛点;
- 从实战层掌握镜像构建、容器操作的标准化流程;
- 从规模化层掌握Docker Compose编排技巧,实现多服务一键部署;
- 结合AI场景优化(资源限制、GPU适配、数据持久化),保障服务稳定运行。
通过Docker容器化,全栈项目可实现“一次构建,处处运行”,部署效率提升80%以上,运维成本降低50%,是从“开发型工程师”向“全栈型工程师”进阶的必备技能。
1.1 如何进行全栈视角下的实现文件服务容器化改造?
MongoDB设置账号密码
接到 MongoDB
打开另一个终端窗口,使用 mongosh 命令连接到 MongoDB:
列出当前 MongoDB 实例的可用数据库:
db.getMongo().getDBNames()
切换到 rednote 数据库
使用 rednote 数据库来创建用户:
use rednote
创建用户
使用以下命令创建一个具有权限的用户:
db.createUser({
user: "admin", // 替换为你的用户名
pwd: "admin123", // 替换为你的密码
roles: [{ role: "readWrite", db: "rednote" }]
})
验证下
db.auth("admin", "admin123")
修改MonngoDB配置文件
原为 127.0.0.1,改为 0.0.0.0 允许所有IP访问
net:
bindIp: 0.0.0.0 # 原为 127.0.0.1,改为 0.0.0.0 允许所有IP访问
开放 MySQL 远程连接
默认情况下 MySQL 仅允许本地访问。以下是开启 MySQL 远程连接的详细步骤。
1. 修改 MySQL 用户权限
登录 MySQL:
mysql -u root -p
顾名思义,该方法就是直接修改更改“mysql”数据库里的“user”表里的“host”列,将“localhost”改为“%”。
use mysql;
select user,host from user;
update user set host='%' where user='root';
修改服务地址
将所有领域微服务应用的配置中的localhost、127.0.0.1 改为实际IP地址:
# 配置 MongoDB
#spring.data.mongodb.uri=mongodb://localhost:27017
spring.data.mongodb.grid-fs-database=rednote_files
spring.data.mongodb.host=192.168.68.157
spring.data.mongodb.port=27017
spring.data.mongodb.username=admin
spring.data.mongodb.password=admin123
spring.data.mongodb.database=rednote
spring.data.mongodb.authentication-database=rednote
# 数据库配置
spring.datasource.url=jdbc:mysql://192.168.68.157:3306/rednote_content_domain?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&allowMultiQueries=true&useSSL=false&allowPublicKeyRetrieval=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=
spring.datasource.url=jdbc:mysql://192.168.68.157:3306/rednote_user_domain?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&allowMultiQueries=true&useSSL=false&allowPublicKeyRetrieval=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=
# 配置 Nacos
spring.cloud.nacos.discovery.server-addr=192.168.68.157:8280
spring.cloud.nacos.config.server-addr=192.168.68.157:8280
seata.registry.nacos.server-addr=192.168.68.157:8280
制作Docker镜像
在领域微服务根目录下创建Dockerfile文件
# 指定基础镜像
FROM openjdk:24-ea-17-slim
# 创建目录,作为工作目录
RUN mkdir -p /rednote-file-microservice
WORKDIR /rednote-file-microservice
# 将文件复制到镜像中
COPY ./target/rednote-file-microservice-0.0.1-SNAPSHOT.jar app.jar
# 设置TZ时区
ENV TZ=Asia/Shanghai
# 声明要暴露的端口
EXPOSE 9010
# 启动应用
CMD ["java", "-jar", "app.jar"]
先执行Maven构建,生成rednote-file-microservice-0.0.1-SNAPSHOT.jar文件,而后在执行docker构建:
docker build -t rednote-file-microservice:1.0.0 .
容器启动
# 启动容器(核心参数)
docker run -d --name rednote-file-microservice -p 9010:9010 rednote-file-microservice:1.0.0
1.2 如何实现后台管理微服务容器化改造?
制作Docker镜像
在领域微服务根目录下创建Dockerfile文件
# 指定基础镜像
FROM openjdk:24-ea-17-slim
# 创建目录,作为工作目录
RUN mkdir -p /rednote-admin-microservice
WORKDIR /rednote-admin-microservice
# 将文件复制到镜像中
COPY ./target/rednote-admin-microservice-0.0.1-SNAPSHOT.jar app.jar
# 设置TZ时区
ENV TZ=Asia/Shanghai
# 声明要暴露的端口
EXPOSE 9040
# 启动应用
CMD ["java", "-jar", "app.jar"]
构建镜像及运行
docker build -t rednote-admin-microservice:1.0.0 .
docker run -d --name rednote-admin-microservice -p 9040:9040 rednote-admin-microservice:1.0.0
1.3 如何实现AI微服务容器化改造?
制作Docker镜像
在领域微服务根目录下创建Dockerfile文件
# 指定基础镜像
FROM openjdk:24-ea-17-slim
# 创建目录,作为工作目录
RUN mkdir -p /rednote-ai-microservice
WORKDIR /rednote-ai-microservice
# 将文件复制到镜像中
COPY ./target/rednote-ai-microservice-0.0.1-SNAPSHOT.jar app.jar
# 设置TZ时区
ENV TZ=Asia/Shanghai
# 声明要暴露的端口
EXPOSE 9050
# 启动应用
CMD ["java", "-jar", "app.jar"]
构建镜像及运行
docker build -t rednote-ai-microservice:1.0.0 .
docker run -d --name rednote-ai-microservice -p 9050:9050 rednote-ai-microservice:1.0.0
1.4 如何实现内容微服务容器化改造?
制作Docker镜像
在领域微服务根目录下创建Dockerfile文件
# 指定基础镜像
FROM openjdk:24-ea-17-slim
# 创建目录,作为工作目录
RUN mkdir -p /rednote-content-microservice
WORKDIR /rednote-content-microservice
# 将文件复制到镜像中
COPY ./target/rednote-content-microservice-0.0.1-SNAPSHOT.jar app.jar
# 设置TZ时区
ENV TZ=Asia/Shanghai
# 声明要暴露的端口
EXPOSE 9030
# 启动应用
CMD ["java", "-jar", "app.jar"]
构建镜像及运行
docker build -t rednote-content-microservice:1.0.0 .
docker run -d --name rednote-content-microservice -p 9030:9030 rednote-content-microservice:1.0.0
1.5 如何实现网关微服务容器化改造?
制作Docker镜像
在领域微服务根目录下创建Dockerfile文件
# 指定基础镜像
FROM openjdk:24-ea-17-slim
# 创建目录,作为工作目录
RUN mkdir -p /rednote-gateway-microservice
WORKDIR /rednote-gateway-microservice
# 将文件复制到镜像中
COPY ./target/rednote-gateway-microservice-0.0.1-SNAPSHOT.jar app.jar
# 设置TZ时区
ENV TZ=Asia/Shanghai
# 声明要暴露的端口
EXPOSE 8080
# 启动应用
CMD ["java", "-jar", "app.jar"]
构建镜像及运行
docker build -t rednote-gateway-microservice:1.0.0 .
docker run -d --name rednote-gateway-microservice -p 8080:8080 rednote-gateway-microservice:1.0.0
1.6 如何实现用户微服务容器化改造?
制作Docker镜像
在领域微服务根目录下创建Dockerfile文件
# 指定基础镜像
FROM openjdk:24-ea-17-slim
# 创建目录,作为工作目录
RUN mkdir -p /rednote-user-microservice
WORKDIR /rednote-user-microservice
# 将文件复制到镜像中
COPY ./target/rednote-user-microservice-0.0.1-SNAPSHOT.jar app.jar
# 设置TZ时区
ENV TZ=Asia/Shanghai
# 声明要暴露的端口
EXPOSE 9020
# 启动应用
CMD ["java", "-jar", "app.jar"]
构建镜像及运行
docker build -t rednote-user-microservice:1.0.0 .
docker run -d --name rednote-user-microservice -p 9020:9020 rednote-user-microservice:1.0.0
1.7 如何实现前端项目容器化改造?
制作Docker镜像
在领域微服务根目录下创建Dockerfile文件
# 基础镜像
FROM node:22.17.0-alpine AS builder
# 工作目录
WORKDIR /app
# 复制项目依赖
COPY package*.json ./
COPY package-lock.json ./
# 安装依赖
RUN npm install
# 复制项目
COPY . .
# 构建
RUN npm run build
# 构建镜像
FROM nginx:1.29-alpine
# 复制构建文件
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.conf
# 暴露端口
EXPOSE 80
# 容器启动后默认的命令或参数
CMD ["nginx", "-g", "daemon off;"]
准备nginx.conf
在领域微服务根目录下创建nginx.conf文件
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
gzip on; # 启用压缩
gzip_types text/css application/javascript image/svg+xml; # 压缩类型
gzip_min_length 1k; # 最小压缩文件大小
gzip_comp_level 4; # 压缩级别(1-9,4为平衡点)
gzip_disable "MSIE [1-6]\."; # 禁用旧版IE压缩
server {
listen 80;
server_name 192.168.68.157;
#charset koi8-r;
#access_log logs/host.access.log main;
# 修改允许客户端最大请求体大小,这里修改成10M,也就是客户端最大能发送10M的数据给服务器了
client_max_body_size 10M;
# 前端静态资源
location / {
#root html;
root /usr/share/nginx/html; # 更新路径
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
#root html;
root /usr/share/nginx/html; # 更新路径
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
#反向代理
location /api/ {
proxy_pass http://rednote-gateway-microservice/;
}
location /file/ {
proxy_pass http://rednote-gateway-microservice/file/;
}
location /uploads/ {
proxy_pass http://rednote-gateway-microservice/uploads/;
}
}
upstream rednote-gateway-microservice {
server 192.168.68.157:8080;
}
# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;
# location / {
# root html;
# index index.html index.htm;
# }
#}
# HTTPS server
#
#server {
# listen 443 ssl;
# server_name localhost;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# location / {
# root html;
# index index.html index.htm;
# }
#}
}
构建镜像及运行
docker build -t rednote-ui:1.0.0 .
docker run -d --name rednote-ui -p 80:80 rednote-ui:1.0.0
2.1 Docker Compose编排仿“小红书”全栈项目
services:
rednote-file-microservice:
image: rednote-file-microservice:1.0.0
hostname: rednote-file-microservice
container_name: rednote-file-microservice
deploy:
resources:
limits:
memory: 1G
ports:
- "9010:9010"
rednote-user-microservice:
image: rednote-user-microservice:1.0.0
hostname: rednote-user-microservice
container_name: rednote-user-microservice
deploy:
resources:
limits:
memory: 1G
ports:
- "9020:9020"
rednote-content-microservice:
image: rednote-content-microservice:1.0.0
hostname: rednote-content-microservice
container_name: rednote-content-microservice
deploy:
resources:
limits:
memory: 1G
ports:
- "9030:9030"
rednote-admin-microservice:
image: rednote-admin-microservice:1.0.0
hostname: rednote-admin-microservice
container_name: rednote-admin-microservice
deploy:
resources:
limits:
memory: 1G
ports:
- "9040:9040"
rednote-ai-microservice:
image: rednote-ai-microservice:1.0.0
hostname: rednote-ai-microservice
container_name: rednote-ai-microservice
deploy:
resources:
limits:
memory: 1G
ports:
- "9050:9050"
rednote-gateway-microservice:
image: rednote-gateway-microservice:1.0.0
hostname: rednote-gateway-microservice
container_name: rednote-gateway-microservice
deploy:
resources:
limits:
memory: 1G
ports:
- "8080:8080"
rednote-ui:
image: rednote-ui:1.0.0
hostname: rednote-ui
container_name: rednote-ui
deploy:
resources:
limits:
memory: 1G
ports:
- "80:80"
depends_on:
- rednote-file-microservice
- rednote-user-microservice
- rednote-content-microservice
- rednote-admin-microservice
- rednote-ai-microservice
- rednote-gateway-microservice
docker-compose up -d
docker-compose down