GVKun编程网logo

使用属性server.port = 0运行spock测试时如何查找Spring Boot容器的端口(springboot从配置中心获取属性文件)

7

本文的目的是介绍使用属性server.port=0运行spock测试时如何查找SpringBoot容器的端口的详细情况,特别关注springboot从配置中心获取属性文件的相关信息。我们将通过专业的研

本文的目的是介绍使用属性server.port = 0运行spock测试时如何查找Spring Boot容器的端口的详细情况,特别关注springboot从配置中心获取属性文件的相关信息。我们将通过专业的研究、有关数据的分析等多种方式,为您呈现一个全面的了解使用属性server.port = 0运行spock测试时如何查找Spring Boot容器的端口的机会,同时也不会遗漏关于17. Spring Boot 配置嵌入式Servlet容器、4、SpringBoot嵌入式Servlet容器、docker 使用教程4-(Docker创建Java容器运行SpringBoot项目)、docker 部署springboot容器日志处理的知识。

本文目录一览:

使用属性server.port = 0运行spock测试时如何查找Spring Boot容器的端口(springboot从配置中心获取属性文件)

使用属性server.port = 0运行spock测试时如何查找Spring Boot容器的端口(springboot从配置中心获取属性文件)

鉴于此条目application.properties

server.port=0

这导致Spring Boot选择一个随机可用端口,并使用spock测试Spring Boot Web应用程序,spock代码如何知道要命中哪个端口?

正常注射是这样的:

@Value("${local.server.port}")int port;

不适用于spock。

答案1

小编典典

您可以使用以下代码找到端口:

int port = context.embeddedServletContainer.port

对于那些对java等效语言感兴趣的人:

int port = ((TomcatEmbeddedServletContainer)((AnnotationConfigEmbeddedWebApplicationContext)context).getEmbeddedServletContainer()).getPort();

这是一个可以扩展的抽象类,它包装了Spring Boot应用程序的初始化并确定了端口:

abstract class SpringBootSpecification extends Specification {    @Shared    @AutoCleanup    ConfigurableApplicationContext context    int port = context.embeddedServletContainer.port    void launch(Class clazz) {        Future future = Executors.newSingleThreadExecutor().submit(                new Callable() {                    @Override                    public ConfigurableApplicationContext call() throws Exception {                        return (ConfigurableApplicationContext) SpringApplication.run(clazz)                    }                })        context = future.get(20, TimeUnit.SECONDS);    }}

您可以这样使用:

class MySpecification extends SpringBootSpecification {    void setupSpec() {        launch(MyLauncher.class)    }    String getBody(someParam) {        ResponseEntity entity = new RestTemplate().getForEntity("http://localhost:${port}/somePath/${someParam}", String.class)        return entity.body;    }}

17. Spring Boot 配置嵌入式Servlet容器

17. Spring Boot 配置嵌入式Servlet容器

一、如何定制和修改Servlet容器的相关配置


 

1、配置文件(ServerProperties);

优先级最高

server.port=8081
server.context‐path=/crud
server.tomcat.uri‐encoding=UTF‐8
//通用的Servlet容器设置
server.xxx
//Tomcat的设置
server.tomcat.xxx

 

2、java代码

2.1 Spring Boot 1.5.10 版本 

@Bean //一定要将这个定制器加入到容器中 嵌入式的Servlet容器定制器
public EmbeddedServletContainerCustomizer embeddedServletContainerCustomizer(){
  return new EmbeddedServletContainerCustomizer() {
    //定制嵌入式的Servlet容器相关的规则
    @Override
    public void customize(ConfigurableEmbeddedServletContainer container) {
      container.setPort(8083);
    }
  };
}

 

2.2 Spring Boot 2.1.0版本

 2.2.1、 方式1  (优先级第二)

import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.stereotype.Component;
@Component
public class CustomizationBean implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {
    @Override
    public void customize(ConfigurableServletWebServerFactory server) {
        server.setPort(9000);
    }
}

 

  2.2.2、方式2 (优先级最低)

