前言

简单的学习下怎么在 Spring Boot 中使用 Docker 进行构建,发布一个镜像,现在我们通过远程的 docker api 构建镜像,运行容器,发布镜像等操作。

这里只介绍两种方式:

  1. 远程命令 api (需要知道 Docker 命令)
  2. maven 插件 (不需要了解 Docker 命令)

开启 Docker api 远程访问

开启 docker api 远程操作的功能,
例如,centos 7 中在 /usr/lib/systemd/system/docker.service,文件中,修改 ExecStart 的参数:

ExecStart=/usr/bin/dockerd  -H tcp://0.0.0.0:2375  -H unix:///var/run/docker.sock

端口自定义设置即可。

重载所有修改过的配置文件,并且重启 docker,

systemctl daemon-reload
systemctl restart docker.service

需要注意的是,由于没有密码登陆任何权限验证,外网或者生产环境需要上证书使用。

命令方式构建镜像

这种方式其实非常简单,就是需要懂得 docker 命令,才能操作。

经过上面开启 Docker Api 后,我们可以使用网络环境操作 Docker 引擎了。

  1. 新建 Dockerfile 构建镜像文件,新创建一个文件夹,专门放构建镜像需要的文件,我创建的是 /src/docker/

    FROM java:8
    EXPOSE 8080VOLUME /tmp
    ADD springboot-docker.jar app.jar
    ENTRYPOINT ["java","-jar","/app.jar"]
    
  2. 执行 maven 命令 ,将项目打包 mvn clean package --DskipTests,然后将打好的 jar 包,也放入到 Dockerfile项目目录中。

  3. 然后进入 src/docker 目录下执行 :

    docker -H tcp://xxx.xxx.xxx.xxx:2375 build -t test .
    

    开始构建镜像:

    Sending build context to Docker daemon  31.74MB
    Step 1/5 : FROM java:8---> d23bdf5b1b1b
    Step 2/5 : EXPOSE 8080---> Using cache---> 060a43a42146
    Step 3/5 : VOLUME /tmp---> Using cache---> b4f88fde6181
    Step 4/5 : ADD springboot-docker.jar app.jar---> 3a40188825b0
    Step 5/5 : ENTRYPOINT ["java","-jar","/app.jar"]---> Running in ab093916fc4c
    Removing intermediate container ab093916fc4c---> 45a3966feb60
    Successfully built 45a3966feb60
    Successfully tagged test:latest
    

    ?

使用 docker-maven-plugin构建镜像

在 maven 项目下加入 docker-maven-plugin

            <!--打包docker插件相关参数的配置--><plugin><groupId>com.spotify</groupId><artifactId>docker-maven-plugin</artifactId><version>0.4.14</version><configuration><!--打包的镜像名--><imageName>${project.groupId}/${project.artifactId}</imageName><!--Dockerfile文件位置,以项目的 root 目录为根节点,建议到单独建立一个目录--><dockerDirectory>./src/docker/</dockerDirectory><!--Docker 远程的 API 地址及端口--><dockerHost>http://xxx.xxx.xxx.199:2375</dockerHost><imageTags><imageTag>latest</imageTag></imageTags><!--执行构建docker镜像的时候需要哪些文件,springboot项目指定 打包好的jar 镜像就好--><resources><resource><!--这里指定的文件是target中的jar文件--><targetPath>/</targetPath><directory>${project.build.directory}</directory><include>${project.build.finalName}.jar</include></resource></resources></configuration></plugin>

创建 Dockerfile

需要跟pom.xml 上面配置的路径保持一致,所以我的路径是 ${baseProjectFolder}/src/docker的文件夹下新建一个文件 Dockerfile,添加构建 docker 相关命令参数:

FROM java:8
EXPOSE 8080VOLUME /tmp
ADD springboot-docker.jar app.jar # 根据打包的jar 包文件名进行修改
ENTRYPOINT ["java","-jar","/app.jar"]

打包

在应用的根目录下执行命令(打包加 dokcer build):

$ mvn clean package docker:build -DskipTests

比如使用我的工程,进行打包后完成了 docker 的构建的信息:

[INFO] Building image com.wuwii/springboot-docker
Step 1/5 : FROM java:8---> d23bdf5b1b1b
Step 2/5 : EXPOSE 8080---> Running in b7936baae57f
Removing intermediate container b7936baae57f---> 060a43a42146
Step 3/5 : VOLUME /tmp---> Running in 65e2b8ac44d3
Removing intermediate container 65e2b8ac44d3---> b4f88fde6181
Step 4/5 : ADD springboot-docker.jar app.jar---> aa3762cda143
Step 5/5 : ENTRYPOINT ["java","-jar","/app.jar"]---> Running in d9f5f63b9736
Removing intermediate container d9f5f63b9736---> 622a7d1e315c
ProgressMessage{id=null, status=null, stream=null, error=null, progress=null, progressDetail=null}
Successfully built 622a7d1e315c
Successfully tagged com.wuwii/springboot-docker:latest

