前言
简单的学习下怎么在 Spring Boot 中使用 Docker 进行构建,发布一个镜像,现在我们通过远程的 docker api 构建镜像,运行容器,发布镜像等操作。
这里只介绍两种方式:
- 远程命令 api (需要知道 Docker 命令)
- maven 插件 (不需要了解 Docker 命令)
开启 Docker api 远程访问
开启 docker api 远程操作的功能,
例如,centos 7 中在 /usr/lib/systemd/system/docker.service
,文件中,修改 ExecStart
的参数:
1 | ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock |
端口自定义设置即可。
重载所有修改过的配置文件,并且重启 docker,
1 | systemctl daemon-reload |
需要注意的是,由于没有密码登陆任何权限验证,外网或者生产环境需要上证书使用。
命令方式构建镜像
这种方式其实非常简单,就是需要懂得 docker 命令,才能操作。
经过上面开启 Docker Api 后,我们可以使用网络环境操作 Docker 引擎了。
新建
Dockerfile
构建镜像文件,新创建一个文件夹,专门放构建镜像需要的文件,我创建的是/src/docker/
1
2
3
4
5
6FROM java:8
EXPOSE 8080
VOLUME /tmp
ADD springboot-docker.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar"]执行 maven 命令 ,将项目打包
mvn clean package --DskipTests
,然后将打好的 jar 包,也放入到Dockerfile
项目目录中。然后进入
src/docker
目录下执行 :1
docker -H tcp://xxx.xxx.xxx.xxx:2375 build -t test .
开始构建镜像:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17Sending 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
1 | <!--打包docker插件相关参数的配置--> |
创建 Dockerfile
需要跟pom.xml
上面配置的路径保持一致,所以我的路径是 ${baseProjectFolder}/src/docker
的文件夹下新建一个文件 Dockerfile
,添加构建 docker 相关命令参数:
1 | FROM java:8 |
打包
在应用的根目录下执行命令(打包加 dokcer build):
1 | $ mvn clean package docker:build -DskipTests |
比如使用我的工程,进行打包后完成了 docker 的构建的信息:
1 | [INFO] Building image com.wuwii/springboot-docker |
使用镜像
进入安装 docker 的主机中,使用命令查看镜像(
IMAGE ID
和上面是一致的):1
2
3$ docker image ls com.wuwii/springboot-docker
REPOSITORY TAG IMAGE ID CREATED SIZE
com.wuwii/springboot-docker latest 622a7d1e315c 22 minutes ago 659MB运行容器:
1
2
3$ docker run -d -p 8080:8080 --name learn com.wuwii/springboot-docker
180fe4a7ddfc10c0cf2c37649ae1628e804564bfe1594ef05840e707801e6da3监听 8080 端口,测试是否成功。
服务编排 compose
一般的我们的 WEB 项目会使用到很多外部工具,例如 Redis ,MYSQL, ES等,如果一个一个启动搭建部署,太麻烦了,还要测试如果把这个一套环境拿到别的地方还能用吗?
使用服务编排可以避免这些坑。
加入我们的项目中增加了 Mysql 的数据库,在根目录新建一个 docker-compose.yml
:
1 | version: '3' |
上面我使用的是前面已经构建好的镜像,然后执行的编排,更好的是直接使用 build
让它自己编排服务。
系统配置文件application.yml
使用缺省值的方式,不影响开发的使用:
1 | spring: |
也可以使用不同的 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
总结
- 主要是写 Dockerfile 的时候最好单独的拿出一个文件夹来放它,我开始的时候就是直接放在项目的根路径,结果构建镜像的时候总是出现了将其他的文件也一起复制到了 Docker 目录中,WINDOW下使用 maven 插件操作这个需要注意这个上下文环境,不然很容易将一个磁盘的文件都拷贝进来了,初学者血的教训。解决办法就是单独创建一个文件夹,将需要的东西单独放置,就不用考虑这么多问题。