当前位置: 首页 > news >正文

一文搞懂:Dockerfile与docker-compose实战——从编写Dockerfile到多容器编排,Spring Boot项目镜像打包全攻略

写在前面你是否经历过这样的场景本地开发调试得好好的一部署到测试服务器就各种报错——“JDK版本不对”、“依赖库缺失”、“配置文件路径找不到”……每次都得重复安装环境、调试配置浪费大量时间。Docker的出现彻底改变了这个局面。它让开发者可以将应用与其运行环境一起打包成一个轻量级的镜像无论在哪个平台上只要安装了Docker就能以完全一致的方式运行。在Java开发中最常见的需求就是把我的Spring Boot项目打包成一个镜像然后用docker-compose把应用、MySQL、Redis等依赖服务一起启动。这篇笔记我们从最基础的Dockerfile编写开始一步步掌握镜像构建、多阶段构建优化再到使用docker-compose编排多个容器最终实现一套完整的本地开发/测试环境。不管你是刚接触Docker的初学者还是希望规范化项目交付的开发者这篇文章都能帮你快速上手。1️⃣ Docker核心概念回顾在开始编写Dockerfile之前先理清三个核心概念镜像Image一个只读的模板包含应用及其运行所需的环境操作系统、依赖库、代码等。类似于面向对象中的“类”。容器Container镜像的运行实例是真正运行应用的地方。可以创建、启动、停止、删除。类似于“对象”。仓库Repository存放镜像的地方如Docker Hub、私有Harbor等。关系图2️⃣ Dockerfile基础指令详解与最佳实践Dockerfile是一个文本文件包含一系列指令告诉Docker如何构建镜像。下面是常用的指令及其作用最佳实践原则选择合适的基础镜像生产环境尽量用slim或alpine变体如openjdk:17-jdk-slim体积小漏洞少。减少层数将多条RUN命令合并成一条用连接避免产生太多中间层。利用构建缓存把不容易变化的指令放在前面如COPY pom.xml先于COPY src这样修改代码后不必重装依赖。使用.dockerignore排除不需要的文件如.git、target/、*.log加速构建。指定非root用户创建应用用户运行容器提高安全性。3️⃣ Spring Boot项目打包镜像从jar到镜像假设你有一个Spring Boot项目用Maven构建后生成target/myapp.jar。下面是一个基本的Dockerfile# 第一阶段基础环境 FROM openjdk:17-jdk-slim WORKDIR /app # 复制jar包 COPY target/myapp.jar app.jar # 暴露端口 EXPOSE 8080 # 启动命令 ENTRYPOINT [java, -jar, app.jar]构建镜像# 在项目根目录执行Dockerfile所在位置 docker build -t myapp:1.0 .运行容器docker run -d -p 8080:8080 --name myapp myapp:1.0此时访问http://localhost:8080即可看到应用。问题这个镜像包含了完整的JDK和jar包体积通常在300MB以上。我们可以通过多阶段构建大幅减小体积。4️⃣ 多阶段构建大幅减小镜像体积多阶段构建允许在一个Dockerfile中使用多个FROM指令最终只保留最后一个阶段的产物。对于Spring Boot应用可以在第一阶段用Maven构建可选第二阶段用JRE运行。# 第一阶段构建使用Maven镜像 FROM maven:3.8.6-openjdk-17-slim AS builder WORKDIR /build COPY pom.xml . RUN mvn dependency:go-offline # 下载依赖利用缓存 COPY src ./src RUN mvn package -DskipTests # 第二阶段运行使用精简JRE FROM openjdk:17-jdk-slim WORKDIR /app COPY --frombuilder /build/target/*.jar app.jar EXPOSE 8080 ENTRYPOINT [java, -jar, app.jar]优势最终镜像中只包含JRE和jar包没有Maven和源代码体积可缩小到100MB左右。还可以使用更极致的eclipse-temurin:17-jre-alpine体积低于80MB。构建命令不变Docker会自动执行多阶段。5️⃣ docker-compose入门定义和运行多容器应用对于一个完整的后端服务通常需要依赖数据库如MySQL、缓存如Redis等。使用docker-compose可以通过一个YAML文件定义多个容器的配置、网络和依赖关系实现一键启动。安装docker-composeDocker Desktop已内置Linux需单独安装sudo apt install docker-compose-plugin。docker-compose.yml基础结构version: 3.8 services: app: build: . # 使用当前目录的Dockerfile构建 ports: - 8080:8080 depends_on: - mysql - redis environment: - SPRING_DATASOURCE_URLjdbc:mysql://mysql:3306/mydb - SPRING_REDIS_HOSTredis mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: root123 MYSQL_DATABASE: mydb ports: - 3306:3306 volumes: - mysql_data:/var/lib/mysql # 持久化数据 redis: image: redis:7-alpine ports: - 6379:6379 volumes: mysql_data:启动docker-compose up -d停止docker-compose down加-v会删除数据卷注意服务之间通过服务名互相访问如mysql因为compose会自动创建一个网络并解析服务名。6️⃣ 实战Spring Boot MySQL Redis 完整编排下面我们以一个完整的Spring Boot项目为例演示如何配置环境变量、依赖服务并实现一键启动。步骤1准备Spring Boot应用在application.properties或application.yml中使用环境变量占位符spring: datasource: url: ${SPRING_DATASOURCE_URL:jdbc:mysql://localhost:3306/mydb} username: ${SPRING_DATASOURCE_USERNAME:root} password: ${SPRING_DATASOURCE_PASSWORD:root123} redis: host: ${SPRING_REDIS_HOST:localhost} port: ${SPRING_REDIS_PORT:6379}这样在compose中通过environment覆盖即可。步骤2编写Dockerfile多阶段如上所示放到项目根目录。步骤3编写docker-compose.ymlversion: 3.8 services: app: build: . ports: - 8080:8080 depends_on: mysql: condition: service_healthy # 等待MySQL健康后再启动 redis: condition: service_started environment: - SPRING_DATASOURCE_URLjdbc:mysql://mysql:3306/mydb?useSSLfalseallowPublicKeyRetrievaltrue - SPRING_DATASOURCE_USERNAMEroot - SPRING_DATASOURCE_PASSWORDroot123 - SPRING_REDIS_HOSTredis restart: on-failure mysql: image: mysql:8.0 ports: - 3306:3306 environment: MYSQL_ROOT_PASSWORD: root123 MYSQL_DATABASE: mydb volumes: - mysql_data:/var/lib/mysql healthcheck: test: [CMD, mysqladmin, ping, -h, localhost] interval: 10s timeout: 5s retries: 5 redis: image: redis:7-alpine ports: - 6379:6379 restart: always volumes: mysql_data:步骤4构建并启动docker-compose up -d --build # --build强制重新构建镜像查看日志docker-compose logs -f app步骤5清理docker-compose down -v # 删除容器和数据卷谨慎7️⃣ 常用docker-compose命令与调试技巧调试技巧单独启动某个服务docker-compose up -d mysql避免一次性启动全部。查看容器内部文件docker-compose exec app ls -la /app复制文件到容器docker cp 本地文件 容器名:目标路径也可以反过来。检查网络连通性docker-compose exec app ping mysql需镜像装有ping。8️⃣ 总结与最佳实践一个更完善的Dockerfile示例FROM eclipse-temurin:17-jre-alpine AS runner WORKDIR /app RUN addgroup -g 1000 app adduser -u 1000 -G app -D app COPY --chownapp:app target/*.jar app.jar USER app EXPOSE 8080 ENTRYPOINT [java, -jar, app.jar]在实际项目中你可能会遇到Spring Boot应用连接MySQL时出现“Communications link failure”即使compose中已经定义了depends_on。这是因为MySQL启动完成进程存在并不代表它能接受连接。你是如何解决这个问题的除了使用healthcheck等待你用过哪些更可靠的方案如使用wait-for-it.sh脚本欢迎分享你的经验。
http://www.rkmt.cn/news/1372420.html