@Bean
public ConfigurableServletWebServerFactory webServerFactory() {
    TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
    factory.setPort(9000);
    // factory.setSessionTimeout(10, TimeUnit.MINUTES);  此方法没找到
    factory.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/notfound.html"));
    return factory;
}

 

二、自定义Servlet容器


 

1、Spring Boot 支持的 Servlet容器类型

 

 2、切换Tomcat容器为jetty容器

 

 

 

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions><!-- 排除掉默认的Tomcat web容器-->
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<!-- 引入jetty容器。jetty 适合长连接的场景-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jetty</artifactId><!--  spring-boot-starter-undertow ,不支持JSP-->
</dependency>

 

undertow

 

 

包下:spring-boot-autoconfigure-2.1.0.RELEASE.jar

 

 

三、嵌入式Servlet容器自动配置原理Spring Boot 2.1.0版本示例: (注:1.5.10 和2.1.0版本有很大不同)


 

 Servelt容器的自动配置类

@Configuration
@ConditionalOnWebApplication
@EnableConfigurationProperties(ServerProperties.class)
public class EmbeddedWebServerFactoryCustomizerAutoConfiguration {

    /**
     * Nested configuration if Tomcat is being used.
     */
    @Configuration
    @ConditionalOnClass({ Tomcat.class, UpgradeProtocol.class })
    public static class TomcatWebServerFactoryCustomizerConfiguration {

        @Bean
        public TomcatWebServerFactoryCustomizer tomcatWebServerFactoryCustomizer(
                Environment environment, ServerProperties serverProperties) {
            return new TomcatWebServerFactoryCustomizer(environment, serverProperties);
        }

    }

    /**
     * Nested configuration if Jetty is being used.
     */
    @Configuration
    @ConditionalOnClass({ Server.class, Loader.class, WebAppContext.class })
    public static class JettyWebServerFactoryCustomizerConfiguration {

        @Bean
        public JettyWebServerFactoryCustomizer jettyWebServerFactoryCustomizer(
                Environment environment, ServerProperties serverProperties) {
            return new JettyWebServerFactoryCustomizer(environment, serverProperties);
        }

    }

    /**
     * Nested configuration if Undertow is being used.
     */
    @Configuration
    @ConditionalOnClass({ Undertow.class, SslClientAuthMode.class })
    public static class UndertowWebServerFactoryCustomizerConfiguration {

        @Bean
        public UndertowWebServerFactoryCustomizer undertowWebServerFactoryCustomizer(
                Environment environment, ServerProperties serverProperties) {
            return new UndertowWebServerFactoryCustomizer(environment, serverProperties);
        }

    }

    /**
     * Nested configuration if Netty is being used.
     */
    @Configuration
    @ConditionalOnClass(HttpServer.class)
    public static class NettyWebServerFactoryCustomizerConfiguration {

        @Bean
        public NettyWebServerFactoryCustomizer nettyWebServerFactoryCustomizer(
                Environment environment, ServerProperties serverProperties) {
            return new NettyWebServerFactoryCustomizer(environment, serverProperties);
        }

    }

}

 

 Tomcat 的Server的定制(Jetty、Netty、Undertow 类似)

