目标
- 通过镜像版本控制代码版本
- 启动过程快速
大致思路
-
DOCKERFILE
构建过程获取最新代码 - 共享maven 本地仓库,
docker run
时提升maven clean package
速度
环境
- docker on windows (win10)
- 开发工具
idea
,构建工具maven
-
jdk8
,spring boot 2.0
开始
通过spring官网,我们可以快速的构建一个spring boot的项目。
引入pom依赖
本次使用的是spring boot构建restful API功能测试,pom.xml 如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>modao.wxp</groupId>
<artifactId>docker-springboot</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
其中有些地方需要说明下:
- spring boot 有很多starter,我们本次用了两个,一个是
parent
节点,另一个是starter-web
.parent
属于特殊的starter,内置dependency-management
,以及其他一些默认的配置,目的是方便我们不用去考虑版本依赖问题,直接使用内置版本。
而starter-web,是其中的一个用于web开发的依赖合集,非常方便。- 之所以引入
spring-boot-maven-plugin
是因为最后部署docker需要一个可执行的jar文件(具体刚刚的官网上有说明),不引用的话启动调试也是没有问题的,只是mvn clean package
命令的时候打出来的包执行的时候会报找不到主类的错误。
编写测试接口
package modao.dockerspringboot.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/")
public class TestController {
@GetMapping("/helloworld")
public String helloWorld(){
return "hello world";
}
}
测试
打开命令界面(ALT+F12),执行mvn clean package
后执行java -jar target\docker-springboot-1.0-SNAPSHOT.jar
docker 构建
win10下可以下载docker for windows,或者virtualbox虚拟机构建linux环境安装
编写DOCKERFILE
同样,在idea环境下打开命令行,如果你是docker on windows的话,如果不是你可以将项目文件拷贝到你指定的位置,再到目录下执行
FROM maven:3.5-jdk-8
COPY src /opt/app/
COPY pom.xml /opt/app/pom.xml
WORKDIR /opt/app
EXPOSE 8080
RUN mvn clean package
CMD java -jar ./target/*.jar
大致意思是:
基于
maven:3.5-jdk-8
(基础镜像),将项目源目录和pom.xml 拷贝到这个镜像内,然后设置工作目录,并导出8080端口。最后RUN mvn clean package
特别注意,是在build镜像过程中的命令,而CMD java -jar ./target/*.jar
是容器启动命令,具体可以查看docker官网
构建docker image
在当前目录下执行命令docker run -f Dockerfile -t dockerspringboot:1.0 .
注意最后的
.
,不能省略,表示当前路径,前面的命令表示我们要基于Dockerfile创建一个名称为dockerspringboot,版本为1.0的镜像,这个新镜像其实就是源镜像上面多加了一点点功能。这样的分层结构在编程里经常出现,很方便
问题的开始
你会发现你熟悉的mvn命令构建过程,但是使用的却是maven官网的仓库,超慢。。。
使用国内镜像
可以拷贝你本机的setting.xml文件,或者在默认的setting.xml配置阿里镜像:
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>central</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
我们将这个setting文件拷贝到项目路径下,与pom.xml同级,接下来要让这个setting起作用。
回到Dockerfile,我们可以在hub.docker.com上找到这个源镜像的使用说明
COPY settings.xml /usr/share/maven/ref/
我们在Dockerfile里加上这句:
FROM maven:3.5-jdk-8
COPY src /opt/app/
COPY pom.xml /opt/app/pom.xml
COPY settings.xml /usr/share/maven/ref/
WORKDIR /opt/app
EXPOSE 8080
RUN mvn clean package
CMD java -jar ./target/*.jar
Ctrl+C结束刚刚的任务,如果还没有结束的话
重新执行
docker build -f Dockerfile -t dockerspringboot:1.0 .
结果。。。还是使用的官方的
运行
我们试试将编译过程放到运行期试试
RUN mvn clean package
CMD java -jar ./target/*.jar
改为
CMD mvn clean package && java -jar ./target/*.jar
镜像构建过程快了,我们启动试试
docker run -it -p 8080:8080 dockerspringboot:1.0
加-it
可以看到启动过程,现在我们发现阿里镜像的配置启用了
但整个过程还是很慢
挂载docker volume
既然很慢,我们想最直接的办法就是缓存maven resposity不用每次都去下载。做法有两种,直接挂载本地目录和通过volume
创建docker volume
docker volume create --name maven-repo
具体参见docker官网,是一个可以容器间共享的挂载卷,为什么不直接挂载本地,因为windows文件格式的一些问题,我没有成功
更改运行命令:
docker run -it -p 8080:8080 -v maven-repo:/root/.m2 dockerspringboot:1.0
好了,你会发现当你第二次再运行的时候,缓存已经用上了,其他容器也可以共享这个镜像。同样的,如前端node_modules这样的文件夹也可以用类似的方式共享缓存,甚至有人搞出了拉方式的热部署。。
下一步
或许可以将代码托管git,构建时基于git这样就分离构建和代码,方便镜像版本构建,问题回溯。