使用镜像

  1. 进入安装 docker 的主机中,使用命令查看镜像(IMAGE ID 和上面是一致的):

    $ docker image ls com.wuwii/springboot-docker
    REPOSITORY                    TAG                 IMAGE ID            CREATED             SIZE
    com.wuwii/springboot-docker   latest              622a7d1e315c        22 minutes ago      659MB
    
  2. 运行容器:

    $ docker run -d -p 8080:8080 --name learn  com.wuwii/springboot-docker180fe4a7ddfc10c0cf2c37649ae1628e804564bfe1594ef05840e707801e6da3
    

    监听 8080 端口,测试是否成功。

服务编排 compose

一般的我们的 WEB 项目会使用到很多外部工具,例如 Redis ,MYSQL, ES等,如果一个一个启动搭建部署,太麻烦了,还要测试如果把这个一套环境拿到别的地方还能用吗?

使用服务编排可以避免这些坑。

加入我们的项目中增加了 Mysql 的数据库,在根目录新建一个 docker-compose.yml

version: '3'
services:web:depends_on:- dbports:- "8080:8080" # 建议加上引号,如果单独两位数的数字,可能出现解析问题restart: always# build:#  context: ./src/docker # Dockerfile 文件的目录,可以远程地址,绝对 or 相对# dockerfile: Dockerfile # 如果你的 Dockerfile 重命名了,需要指定image: test:latestenvironment:DB_HOST: db:3306DATABASE: learnDB_USERNAME: root # 测试用下 rootDB_PASSWORD: 123456 #  # 建议使用 secretdb:image: mysql:5.7volumes:- db_data:/var/lib/mysqlrestart: alwaysenvironment:MYSQL_ROOT_PASSWORD: 123456MYSQL_DATABASE: learnMYSQL_USER: kronchanMYSQL_PASSWORD: 123456volumes:db_data:  # 使用的数据卷必须声明

上面我使用的是前面已经构建好的镜像,然后执行的编排,更好的是直接使用 build 让它自己编排服务。

系统配置文件application.yml使用缺省值的方式,不影响开发的使用:

spring:datasource:url: jdbc:mysql://${DB_HOST:localhost:3306}/${DATABASE:learn}?useSSL=false&allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8username: ${DB_USERNAME:root}password: ${DB_PASSWORD:123456}driver-class-name: com.mysql.jdbc.Driverjpa:show-sql: truedatabase: mysqlhibernate:ddl-auto: updateproperties:hibernate:dialect: org.hibernate.dialect.MySQL57Dialect # 方言根据 数据库版本选择吧

也可以使用不同的 spring.profiles指定不同的环境,在 docker-compose.yml 中覆盖执行命令指定环境也是常见做法的:command: mvn clean spring-boot:run -Dspring-boot.run.profiles=xxx

最后启动,在 docker-compose.yml目录下执行 : docker-compose up

关闭服务 docker-compose down

注意

docker-compose 顺序的问题,这个是开始学习编排的时候需要注意的问题,如果上面的服务编排中 mysql 启动的慢, web 项目就会启动失败,它启动的时候不知道被依赖的服务是否启动完成,就会出现这样的问题。

解决的办法有以下几种:

  • 足够的容错和重试机制,比如连接数据库,在初次连接不上的时候,服务消费者可以不断重试,直到连接上位置
  • docker-compose拆分,分成两部分部署,将要先启动的服务放在一个docker-compose中,后启动的服务放在两一个docker-compose中,启动两次,两者使用同一个网络。
  • 同步等待,使用wait-for-it.sh或者其他shell脚本将当前服务启动阻塞,直到被依赖的服务加载完毕
    wait-for-it的github地址为:wait-for-it

总结

  1. 主要是写 Dockerfile 的时候最好单独的拿出一个文件夹来放它,我开始的时候就是直接放在项目的根路径,结果构建镜像的时候总是出现了将其他的文件也一起复制到了 Docker 目录中,WINDOW下使用 maven 插件操作这个需要注意这个上下文环境,不然很容易将一个磁盘的文件都拷贝进来了,初学者血的教训。解决办法就是单独创建一个文件夹,将需要的东西单独放置,就不用考虑这么多问题。