public class TomcatWebServerFactoryCustomizer implements
        WebServerFactoryCustomizer<ConfigurableTomcatWebServerFactory>, Ordered {

    private final Environment environment;

    private final ServerProperties serverProperties;

    public TomcatWebServerFactoryCustomizer(Environment environment,
            ServerProperties serverProperties) {
        this.environment = environment;
        this.serverProperties = serverProperties;
    }

    @Override
    public int getOrder() {
        return 0;
    }

    @Override
    public void customize(ConfigurableTomcatWebServerFactory factory) {
        ServerProperties properties = this.serverProperties;
        ServerProperties.Tomcat tomcatProperties = properties.getTomcat();
        PropertyMapper propertyMapper = PropertyMapper.get();
        propertyMapper.from(tomcatProperties::getBasedir).whenNonNull()
                .to(factory::setBaseDirectory);
        propertyMapper.from(tomcatProperties::getBackgroundProcessorDelay).whenNonNull()
                .as(Duration::getSeconds).as(Long::intValue)
                .to(factory::setBackgroundProcessorDelay);
        customizeRemoteIpValve(factory);
        propertyMapper.from(tomcatProperties::getMaxThreads).when(this::isPositive)
                .to((maxThreads) -> customizeMaxThreads(factory,
                        tomcatProperties.getMaxThreads()));
        propertyMapper.from(tomcatProperties::getMinSpareThreads).when(this::isPositive)
                .to((minSpareThreads) -> customizeMinThreads(factory, minSpareThreads));
        propertyMapper.from(this::determineMaxHttpHeaderSize).whenNonNull()
                .asInt(DataSize::toBytes).when(this::isPositive)
                .to((maxHttpHeaderSize) -> customizeMaxHttpHeaderSize(factory,
                        maxHttpHeaderSize));
        propertyMapper.from(tomcatProperties::getMaxSwallowSize).whenNonNull()
                .asInt(DataSize::toBytes)
                .to((maxSwallowSize) -> customizeMaxSwallowSize(factory, maxSwallowSize));
        propertyMapper.from(tomcatProperties::getMaxHttpPostSize).asInt(DataSize::toBytes)
                .when((maxHttpPostSize) -> maxHttpPostSize != 0)
                .to((maxHttpPostSize) -> customizeMaxHttpPostSize(factory,
                        maxHttpPostSize));
        propertyMapper.from(tomcatProperties::getAccesslog)
                .when(ServerProperties.Tomcat.Accesslog::isEnabled)
                .to((enabled) -> customizeAccessLog(factory));
        propertyMapper.from(tomcatProperties::getUriEncoding).whenNonNull()
                .to(factory::setUriEncoding);
        propertyMapper.from(properties::getConnectionTimeout).whenNonNull()
                .to((connectionTimeout) -> customizeConnectionTimeout(factory,
                        connectionTimeout));
        propertyMapper.from(tomcatProperties::getMaxConnections).when(this::isPositive)
                .to((maxConnections) -> customizeMaxConnections(factory, maxConnections));
        propertyMapper.from(tomcatProperties::getAcceptCount).when(this::isPositive)
                .to((acceptCount) -> customizeAcceptCount(factory, acceptCount));
        customizeStaticResources(factory);
        customizeErrorReportValve(properties.getError(), factory);
    }
。。。。。。
}

 

 

Spring Boot 2.1.0 版本的web容器启动流程 (Spring boot 1.5.10版本类似但不同)

 

1.Spring boot启动器

@SpringBootApplication
public class SpringBootDemo01Application {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootDemo01Application.class, args);
    }
}

 

2.run方法启动过程源码分析

public class SpringApplication {
   //在createApplicationContext()中根据类型classforName()加载 不同类型的  
    public static final String DEFAULT_CONTEXT_CLASS = "org.springframework.context."
            + "annotation.AnnotationConfigApplicationContext";

    public static final String DEFAULT_SERVLET_WEB_CONTEXT_CLASS = "org.springframework.boot."
            + "web.servlet.context.AnnotationConfigServletWebServerApplicationContext";

    public static final String DEFAULT_REACTIVE_WEB_CONTEXT_CLASS = "org.springframework."
            + "boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext";

