三十、Docker及容器化部署

3 阅读20分钟

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 --versiondocker 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 ComposeKubernetes适用场景
部署规模单机集群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),避免兼容问题;
  • 结构分层:按versionservicesvolumesnetworks编写,逻辑清晰;
  • 服务命名标准化:服务名-环境(如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全栈工程师突破部署运维瓶颈的核心技能,其核心价值在于环境标准化、部署高效化、运维规模化。掌握本文的核心内容:

  1. 从认知层理解Docker解决的全栈项目部署痛点;
  2. 从实战层掌握镜像构建、容器操作的标准化流程;
  3. 从规模化层掌握Docker Compose编排技巧,实现多服务一键部署;
  4. 结合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

2.2 Harbor从安装到生产配置:快速搭建企业级镜像中心

2.3 Harbor用户与角色配置,建立精细化权限管理体系

2.4 Harbor项目创建,高效实现业务隔离与资源优化的双重保障

2.5 镜像仓库存实战,掌握标准化镜像协作流程

3.1 如何实现企业级容器化部署仿“小红书”项目?