学习Spring Boot:(二十三)Spring Boot 中使用 Docker相关推荐

  1. 结束处理程序——Windows核心编程学习手札之二十三

    结束处理程序 --Windows核心编程学习手札之二十三 使用SEH可以只关注程序要完成任务,而运行中发生的错误,系统将会发现并通知.Windows引入SHE是为了便于操作系统的开发,使用SHE所造成 ...

  2. OpenCV学习笔记(二十一)——绘图函数core OpenCV学习笔记(二十二)——粒子滤波跟踪方法 OpenCV学习笔记(二十三)——OpenCV的GUI之凤凰涅槃Qt OpenCV学习笔记(二十

    OpenCV学习笔记(二十一)--绘图函数core 在图像中,我们经常想要在图像中做一些标识记号,这就需要绘图函数.OpenCV虽然没有太优秀的GUI,但在绘图方面还是做得很完整的.这里就介绍一下相关 ...

  3. Spring(二)--------Spring配置、DI依赖注入、Bean自动装配

    Spring(二)--------Spring配置.DI依赖注入.Bean自动装配 5.Spring配置 5.1 别名 设置别名:第一种方式alias <!--其中name为ID的对应值--&g ...

  4. 强化学习系列文章(二十三):AirSim Python API图像与图像处理

    强化学习系列文章(二十三):AirSim Python API图像与图像处理 参考网址:https://microsoft.github.io/AirSim/image_apis/#segmentat ...

  5. C语言学习(十二)C语言中的字符(宽字符与窄字符)、从字符谈谈C语言的编码、转义字符

    C语言学习(十二)C语言中的字符(宽字符与窄字符).从字符谈谈C语言的编码.转义字符 目录 C语言学习(十二)C语言中的字符(宽字符与窄字符).从字符谈谈C语言的编码.转义字符 英文字符 字符的表示 ...

  6. Slicer学习笔记(二十三)slicer调试自带模块

    Slicer学习笔记(二十三)slicer调试自带模块 1.调试Segment Editor模块下的Grow from seeds 2.调试文件与细节 2.1.masterImageData的调试信息 ...

  7. Spring 学习笔记(二)Spring AOP

    前言 容器和AOP是Spring的两大核心.本文将来学习Spring AOP. AOP是什么? AOP在计算机科学领域还是相对年轻的概念,由Xerox PARC公司发明.Gregor Kiczales ...

  8. 和php交互的过程_JavaScript学习笔记(二十三) 服务器PHP

    PHP PHP 一门后端语言 为什么要学习一个后端语言呢? 目前市场上的需求,要求前端人员掌握一个后端语言 方便和后端开发人员进行交互 基本组织架构 在讲后端语言之前,我们简单的了解一下我们基本的组织 ...

  9. Linux学习笔记(二十三) -- QT的安装和卸载

    1.QT简介 Qt 是一个跨平台C++图形用户界面应用程序开发框架.它可以用来开发GUI程序和非GUI程序(比如控制台工具和服务器). 2.QT安装 使用如下命令: sudo apt-get inst ...

  10. Spring学习笔记(二十三)——实现网站微信扫码登录获取微信用户信息Demo

    目录 微信扫码登录介绍 开发步骤 微信扫码登录示例 微信开放文档 遇到的问题 使用第三方工具实现网站微信扫码登录 开发前介绍 开发步骤 微信扫码登录获取微信用户信息Demo实现流程 实现效果 实现过程 ...

最新文章

  1. Serverless 解惑——函数计算如何安装字体
  2. nyoj-999 师傅又被妖怪抓走了
  3. 几个方便编程的C++特性
  4. 回归分析中的正则化问题
  5. 汇编软件的安装与实验一
  6. 二叉树祖先节点_二叉树的祖先
  7. NodeJS使用淘宝 NPM 镜像/NPM使用国内源
  8. python数据结构与算法第10讲_Python数据结构与算法10:基本结构:练习题1
  9. 掌握这些的Linux命令,你基本稳了
  10. 博弈论:寻找先手必胜策略——Grundy值
  11. jQuery增加删除修改tab导航特效
  12. 关于echarts中饼图设置颜色的方法
  13. 推荐广告相关名词ctr,cvr等
  14. 关于Qt中QMAKESPEC环境变量
  15. QT中事件及事件处理
  16. “禁止燃放烟花爆竹”社会治理创新活动
  17. 卸载完mathtype后,word加载项中还是有mathtype的解决方法
  18. ARM程序的镜像文件以及在内存中的分区
  19. 多商户商城系统功能拆解24讲-平台端分销会员
  20. 【Java基础】· IO流习题详解

热门文章

  1. [转载] Java中Scanner用法总结
  2. stl中map函数_map :: max_size()函数,以及C ++ STL中的Example
  3. scala 转换为字符串_如何在Scala中将字符串转换为布尔值?
  4. uselocale_Java扫描仪useLocale()方法与示例
  5. ruby 将字符串转为数组_Ruby程序将数组打印为字符串
  6. 块元素、行内块和内联元素_如何删除内联块元素之间的空间?
  7. python函数示例_带Python示例的float()函数
  8. C# WinForm窗体四周阴影效果
  9. Js实现动态插入删除文本框
  10. 第一次创建springboot框架项目