   //run1调用run2
public static ConfigurableApplicationContext run(Class<?> primarySource,String... args) { return run(new Class<?>[] { primarySource }, args); }    //run2调用run3 public static ConfigurableApplicationContext run(Class<?>[] primarySources,String[] args) { return new SpringApplication(primarySources).run(args); }
   //run3启动Web服务器
public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>(); configureHeadlessProperty(); SpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting(); try { ApplicationArguments applicationArguments = new DefaultApplicationArguments( args); ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); configureIgnoreBeanInfo(environment); Banner printedBanner = printBanner(environment); context = createApplicationContext(); exceptionReporters = getSpringFactoriesInstances( SpringBootExceptionReporter.class, new Class[] { ConfigurableApplicationContext.class }, context); prepareContext(context, environment, listeners, applicationArguments, printedBanner); refreshContext(context); afterRefresh(context, applicationArguments); stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass) .logStarted(getApplicationLog(), stopWatch); } listeners.started(context); callRunners(context, applicationArguments); } catch (Throwable ex) { handleRunFailure(context, ex, exceptionReporters, listeners); throw new IllegalStateException(ex); } try { listeners.running(context); } catch (Throwable ex) { handleRunFailure(context, ex, exceptionReporters, null); throw new IllegalStateException(ex); } return context; } protected ConfigurableApplicationContext createApplicationContext() { Class<?> contextClass = this.applicationContextClass; if (contextClass == null) { try { switch (this.webApplicationType) { case SERVLET: contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS); break; case REACTIVE: contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS); break; default: contextClass = Class.forName(DEFAULT_CONTEXT_CLASS); } } catch (ClassNotFoundException ex) { throw new IllegalStateException( "Unable create a default ApplicationContext, " + "please specify an ApplicationContextClass", ex); } } return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass); } private void refreshContext(ConfigurableApplicationContext context) { refresh(context); if (this.registerShutdownHook) { try { context.registerShutdownHook(); } catch (AccessControlException ex) { // Not allowed in some environments. } } } protected void refresh(ApplicationContext applicationContext) { Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext); ((AbstractApplicationContext) applicationContext).refresh(); } }

 

 

public abstract class AbstractApplicationContext extends DefaultResourceLoader
        implements ConfigurableApplicationContext {
        
            @Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            prepareRefresh();

            // Tell the subclass to refresh the internal bean factory.
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            prepareBeanFactory(beanFactory);

            try {
                // Allows post-processing of the bean factory in context subclasses.
                postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                registerBeanPostProcessors(beanFactory);

                // Initialize message source for this context.
                initMessageSource();

                // Initialize event multicaster for this context.
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
                onRefresh();

                // Check for listener beans and register them.
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons.
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                finishRefresh();
            }

            catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }

                // Destroy already created singletons to avoid dangling resources.
                destroyBeans();

                // Reset ''active'' flag.
                cancelRefresh(ex);

                // Propagate exception to caller.
                throw ex;
            }

            finally {
                // Reset common introspection caches in Spring''s core, since we
                // might not ever need metadata for singleton beans anymore...
                resetCommonCaches();
            }
        }
    }
    protected void onRefresh() throws BeansException {
        // For subclasses: do nothing by default.
    }
    
}

 

 

public class ServletWebServerApplicationContext extends GenericWebApplicationContext
        implements ConfigurableWebServerApplicationContext {
        
    @Override
    protected void onRefresh() {
        super.onRefresh();
        try {
            createWebServer();
        }
        catch (Throwable ex) {
            throw new ApplicationContextException("Unable to start web server", ex);
        }
    }
    
    
    private void createWebServer() {
        WebServer webServer = this.webServer;
        ServletContext servletContext = getServletContext();
        if (webServer == null && servletContext == null) {
            ServletWebServerFactory factory = getWebServerFactory();
            this.webServer = factory.getWebServer(getSelfInitializer());
        }
        else if (servletContext != null) {
            try {
                getSelfInitializer().onStartup(servletContext);
            }
            catch (ServletException ex) {
                throw new ApplicationContextException("Cannot initialize servlet context",
                        ex);
            }
        }
        initPropertySources();
    }
        
}

 

 

 

spring-boot-2.1.0.RELEASE.jar

 

4、SpringBoot嵌入式Servlet容器

4、SpringBoot嵌入式Servlet容器