相关文章:

  • Django 从 0 到 1 打造完整电商平台:商品排序与浏览量统计
  • 【无人机三维路径规划】基于circle序列和正余弦策略的APO和CO算法无人机集群路径规划附Matlab代码
  • DeepSeek配额策略失效的7个静默信号(第5个90%工程师都忽略),立即执行这1次curl诊断脚本保生产稳定
  • ChatGPT路演PPT背后的资本语言学:用BERT模型分析217份AI融资材料,发现高过会率PPT共有的8个动词密度阈值
  • 2026GEO公司哪家好:全球AI搜索流量迁移与大模型认知主权争夺战 - GEO优化
  • Solid.js信号驱动架构深度解析:告别虚拟DOM的真正实践
  • 如何用GHelper实现华硕笔记本性能与静音的完美平衡
  • 后端架构技术01-「10万并发压垮线程池?Project Loom虚拟线程:一个线程几KB,轻松扛住流量洪峰」
  • Taotoken的API Key管理与审计日志功能实践体验
  • 昇腾NPU的算子公共平台,实现M×N算子复用
  • 火盾声学材料:安庆地区防火吸音板综合解决方案,玻纤吸音板/演播厅空间吸声体/布艺软包吸音板,防火吸音板源头厂家有哪些 - 品牌推荐师
  • 论文初稿被批太水?青年教师力荐这几个AI论文写作软件
  • JavaScript 比较
  • 今天不用就过期:Gemini深度研究模式2024Q3权限变更预警——3类高价值功能即将对免费用户关闭
  • 洛谷 P11398
  • 5月20号
  • 如何解锁索尼相机的隐藏功能:OpenMemories-Tweak完整指南
  • 日志爆炸时代如何不被淹没?DeepSeek智能分析方案全链路实操,含Prometheus+Loki+DeepSeek三端联调手册
  • Java学习笔记:多态
  • ChatGPT记忆功能安全风险预警,3大数据泄露漏洞已验证(附GDPR/等保2.0合规配置清单)
  • C++的STL
  • DLSS Swapper深度解析:如何实现跨平台游戏DLSS版本智能管理
  • 【优化调度】基于改进遗传算法求解带时间窗约束多卫星任务规划附Matlab代码
  • 2026年5月有实力的一体化污水提升泵站/一体化泵站厂家推荐河北铄康环保设备有限公司,水质适应性广各类浑浊污水均可稳定输送处理 - 品牌鉴赏师
  • 溧阳沙发翻新换皮换布面靠谱商家优选推荐|匠阁沙发翻新、御匠沙发翻新、锦修沙发翻新三大品牌、全品类沙发翻新换皮换布一站式服务 - 卓信营销
  • 建立在不同的基线模型上,GAT,GCN,和GIN
  • 2026年5月优秀的EPS外墙装饰/EPS装饰线条厂家推荐丰县建鑫泡沫制品有限公司,雕花构件定制打造建筑独特标识 - 品牌鉴赏师
  • 2026长岛民宿排名指南,长岛海东渔家民宿没白来! - 资讯纵览
  • 英语 听力 重读软件app
  • AI写作辅助平台8款AI写作辅助软件梯队榜,毕业护航!