Open LangVE opened 2 years ago
$ ./mvnw package
$ java -jar target/hacking-spring-boot-ch5-reactive-0.0.1-SNAPSHOT.jar
FROM adoptopenjdk/openjdk8:latest
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]
애플리케이션을 여러 부분으로 분할해서 여러 계층에 나눠 담고 도커의 캐시 시스템을 활용하는 것이 더 효율적.
하지만 스프링부트 메이븐 플러그인에 내장된 도커 지원 기능을 활용하는 편이 더 낫다. 이를 위해 pom.xml 파일에 계층화 방식을 사용한다고 지정한다.
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<layers>
<enabled>true</enabled>
</layers>
</configuration>
</plugin>
$ ./mvnw clean package
$ java -Djarmode=layertools -jar target/hacking-spring-boot-ch5-reactive-0..1-SNAPSHOT.jar list
dependencies
spring-boot-loader
snapshot-dependencies
application
스프링 부트가 jarmode-layertools 파라미터를 인식해서 list 명령을 만나면 JAR 파일에 내장된 모든 계층을 보여준다
FROM adoptopenjdk/openjdk8:latest as builder
WORKDIR application
ARG JAR FILE=target/*.jar
COPY ${JAR_FILE} application.jar
RUN java -Diarmode=layertools -jar application.jar extract
FROM adoptopenjdk/openjdk8:latest
WORKDIR application
COPY --from=builder application/dependencies/ ./
COPY --from=builder application/spring-boot-loader/ ./
#COPY --from=builder application/snapshot-dependencies/ ./
COPY --from=builder application/application/ ./
ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]
$ docker build . --tag hacking-with-spring-boot
$ docker run -it -p 8080:8080 hacking-with-sprint-boot:latest
$ ./mvnw spring-boot:build-image
spring-boot:build-image 명령을 실행하면 스프링 부트가 페이카토 빌드팩 프로젝트에서 빌드펙을 가져와서 도커 컨테이너 이미지를 빌드한다.
$ docker run -it -p 8080:8080 docker.io/library/hacking-spring-boot-ch5-reactive:0.0.1-SNPSHOP
방식 | 장점 | 단점 |
---|---|---|
계층 기반 Dockerfile 이미지 | - Dockerfile을 직접 작성하므로 이미지 빌드 전체 과정 제어 가능. - 스프링 부트에서 계층화를 제공하므로 빌드 과정 최적화 가능 |
- 컨테이너 직접 관리 - 컨테이너를 빌드 과정이 완전하지 않으면 보안에 취약한 계층 존재 위험 |
페이키토 빌드팩 기반 이미지 | - Dockerfile을 직접 다룰 필요 없음. - 최신 패치와 SSL을 포함한 업계표준 컨테이너 기술이 빌드 과정에 포함 - 개발에 더 집중 가능 |
- DOckerfile에 비해 제어할 수 있는 것이 적음 |
management.endpoint.health.show-details=always
info.project.version=@project.version@
info.java.version=@java.version@
info.spring.framework.version=@spring-framework.version@
info.spring.data.version=@spring-data-bom.version@
<plugin>
<groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId>
</plugin>
management.endpoints.web.exposure.include=*
management.endpoints.web.exposure.include=aduitevents,beans,caches, ...
$ curl -v -H 'Content-Type: application/json' -d '{"configuraedLevel": "TRACE"}' http://localhost:8080/actuator/loggers/com.greglturnquist/
@Bean
HttpTraceRepository traceRepository(){
return new InMemoryHttpTraceRepository();
}
public class HttpTraceWrapper {
private @Id String id;
private HttpTrace httpTrace;
public HttpTraceWrapper(HttpTrace httpTrace) {
this.httpTrace = httpTrace;
}
public HttpTrace getHttpTrace() {
return httpTrace;
}
}
public interface HttpTraceWrapperRepository extends Repository<HttpTraceWrapper, String> {
Stream<HttpTraceWrapper> findAll();
void save(HttpTraceWrapper trace);
}
public class SpringDateHttpTraceRepository implements HtttpTraceRepository {
private final HttpTraceWrapperRepository repositoty;
public SpringDataHttpTraceRepository(HttpTraceWrapperRepository repository) {
this.repositoty = repositoty;
}
@Override
public List<HttpTrace> findAll() {
return repository.findAll()
.map(HttpTraceWrapper::getHttpTrace)
.collect(Collectors.toList());
}
@Override
public void add(HttpTrace trace) {
repository.save(new HttpTraceWrapper(trace));
}
}
@Bean
HttpTraceRepository springDataTraceRepository(HttpTraceWrapperRepository repository) {
return new SpringDateHttpTraceRepository(repositoty)
}
static Converter<Document, HttpTraceWrapper> CONVERTER = new Converter<Document, HttpTraceWrapper>() {
@Overrid
public HttpTraceWrapper convert(Document document) {
Document httpTrace = document.get("httpTrace", Document.class);
Document request = httpTrace.get("request", Document.class);
Document response = httpTrace.get("response", Document.class);
return new HttpTraceWrapper(new HttpTrace(
new HttpTrace.Request(request.getString("method"),
URI.create(request.getStirng("uri")),
request.get("headers", Map.class),
null),
new Httptrace.Response(response.getInterger("status"),
response.get("headers", Map.class)),
httpTrace.getDate("timestamp").toInstant(),
null,
null,
httpTrace.getLong("timeTaken")));
}
}
@Bean
public MappingMongoConverter mappingMongoConverter(MongoMappingContext context) {
MappingMongoConverter mappingConverter = new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, context);
mappingConverter.setCustomConversions(new MongoCustomConversions(Collections.singletonList(Converter)));
return mappingConverter;
}
management.endpoints.web.base-path=?manage
management.endpoints.web.base-path=/
management.endpoints.web.path-mapping.loggers=logs
스터디 5회차