1、切换嵌入式Servlet容器

  • 默认支持的web服务器webServer:
 Tomcat, Jetty,  Undertow
 ServletWebServerApplicationContext 容器启动寻找ServletWebServerFactory 并引导创建服务器
  • 切换服务器(可以切换四种)
    image.png

    切换的方式:
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-web</artifactId>
              <exclusions>
                  <exclusion> 排除
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-tomcat</artifactId>
                  </exclusion>
              </exclusions>
          </dependency>
          <dependency>  导入
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-undertow</artifactId>
          </dependency>
              
              
    2022-07-17 19:34:02.650  INFO 6808 --- [  restartedMain] o.s.b.w.e.undertow.UndertowWebServer     : Undertow started on port(s) 8080 (http)

原理

  • SpringBoot应用启动发现当前是Web应用。因为导了web场景包,它里面也导入tomcat
  • web应用会创建一个web版的ioc容器,名字叫 ServletWebServerApplicationContext
  • ServletWebServerApplicationContext 它在项目一启动的时候寻找 ServletWebServerFactory(Servlet 的web服务器工厂---> 这个工厂生产 Servlet 的web服务器)
  • SpringBoot底层默认有很多的WebServer工厂:TomcatServletWebServerFactory, JettyServletWebServerFactory, UndertowServletWebServerFactory
  • 这些web服务器工厂不需要我们配,底层直接会有一个自动配置类ServletWebServerFactoryAutoConfiguration
  • ServletWebServerFactoryAutoConfiguration导入了ServletWebServerFactoryConfiguration(配置类)
  • ServletWebServerFactoryConfiguration 配置类 根据动态判断系统中到底导入了哪个Web服务器的包。(默认是web-starter导入tomcat包),容器中就有 TomcatServletWebServerFactory
  • TomcatServletWebServerFactory 创建出Tomcat服务器TomcatWebServer并启动;TomcatWebServer 的构造器拥有初始化方法initialize,这个初始化方法把所有东西准备好,把tomcat调用start方法this.tomcat.start();启动tomcat
  • 其实内嵌服务器,就是手动把启动服务器的代码调用(前提是tomcat核心jar包存在,才能启动tomcat)

2、定制Servlet容器

  • 实现 WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>
    ○ 把配置文件的值和ServletWebServerFactory 进行绑定
  • 修改配置文件 server.xxx
  • 直接自定义 ConfigurableServletWebServerFactory

xxxxxCustomizer:定制化器,可以改变xxxx的默认规则

import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.stereotype.Component;

@Component
public class CustomizationBean implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {

    @Override
    public void customize(ConfigurableServletWebServerFactory server) {
        server.setPort(9000);
    }

}

docker 使用教程4-(Docker创建Java容器运行SpringBoot项目)

docker 使用教程4-(Docker创建Java容器运行SpringBoot项目)

上一篇  docker 使用教程3-(Docker安装Nginx) 学习如何拷贝文件到容器

本篇介绍如何使用docker创建Java容器运行SpringBoot项目

 

大部分教程都是使用Dockerfile来创建镜像再去运行,当然这也是一种办法,本篇两种方法都有介绍: 

思路1:先拉取java镜像,构建java容器,再把SpringBoot的jar包拷进容器,然后进入容器运行jar包就OK了。

思路2:构建DockerFile创建SpringBoot容器运行。

 

实现方式一

①、拉取镜像

docker pull java:8

 

②、运行容器

docker run -p 8888:8001 --name java-test -d java:8 tail -f /dev/null

参数解释:

-p 端口映射:(主机端口:容器端口)
--name 容器名称(java-test)
-d 后台运行
java:8 镜像名称:版本号
tail -f /dev/null 有事可做(不然运行了就退出了)

 

 

 

 

 

 

 

③、拷贝 jar 包到容器内部

    1、先下载SpringBoot项目jar包

          jar包下载地址:https://gitee.com/cnetopro/springboot-dcoker

    2、通过Xftp或者其他软件把 springboot-0.0.1-SNAPSHOT.jar 传输到主机

    3、把 springboot-0.0.1-SNAPSHOT.jar 拷贝到容器内部

