创建项目
创建spring boot项目,添加Spring Web依赖。
编写业务代码
一个简单的REST API。
package cn.har01d.demo.springbootdocker;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class GreetingController {
@Value("${server.name:Spring}")
private String serverName;
@RequestMapping("/")
public String hello() {
return "Hello world!";
}
@GetMapping("/server")
public String server() {
return serverName;
}
}
简单的Dockerfile
FROM openjdk:8-jdk-alpine
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
使用Maven构建项目
./mvnw package
使用Docker构建image
docker build -t springio/gs-spring-boot-docker .
运行Docker container
docker run --name spring-boot-docker --rm -p 8080:8080 -t springio/gs-spring-boot-docker
最小权限运行
容器默认运行在root用户,为了减少安全风险,创建一个新用户和组。容器运行在非root权限下。
修改Dockerfile
FROM openjdk:8-jdk-alpine
RUN addgroup -S spring && adduser -S spring -G spring
USER spring:spring
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
构建性能优化
一般情况下项目的依赖很少变化而项目本身代码经常变化。
Docker在构建过程中对不同的层有缓存机制,可以加快构建过程的速度。
修改Dockerfile
FROM openjdk:8-jre-alpine
RUN addgroup -S spring && adduser -S spring -G spring
USER spring:spring
ARG DEPENDENCY=target/dependency
COPY ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY ${DEPENDENCY}/META-INF /app/META-INF
COPY ${DEPENDENCY}/BOOT-INF/classes /app
ENTRYPOINT ["java","-cp","app:app/lib/*","cn.har01d.demo.springbootdocker.SpringBootDockerApplication"]
3个COPY创建了不同的层。
如果项目依赖没有变化,那么就可以重用。
构建Docker image
将Spring Boot生成的fat jar解压,取出依赖的jar文件。
mvn clean package
mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)
docker build -t springio/gs-spring-boot-docker .
使用Maven插件
spring-boot-maven-plugin插件支持直接构建Docker image,不需要使用Dockerfile。
修改pom.xml文件
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>build-image</goal>
</goals>
</execution>
</executions>
<configuration>
<image>
<name>springio/gs-spring-boot-docker</name>
</image>
</configuration>
</plugin>
</plugins>
</build>
运行时环境变量
指定Spring profiles
docker run -e "SPRING_PROFILES_ACTIVE=prod" -p 8080:8080 -t springio/gs-spring-boot-docker
修改server.name
docker run -e "server.name=Test" -p 8080:8080 -t springio/gs-spring-boot-docker
http://localhost:8080/server
HTTP/1.1 200
Content-Type: text/plain;charset=UTF-8
Content-Length: 4
Date: Sun, 12 Jun 2022 03:02:48 GMT
Keep-Alive: timeout=60
Connection: keep-alive
Test
Response code: 200; Time: 65ms; Content length: 4 bytes
Java Debug
docker run -e "JAVA_TOOL_OPTIONS=-agentlib:jdwp=transport=dt_socket,address=5005,server=y,suspend=n" -p 8080:8080 -p 5005:5005 -t springio/gs-spring-boot-docker
示例项目
https://github.com/power721/spring-boot-docker