Docker和Docker-Compose在Windows上的实际应用
Docker 和 Docker Compose 在 Windows 上的实际应用
项目案例:virtual-chat(Spring Boot 虚拟聊天应用)
环境:Windows 10/11 + Docker Desktop
技术栈:Java 17、Spring Boot、Maven、Docker、Docker Compose
目录
- 一、前言
- 二、Docker Desktop for Windows 安装与配置
- 三、配置国内镜像源加速构建
- 四、方式一:使用 Dockerfile 直接构建部署
- 五、方式二:使用 Docker Compose 编排部署
- 六、常见问题与解决方案
- 七、核心配置文件详解
- 八、Docker 与 Docker Compose 的区别与优势
- 九、总结
一、前言
在现代软件开发中,容器化技术已经成为标准化部署的重要手段。Docker 作为最流行的容器化平台,能够帮助开发者实现"一次构建,到处运行"的目标。而 Docker Compose 则进一步简化了多容器应用的编排和管理。
本文将以 virtual-chat 项目为例,详细介绍在 Windows 环境下如何使用 Docker 和 Docker Compose 进行项目的构建、打包和部署,并分享实际开发中遇到的问题和解决方案。
二、Docker Desktop for Windows 安装与配置
2.1 系统要求
- Windows 10 64位:专业版、企业版或教育版(Build 19041 或更高版本)
- Windows 11:所有版本
- 启用 WSL 2(Windows Subsystem for Linux)
- BIOS 中启用虚拟化技术
2.2 安装步骤
-
下载 Docker Desktop
- 访问官网:https://www.docker.com/products/docker-desktop
- 下载 Windows 版本安装包
-
安装过程
# 双击下载的 Docker Desktop Installer.exe # 按照向导完成安装 # 安装完成后重启计算机 -
验证安装
# 检查 Docker 版本 docker --version # 检查 Docker Compose 版本 docker-compose --version # 运行测试容器 docker run hello-world -
启动 Docker Desktop
- 从开始菜单启动 Docker Desktop
- 等待右下角托盘图标显示"Docker Desktop is running"
- 确保 WSL 2 后端正常运行
三、配置国内镜像源加速构建
由于 Docker Hub 在国内访问速度较慢,配置国内镜像源可以显著提升镜像拉取和构建速度。
3.1 配置方法
-
打开 Docker Desktop 设置
- 右键点击任务栏 Docker 图标
- 选择 “Settings” → “Docker Engine”
-
添加国内镜像源
在
registry-mirrors数组中添加以下镜像源:{ "builder": { "gc": { "defaultKeepStorage": "20GB", "enabled": true } }, "experimental": false, "registry-mirrors": [ "https://docker.m.daocloud.io", "https://huecker.io", "https://dockerhub.timeweb.cloud", "https://noohub.ru" ] } -
应用并重启
- 点击 “Apply & restart”
- 等待 Docker Desktop 重启完成
3.2 验证配置
# 查看 Docker 信息,确认镜像源已生效
docker info | Select-String "Registry Mirrors"
# 测试拉取镜像速度
docker pull eclipse-temurin:17-jre-alpine
提示:如果某个镜像源失效,可以尝试更换其他源。常用的国内镜像源包括阿里云、DaoCloud、腾讯云等。
四、方式一:使用 Dockerfile 直接构建部署
4.1 项目准备
以 virtual-chat 项目为例,首先确保项目能够正常构建:
# 进入项目目录
cd d:\aiwork\virtual-chat
# 本地 Maven 构建(推荐先本地构建,避免 Docker 内下载依赖超时)
mvn clean package -DskipTests
4.2 创建 Dockerfile
我们使用简化版的 Dockerfile.simple,采用两阶段构建思路(本地构建 + Docker 打包):
# 使用官方的 OpenJDK 17 JRE 镜像作为基础镜像
FROM eclipse-temurin:17-jre-alpine
# 安装 curl 用于健康检查
RUN apk add --no-cache curl
# 设置工作目录
WORKDIR /app
# 复制已构建的 JAR 文件
COPY target/virtual-chat-0.0.1-SNAPSHOT.jar app.jar
# 暴露端口
EXPOSE 8080
# 启动应用
ENTRYPOINT ["java", "-jar", "app.jar"]
4.3 创建 .dockerignore
为了避免将不必要的文件复制到镜像中,创建 .dockerignore 文件:
# Git
.git
.gitignore
# IDE
.vscode
.idea
*.iml
# Maven
target/
!.mvn/wrapper/maven-wrapper.jar
!target/virtual-chat-0.0.1-SNAPSHOT.jar
# Data
data/
*.db
# Logs
*.log
# OS
.DS_Store
Thumbs.db
# Documentation
*.md
*.docx
*.txt
# Scripts
*.bat
*.ps1
# Python
__pycache__/
*.pyc
*.pyo
# Generated files
generated-images/
关键点:注意第 11-13 行,我们排除了整个
target/目录,但显式允许了最终的 JAR 文件。这样既减少了镜像体积,又保留了必要的构建产物。
4.4 构建 Docker 镜像
# 构建镜像(指定标签)
docker build -f Dockerfile.simple -t virtual-chat:latest .
# 查看构建的镜像
docker images | Select-String "virtual-chat"
4.5 运行容器
# 启动容器
docker run -d `
--name virtual-chat-app `
-p 8080:8080 `
-v ${PWD}/data:/app/data `
-e SPRING_PROFILES_ACTIVE=prod `
virtual-chat:latest
# 查看运行状态
docker ps | Select-String "virtual-chat"
# 查看日志
docker logs -f virtual-chat-app
# 访问应用
curl http://localhost:8080
4.6 停止和清理
# 停止容器
docker stop virtual-chat-app
# 删除容器
docker rm virtual-chat-app
# 删除镜像(可选)
docker rmi virtual-chat:latest
五、方式二:使用 Docker Compose 编排部署
对于包含多个服务的应用(如数据库 + 应用服务器),Docker Compose 提供了更便捷的编排方式。
5.1 创建 docker-compose.yml
version: '3.8'
services:
virtual-chat:
build:
context: .
dockerfile: Dockerfile.simple
container_name: virtual-chat-app
ports:
- "8080:8080"
volumes:
# 挂载数据目录以保持H2数据库持久化
- ./data:/app/data
environment:
- SPRING_PROFILES_ACTIVE=prod
- SERVER_PORT=8080
restart: unless-stopped
5.2 使用 Docker Compose 部署
# 构建并启动服务(后台运行)
docker-compose up -d --build
# 查看服务状态
docker-compose ps
# 查看日志
docker-compose logs -f virtual-chat
# 停止服务
docker-compose down
# 停止并删除卷(会清除数据)
docker-compose down -v
5.3 多服务编排示例
如果项目需要连接数据库,可以扩展 docker-compose.yml:
version: '3.8'
services:
# 应用服务
virtual-chat:
build:
context: .
dockerfile: Dockerfile.simple
container_name: virtual-chat-app
ports:
- "8080:8080"
depends_on:
- postgres
environment:
- SPRING_PROFILES_ACTIVE=prod
- SPRING_DATASOURCE_URL=jdbc:postgresql://postgres:5432/virtualchat
- SPRING_DATASOURCE_USERNAME=postgres
- SPRING_DATASOURCE_PASSWORD=secret
restart: unless-stopped
# PostgreSQL 数据库
postgres:
image: postgres:15-alpine
container_name: virtual-chat-db
environment:
POSTGRES_DB: virtualchat
POSTGRES_USER: postgres
POSTGRES_PASSWORD: secret
volumes:
- postgres-data:/var/lib/postgresql/data
ports:
- "5432:5432"
restart: unless-stopped
volumes:
postgres-data:
六、常见问题与解决方案
6.1 问题一:构建进程卡死
现象:
[+] Building 0.0s (0/0)
# 长时间卡在 0/0 进度
原因:
- Docker Buildx 构建进程异常
- 网络问题导致镜像拉取超时
- 资源不足
解决方案:
-
查找并终止构建进程
# 查找 Docker 构建进程 Get-Process | Where-Object {$_.ProcessName -like "*docker*build*"} # 强制终止进程(谨慎使用) Stop-Process -Name "com.docker.build" -Force -
清理构建缓存
# 清理未使用的构建缓存 docker builder prune -a -f # 清理所有未使用的资源 docker system prune -a -f -
重启 Docker Desktop
- 通过 Docker Desktop UI 完全退出
- 重新启动 Docker Desktop
- 等待服务完全恢复后再继续操作
重要提示:强制终止
com.docker.build进程可能导致 Docker Desktop 后端连接中断,建议优先通过 UI 重启。
6.2 问题二:镜像拉取超时
现象:
Error response from daemon: Get "https://registry-1.docker.io/v2/":
context deadline exceeded
解决方案:
-
检查镜像源配置
docker info | Select-String "Registry Mirrors" -
更换可用的镜像源
- 参考第三章重新配置镜像源
- 尝试不同的镜像源组合
-
手动拉取基础镜像
# 先单独拉取基础镜像 docker pull eclipse-temurin:17-jre-alpine # 再执行构建 docker build -f Dockerfile.simple -t virtual-chat:latest .
6.3 问题三:Maven 依赖下载失败
现象:
[ERROR] Failed to execute goal on project virtual-chat:
Could not resolve dependencies
解决方案:
-
优先本地构建
# 在宿主机上先完成 Maven 构建 mvn clean package -DskipTests # 再使用 Dockerfile.simple 打包 docker build -f Dockerfile.simple -t virtual-chat:latest . -
配置 Maven 镜像源
在项目根目录创建settings.xml:<settings> <mirrors> <mirror> <id>aliyun</id> <mirrorOf>central</mirrorOf> <name>Aliyun Maven</name> <url>https://maven.aliyun.com/repository/public</url> </mirror> </mirrors> </settings> -
在 Dockerfile 中挂载 settings.xml
COPY settings.xml /root/.m2/settings.xml
6.4 问题四:端口冲突
现象:
Error starting userland proxy: Bind for 0.0.0.0:8080 failed:
port is already allocated
解决方案:
-
查找占用端口的进程
netstat -ano | findstr :8080 tasklist | findstr <PID> -
修改映射端口
# docker-compose.yml ports: - "8081:8080" # 将宿主机的 8081 映射到容器的 8080 -
停止占用端口的服务
taskkill /F /PID <PID>
6.5 问题五:数据持久化丢失
现象:
容器重启后,H2 数据库或其他数据丢失。
解决方案:
使用 Volume 挂载数据目录:
volumes:
- ./data:/app/data
确保 .dockerignore 中排除了 data/ 目录,避免数据被覆盖。
七、核心配置文件详解
7.1 Dockerfile.simple 解析
# 第1行:指定基础镜像
# eclipse-temurin:17-jre-alpine 是轻量级的 Java 17 JRE 镜像
# Alpine Linux 基础使得镜像体积更小(约 200MB vs 标准版的 600MB+)
FROM eclipse-temurin:17-jre-alpine
# 第5行:安装必要工具
# curl 用于健康检查和调试
# --no-cache 避免缓存包,减小镜像体积
RUN apk add --no-cache curl
# 第8行:设置工作目录
# 后续的所有相对路径都基于此目录
WORKDIR /app
# 第11行:复制 JAR 文件
# 从宿主机的 target 目录复制已构建的 JAR 到容器的 /app 目录
# 重命名为 app.jar 便于统一管理
COPY target/virtual-chat-0.0.1-SNAPSHOT.jar app.jar
# 第14行:声明暴露的端口
# 这只是文档说明,实际端口映射在 docker run 或 docker-compose 中指定
EXPOSE 8080
# 第17行:定义容器启动时执行的命令
# ENTRYPOINT 使得容器像一个可执行程序一样运行
# java -jar 启动 Spring Boot 应用
ENTRYPOINT ["java", "-jar", "app.jar"]
关键设计点:
- 使用 JRE 而非 JDK,减小镜像体积
- Alpine Linux 基础镜像,进一步压缩体积
- 本地构建 + Docker 打包,避免在容器内下载依赖
- 固定 ENTRYPOINT,支持通过
docker run传递 JVM 参数
7.2 docker-compose.yml 解析
# 指定 Compose 文件格式版本
version: '3.8'
# 定义服务列表
services:
# 服务名称(可自定义)
virtual-chat:
# 构建配置
build:
# 构建上下文:当前目录
context: .
# 指定使用的 Dockerfile
dockerfile: Dockerfile.simple
# 容器名称(固定名称便于管理)
container_name: virtual-chat-app
# 端口映射:宿主机端口:容器端口
ports:
- "8080:8080"
# 数据卷挂载:宿主机路径:容器路径
volumes:
# 挂载数据目录以实现持久化
- ./data:/app/data
# 环境变量
environment:
# 激活 Spring Boot 的生产环境配置
- SPRING_PROFILES_ACTIVE=prod
# 设置服务器端口
- SERVER_PORT=8080
# 重启策略:除非手动停止,否则自动重启
restart: unless-stopped
关键字段说明:
| 字段 | 作用 | 示例值 |
|---|---|---|
build.context | 构建上下文目录 | . 表示当前目录 |
build.dockerfile | 指定 Dockerfile 路径 | Dockerfile.simple |
container_name | 容器名称 | 固定名称便于管理 |
ports | 端口映射 | "宿主机端口:容器端口" |
volumes | 数据卷挂载 | "宿主机路径:容器路径" |
environment | 环境变量 | 传递给容器的配置 |
restart | 重启策略 | unless-stopped / always / no |
7.3 .dockerignore 解析
# 排除 Git 相关文件
.git
.gitignore
# 排除 IDE 配置文件
.vscode
.idea
*.iml
# Maven 构建目录(但保留最终 JAR)
target/
!.mvn/wrapper/maven-wrapper.jar
!target/virtual-chat-0.0.1-SNAPSHOT.jar
# 排除数据文件(避免覆盖持久化数据)
data/
*.db
# 排除日志文件
*.log
# 排除操作系统文件
.DS_Store
Thumbs.db
# 排除文档文件
*.md
*.docx
*.txt
# 排除脚本文件
*.bat
*.ps1
# 排除 Python 缓存
__pycache__/
*.pyc
*.pyo
# 排除生成的图片文件
generated-images/
设计原则:
- 减少镜像体积:排除不必要的文件,显著减小镜像大小
- 提高构建速度:减少需要传输到 Docker daemon 的文件数量
- 保护敏感数据:避免将
.env、密钥文件等复制到镜像中 - 保持数据独立:排除
data/目录,确保容器内外数据隔离
八、Docker 与 Docker Compose 的区别与优势
8.1 核心区别
| 特性 | Docker | Docker Compose |
|---|---|---|
| 定位 | 单容器管理工具 | 多容器编排工具 |
| 配置文件 | Dockerfile | docker-compose.yml |
| 适用场景 | 单个应用容器化 | 多服务应用编排 |
| 命令复杂度 | 需要手动管理多个容器 | 一条命令管理所有服务 |
| 网络管理 | 需手动创建和管理网络 | 自动创建内部网络 |
| 依赖管理 | 需手动控制启动顺序 | 通过 depends_on 自动管理 |
8.2 Docker 的优势
-
环境一致性
- "在我的机器上能运行"不再是问题
- 开发、测试、生产环境完全一致
-
资源隔离
- 每个容器拥有独立的文件系统、网络、进程空间
- 避免应用之间的依赖冲突
-
快速部署
- 秒级启动容器
- 支持快速扩缩容
-
轻量级
- 相比虚拟机,容器共享宿主机内核
- 资源开销小,启动速度快
-
版本控制
- 镜像可以打标签、版本化管理
- 支持快速回滚
8.3 Docker Compose 的优势
-
简化多容器管理
# 传统方式:需要分别启动多个容器 docker run -d --name db postgres:15 docker run -d --name app --link db myapp # Compose 方式:一条命令启动所有服务 docker-compose up -d -
声明式配置
- 所有服务配置集中在一个 YAML 文件中
- 易于版本控制和团队协作
-
自动网络管理
- 自动创建内部网络
- 服务之间可以通过服务名互相访问
# 应用可以直接使用服务名 "postgres" 访问数据库 SPRING_DATASOURCE_URL=jdbc:postgresql://postgres:5432/virtualchat -
依赖管理
depends_on: - postgres - redis确保服务按正确顺序启动
-
一键启停
# 启动所有服务 docker-compose up -d # 停止所有服务 docker-compose down # 查看日志 docker-compose logs -f -
环境隔离
# 可以为不同环境使用不同的 compose 文件 docker-compose -f docker-compose.dev.yml up docker-compose -f docker-compose.prod.yml up
8.4 选择建议
使用 Docker 的场景:
- 单个应用的容器化
- 简单的微服务部署
- 学习和实验
使用 Docker Compose 的场景:
- 多服务应用(如 Web + Database + Cache)
- 本地开发环境搭建
- 微服务架构的原型开发
- 需要频繁启停的开发测试环境
生产环境建议:
- 小规模:Docker Compose + 监控
- 中大规模:Kubernetes / Docker Swarm
九、总结
9.1 最佳实践总结
-
镜像源配置
- 始终配置国内镜像源以提升构建速度
- 准备多个备用镜像源
-
构建优化
- 优先本地构建,避免在 Docker 内下载依赖
- 使用多阶段构建或简化版 Dockerfile
- 合理配置
.dockerignore减小镜像体积
-
数据持久化
- 使用 Volume 挂载重要数据目录
- 定期备份持久化数据
-
错误处理
- 遇到构建卡顿时,优先重启 Docker Desktop
- 定期清理未使用的镜像和缓存
- 查看详细日志定位问题
-
安全考虑
- 不要在镜像中硬编码敏感信息
- 使用环境变量或 secrets 管理配置
- 定期更新基础镜像修复安全漏洞
9.2 工作流程回顾
9.3 后续学习方向
-
Docker 高级特性
- 多阶段构建优化镜像体积
- Docker BuildKit 高级功能
- 自定义网络和存储驱动
-
容器编排
- Kubernetes 入门与实践
- Docker Swarm 集群管理
- Helm Chart 包管理
-
CI/CD 集成
- GitHub Actions + Docker
- Jenkins 自动化构建
- 私有镜像仓库搭建
-
监控与日志
- Prometheus + Grafana 监控
- ELK 日志收集
- 容器健康检查
附录:常用命令速查
Docker 基础命令
# 镜像管理
docker images # 列出镜像
docker pull <image> # 拉取镜像
docker rmi <image> # 删除镜像
docker build -t <tag> . # 构建镜像
# 容器管理
docker ps # 查看运行中的容器
docker ps -a # 查看所有容器
docker run -d <image> # 运行容器
docker stop <container> # 停止容器
docker rm <container> # 删除容器
docker logs -f <container> # 查看日志
docker exec -it <container> sh # 进入容器
# 系统清理
docker system prune -a -f # 清理所有未使用资源
docker builder prune -a -f # 清理构建缓存
Docker Compose 命令
# 服务管理
docker-compose up -d # 后台启动服务
docker-compose down # 停止并删除服务
docker-compose ps # 查看服务状态
docker-compose logs -f # 查看日志
docker-compose restart # 重启服务
docker-compose build # 重新构建镜像
# 高级用法
docker-compose up -d --build # 重新构建并启动
docker-compose down -v # 停止并删除卷
docker-compose exec <service> sh # 进入服务容器
更多推荐


所有评论(0)