docker cp /root/springboot-0.0.1-SNAPSHOT.jar 容器ID:/

 

④、进入容器运行项目

进入容器

docker exec -it 容器ID bash

运行SpringBoot项目

nohup java -jar springboot-0.0.1-SNAPSHOT.jar /dev/null 2>&1 &

参数解释:

buhup 谐音no hope,用于后台运行退出不终止项目。
dev/null 日志输入地址(不保留日志)
2>&1 & 标准输出

 

 

 

 

查看运行情况

ps -aux|grep java

 

⑤万事大吉

在浏览器输入 IP:8888 即可看到:

Hello SpringBoot Docker

 

实现方式二

使用Dockerfile构建SpringBoot项目运行环境

①、拉取镜像

docker pull java:8

 

②、下载 SpringBoot 项目 jar 包

    1、先下载SpringBoot项目jar包

          jar包下载地址:https://gitee.com/cnetopro/springboot-dcoker

    2、通过Xftp或者其他软件把 springboot-0.0.1-SNAPSHOT.jar 传输到主机

 

③、创建Dockerfile

vim Dockerfile

内容:

FROM java:8
copY springboot-0.0.1-SNAPSHOT.jar /
CMD java -jar springboot-0.0.1-SNAPSHOT.jar

解释:

FROM 基于 java:8镜像创建
copY 把当前目录的springboot-0.0.1-SNAPSHOT.jar拷贝到容器内的/目录下
CMD 执行命令java -jar springboot-0.0.1-SNAPSHOT.jar 运行项目

 

 

 

 

 

④、构建镜像

docker build -t springboot_test .

解释:

build -t

构建镜像名为 springboot_test
. 表示当前目录的Dockerflie文件

 

 

 

 

 

⑤、运行镜像

docker run -p 8888:8001 --name java-test -d springboot_test

 

⑥、万事大吉

在浏览器输入 IP:8888 即可看到:

Hello SpringBoot Docker

 

docker 部署springboot容器日志处理

docker 部署springboot容器日志处理

将jdk和需要的运行的jar构建成镜像之后,运行成容器之后,可以实时的输出日志,但是当容器挂掉之后,日志也便消失不见。在容器中可以运行bash命令的前提下,容器运行的时候会根据jar中配置的日志目录生成相应的日志文件,当容器停止的时候在容器中的所有的东西也会消失不见,查询原因时就会遇到问题。
 

方式一:

docker logs containerId/containerName

这种方式存在的问题是只能实时输出层,存储的路径在容器内部,容器挂掉之后日志变会消失不见。这种方式存在的问题是只能实时输出层,存储的路径在容器内部,容器挂掉之后日志变会消失不见。

方式二:

数据卷的方式

docker run -d -v /home/vincent/logs/:/logs/ -p 8081:8080  txxs/springboot

前边的是宿主机中日志的目录,后边是容器中日志文件的输出目录,指定暴露的端口号是8081。

这样就可以在外部docker的宿主机上看到日志,但是问题是再次启动镜像的时候日志会怎么办呢,这时候并不会重新新建文件而是直接在原文件的末尾添加,也就是这两个容器的日志文件合并为同一个。改变的办法可以很简单,虽然镜像都是一样的,但是可以动态的生成日志文件的名字,这样在启动镜像的时候因为日志文件的名字不同,也就不存在上边的问题了。具体日志文件的名字可以使用时间或者IP+序号的方式进行拼接。

今天关于使用属性server.port = 0运行spock测试时如何查找Spring Boot容器的端口springboot从配置中心获取属性文件的讲解已经结束,谢谢您的阅读,如果想了解更多关于17. Spring Boot 配置嵌入式Servlet容器、4、SpringBoot嵌入式Servlet容器、docker 使用教程4-(Docker创建Java容器运行SpringBoot项目)、docker 部署springboot容器日志处理的相关知识,请在本站搜索。

本文标签: