Dockerfile制作官方Tomcat镜像及镜像使用详解

这两天学习了Dockerfile感觉这个地方知识点挺多的,而且很重要,所以,今天添加一点小笔记。

官方Tomcat镜像

地址:https://hub.docker.com/_/tomcat/

镜像的Full Description中,我们可以得到许多信息,这里简单介绍几个:

1.Supported tags and respective Dockerfile links

支持的标签,以及对应的Dockerfile链接。一个Dockerfile可以对应多个标签,我们将以8.5.16-jre8版本的Dockerfile进行分析。

2.How to use this image

如何使用本镜像,包括了以不同方式运行容器的命令,以及一些主要环境变量。这里讲的不够详细,我们会详细讲解。

准备知识:APR、Tomcat Native、Tomcat的APR模式

APR是Apache Portable Runtime的简写,其实就是一组用C语言编写的动态链接库,提供统一的API接口,用于访问操作系统底层。详见:http://apr.apache.org/

Tomcat Native的主要作用是为tomcat提供访问本地资源的功能。即利用APR库,访问网络、生成随机数等。Tomcat Native依赖于APR、OpenSSL、JDK。详见:http://tomcat.apache.org/native-doc/

在配置好Tomcat Native后,可以在tomcat配置文件中开启APR模式。开启之后,Tomcat就会直接调用APR库访问网络,不用再通过jvm中转。

因为APR和Tomcat Native是和具体的操作系统紧密关联的,并不像java应用那样编译好后就可以跨平台使用。所以tomcat默认不安装这些功能,而是根据需要,以及具体操作系统,手工编译源码安装。从一些资料上来看,开启tomcat的APR模式后,对tomcat的性能并不一定会有很大的提升(在某些情况下甚至可能下降)。是否开启APR模式要看具体的情况。个人认为,一般情况下,真到了要挖掘Tomcat性能的时候,使用tomcat集群将会是一种更好的解决方案,这对系统的性能、稳定性、可靠性都有提升。

分析Dockerfile(tomcat:8.5.16-jre8)

地址:https://github.com/docker-library/tomcat/blob/master/8.5/jre8/Dockerfile

注意,这里以master分支的Dockerfile链接为例,和DockerHub上的Dockerfile链接可能会不一致,不过不影响我们接下来的分析。以下就是这个Dockerfile的内容,我加了注释加以说明:

#本镜像的基础镜像。有兴趣的话,可以自行在DockerHub上搜索openjdk,分析官方的openjdk镜像的Dockerfile文件。这里为什么不用oracle提供的jdk(jre)?简单地讲,版权问题。
FROM openjdk:8-jre

#声明CATALINA_HOME环境变量,这个变量大家都了解。
ENV CATALINA_HOME /usr/local/tomcat
#将Tomcat下的bin路径加入到PATH环境变量中。
ENV PATH $CATALINA_HOME/bin:$PATH
#创建tomcat路径。
RUN mkdir -p "$CATALINA_HOME"
#指定RUN、CMD、ENTRYPOINT命令的当前工作路径。
WORKDIR $CATALINA_HOME

#Tomcat Native路径配置。
ENV TOMCAT_NATIVE_LIBDIR $CATALINA_HOME/native-jni-lib
#将TOMCAT_NATIVE_LIBDIR加入到LD_LIBRARY_PATH环境变量中,这样Tomcat在查找Tomcat Native相关的动态链接库时,会去查找TOMCAT_NATIVE_LIBDIR环境变量指定的路径。
ENV LD_LIBRARY_PATH ${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$TOMCAT_NATIVE_LIBDIR

#检查、更新OpenSSL,这块的细节我没深究。
ENV OPENSSL_VERSION 1.1.0f-3
RUN { \
  echo 'deb http://deb.debian.org/debian stretch main'; \
 } > /etc/apt/sources.list.d/stretch.list \
 &> /etc/apt/preferences.d/stretch-openssl
RUN apt-get update && apt-get install -y --no-install-recommends \
  libapr1 \
  openssl="$OPENSSL_VERSION" \
 && rm -rf /var/lib/apt/lists/*

#从key服务器导入key,用于验证tomcat压缩文件的签名,这块也没深究。
ENV GPG_KEYS 05AB33110949707C93A279E3D3EFE6B686867BA6 07E48665A34DCAFAE522E5E6266191C37C037D42 47309207D818FFD8DCD3F83F1931D684307A10A5 541FBE7D8F78B25E055DDEE13C370389288584E7 61B832AC2F1C5A90F0F9B00A1C506407564C17A3 713DA88BE50911535FE716F5208B0AB1D63011C7 79F7026C690BAA50B92CD8B66A3AD3F4F22C4FED 9BA44C2621385CB966EBA586F72C284D731FABEE A27677289986DB50844682F8ACB77FC2E86E29AC A9C5DF4D22E99998D9875A5110C01C5A2F6059E7 DCFD35E0BF8CA7344752DE8B6FB21E8933C60243 F3A04C595DB5B6A5F1ECA43E3B7BBB100D811BBE F7DA48BB64BCB84ECBA7EE6935CD23C10D498E23
RUN set -ex; \
 for key in $GPG_KEYS; do \
  gpg --keyserver ha.pool.sks-keyservers.net --recv-keys "$key"; \
 done

#Tomcat相关文件的版本。
ENV TOMCAT_MAJOR 8
ENV TOMCAT_VERSION 8.5.16

#Tomcat相关文件下载地址。
ENV TOMCAT_TGZ_URL https://www.apache.org/dyn/closer.cgi?action=download&filename=tomcat/tomcat-$TOMCAT_MAJOR/v$TOMCAT_VERSION/bin/apache-tomcat-$TOMCAT_VERSION.tar.gz
ENV TOMCAT_ASC_URL https://www.apache.org/dist/tomcat/tomcat-$TOMCAT_MAJOR/v$TOMCAT_VERSION/bin/apache-tomcat-$TOMCAT_VERSION.tar.gz.asc

#执行命令
RUN set -x \
 \
 #下载Tomcat压缩文件
 && wget -O tomcat.tar.gz "$TOMCAT_TGZ_URL" \
 && wget -O tomcat.tar.gz.asc "$TOMCAT_ASC_URL" \
 #进行签名验证
 && gpg --batch --verify tomcat.tar.gz.asc tomcat.tar.gz \
 #解压Tomcat
 && tar -xvf tomcat.tar.gz --strip-components=1 \
 # 删除供Windows系统使用的.bat文件
 && rm bin/*.bat \
 # 删除压缩文件
 && rm tomcat.tar.gz* \
 \
 #安装Tomcat Native
 && nativeBuildDir="$(mktemp -d)" \
 && tar -xvf bin/tomcat-native.tar.gz -C "$nativeBuildDir" --strip-components=1 \
 && nativeBuildDeps=" \
  dpkg-dev \
  gcc \
  libapr1-dev \
  libssl-dev \
  make \
  openjdk-${JAVA_VERSION%%[-~bu]*}-jdk=$JAVA_DEBIAN_VERSION \
 " \
 && apt-get update && apt-get install -y --no-install-recommends $nativeBuildDeps && rm -rf /var/lib/apt/lists/* \
 && ( \
  export CATALINA_HOME="$PWD" \
  && cd "$nativeBuildDir/native" \
  && gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)" \
  && ./configure \
   --build="$gnuArch" \
   --libdir="$TOMCAT_NATIVE_LIBDIR" \
   --prefix="$CATALINA_HOME" \
   --with-apr="$(which apr-1-config)" \
   --with-java-home="$(docker-java-home)" \
   --with-ssl=yes \
  && make -j "$(nproc)" \
  && make install \
 ) \
 && apt-get purge -y --auto-remove $nativeBuildDeps \
 && rm -rf "$nativeBuildDir" \
 && rm bin/tomcat-native.tar.gz

#验证Tomcat Native是否安装成功
RUN set -e \
 && nativeLines="$(catalina.sh configtest 2>&1)" \
 && nativeLines="$(echo "$nativeLines" | grep 'Apache Tomcat Native')" \
 && nativeLines="$(echo "$nativeLines" | sort -u)" \
 && if ! echo "$nativeLines" | grep 'INFO: Loaded APR based Apache Tomcat Native library' >&2; then \
  echo >&2 "$nativeLines"; \
  exit 1; \
 fi

#暴露8080端口
EXPOSE 8080
#容器启动时执行的命令。
CMD ["catalina.sh", "run"]

此Dockerfile的主要功能可归纳为:

1.以openjdk镜像为基础镜像进行构建。

2.安装Tomcat Native,及其依赖库(比如APR、OpenSSL等)。验证是否正确安装。

3.下载Tomcat,检查签名,解压、清除无用文件等。

4.暴露8080端口,配置入口命令。

总的来说,此Dockerfile的功能还是比较清晰的,如果要自己构建自己的Tomcat镜像,可以参考本Dockerfile。另外,Tomcat的Dockerfile应该是自动生成而非手工编写,因为第一,Tomcat的有很多版本的Dockerfile,手工维护工作量大;第二,存在一些我认为不是很很合理的地方(比如从key server上获取很多key)。所以大家在分析一些官方Dockerfile时,如果遇到一些感觉不是很合理的地方也别太纠结。

如何使用官方镜像

$ docker run -d --name tomcat-test -p 8888:8080 tomcat:8.5.16-jre8

以上指令将使用本镜像启动一个容器,你可以通过http://本机ip:8888访问到容器中的Tomcat。这种方式并没有部署应用,所以其实也没什么实际意义。

$ docker run -d --name tomcat-test -p 8888:8080 \
-v /home/myWebApp:/usr/local/tomcat/webapps/ROOT \
-v /home/myWebAppLogs:/usr/local/tomcat/logs \
tomcat:8.5.16-jre8

以上指令增加了两个volume,将/home/myWebApp挂载到容器中的/usr/local/tomcat/webapps/ROOT,将/home/myWebAppLogs挂载到容器中的/usr/local/tomcat/logs路径。容器启动后,tomcat的根应用将会是myWebApp(通过http://本机ip:8888访问),并且tomcat的日志将会输出到/home/myWebAppLogs路径下。
 此后,如果容器被删除,应用和应用的日志也不会随容器一起删除。更新应用时,只需要更新/home/myWebApp路径,再重启容器即可。

如果不想把应用挂载到根目录下,可以更改volume配置,比如:-v /home/myWebApp:/usr/local/tomcat/webapps/myWebApp,再通过http://本机ip:8888/myWebApp访问。

注意:如果想把myWebApp内部的日志也输出到/home/myWebAppLogs路径下,请配置myWebApp的日志文件的输出路径为Tomcat日志路径(相对路径),例如:logs/myLog.log。这样,myWebApp的日志文件将会输出至/usr/local/tomcat/logs下(因为挂载了volume,其实是输出到/home/myWebAppLogs路径下)。

从规范的角度讲,其实这种应用部署方式并不值得推荐,因为部署还是出现了环境相关性。也就是说,必须先把应用目录、日志目录指定好,才能进行部署。而且如果要一台机上要部署两个相同的应用进行负载均衡也比较麻烦(要建两套应用和日志目录,并且修改容器启动命令),难以实现自动化部署。但话又说回来,我相信这种部署方式还是会受到大部分人欢迎的。目前我们公司在测试环境中也普遍使用这种模式,以便一台测试服务器部署多个应用(Tomcat),彼此之间完全没有关联和影响。

如果要做到完全环境无关性部署,可以考虑自己在官方Tomcat镜像的基础上,构建出一个新的镜像。在这个新镜像的Dockerfile中直接下载并部署myWebApp,并使用某些工具或框架,将Tomcat和myWebApp产生的日志,上传汇总到一个统一的日志服务中。这样,如果要再部署一个相同的应用,只要给我一台装有Docker环境的机器,我执行一条指令即可(同一Docker环境下注意端口冲突)。这种方式有利于自动化部署,在服务器数量较多的情况下比较合适。当然,这种方式也有比较麻烦的地方,就是每发布以一个应用版本,都要重新构建一个新的镜像。

关于自动化部署,还可以参考Docker Compose和Kubernetes,这里不做深入(主要是本人对这块的了解和应用也不够多)。

官方镜像的不足

在本镜像的实际使用过程中,还是遇到了一些问题:

1.为了照顾到全球的镜像使用者,官方的openjdk镜像和Tomcat镜像都没对时区进行定制化配置,默认为UTC时间(比北京时间早八小时)。如果应用内部也没有进行时区配置,那么应用获取到的系统时间也将会是UTC时间。

2.在某些机器(或虚拟机)上,jdk的随机数生成器初始化用时过长,导致Tomcat启动用时过长。我用过的阿里云ECS就是这种情况。

这些问题将会在之后我们自己构建的Tomcat镜像中解决。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Spring Boot修改内置Tomcat默认端口号的示例

    Spring Boot 内置Tomcat默认端口号为8080,在开发多个应用调试时很不方便,本文介绍了修改 Spring Boot内置Tomcat端口号的方法. 一.EmbeddedServletContainerCustomizer接口 EmbeddedServletContainerCustomizer接口提供了customize方法用来自定义servlet容器的一些属性 如图编写实现类在customize方法中可设置容器端口号为8088 . 二.TomcatEmbeddedServletC

  • Linux系统下Tomcat8启动速度很慢的解决方法

    前言 最近在工作中遇到一个问题,在Linux下Tomcat 8启动很慢,且日志上无任何错误,在日志中查看到如下信息: Log4j:[2017-08-2715:47:11] INFO ReadProperty:172 - Loading properties file from class path resource [resources/jdbc.properties] Log4j:[2017-08-27 15:47:11] INFO ReadProperty:172 - Loading pro

  • 解决应用启动失败但tomcat不报错的方法

    发现问题 最近遇到了一个奇葩的问题就是应用启动失败,但是tomcat没有报任何的日志出来,log4j.properties日志级别写的是debug级别也没用. 解决过程 遇到这种情况,可以试着在web应用的classpath目录添加一个logging.properties文件来试一下 handlers = org.apache.juli.FileHandler, java.util.logging.ConsoleHandler ##################################

  • 详解springboot-修改内置tomcat版本

    详解springboot-修改内置tomcat版本 1.解析Spring Boot父级依赖 <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.6.RELEASE</version> </parent> 这块配置就是Spring

  • 详解tomcat热部署和热加载的方法

    详解tomcat热部署和热加载的方法 我在项目开发过程中,经常要改动Java/JSP 文件,但是又不想从新启动服务器(服务器从新启动花时间),想直接获得(debug)结果.有两种方式热部署 和热加载: 1.热加载:在server.xml -> context 属性中 设置 reloadable="true" <Context docBase="xxx" path="/xxx" reloadable="true"/&

  • Tomcat开启JMX服务方法介绍

    Tomcat开启JMX服务很简单,只要在catalina.sh里添加: 1.CATALINA_OPTS="-Dcom.sun.management.jmxremote.port=8999 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=true 2." 端口号8999可以修改为未占用的端口即可. 修改JAVA_HOME/jre/lib/management目录下面的

  • java web开发中获取tomcat上properties文件内容的方法

    在java web开发的时候经常会用到读取读取或存放文件,这个文件的默认路径在哪里呢?写死在程序里面显然是可以的,但这样子不利于位于,假如有一天项目从window移植到linux,或者保存文件的路径变了,就需要去源代码中查找,进行替换,这样子不仅效率低,而且程序的耦合度也会过高,这里我用了一个properties文件用于存放文件的保存路径,需要保存或者读取都来自己properties所保存的路径. 1.我存放的propeities文件路径 因为linux和window上面的分盘是不一样的,所以我

  • Dockerfile制作官方Tomcat镜像及镜像使用详解

    这两天学习了Dockerfile感觉这个地方知识点挺多的,而且很重要,所以,今天添加一点小笔记. 官方Tomcat镜像 地址:https://hub.docker.com/_/tomcat/ 镜像的Full Description中,我们可以得到许多信息,这里简单介绍几个: 1.Supported tags and respective Dockerfile links 支持的标签,以及对应的Dockerfile链接.一个Dockerfile可以对应多个标签,我们将以8.5.16-jre8版本的

  • DockerHub 镜像仓库的使用详解

    之前我们使用的镜像都是从 DockerHub 公共仓库拉取的,我们也学习了如何制作自己的镜像,但是通过 tar 包的方式实现镜像的备份恢复迁移对于团队协作开发并不是特别友好,我们也可以将镜像推送至 DockerHub 仓库方便使用. 温馨提示:如果构建的镜像内携带了项目数据,建议还是使用私有仓库比较好. 注册账号 官网:https://hub.docker.com/ 登录账号 通过 docker login 命令输入账号密码登录 DockerHub. 推送镜像至仓库 为了方便测试,我们将 hel

  • windows环境下修改pip镜像源的方法详解

    这篇文章主要介绍了windows环境下修改pip镜像源的方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 (1):在windows文件管理器中,输入 %APPDATA% (2):会定位到一个新的目录下,在该目录下新建pip文件夹,然后到pip文件夹里面去新建个pip.ini文件 (3):在新建的pip.ini文件中输入以下内容,搞定文件路径:"C:\Users\Administrator\AppData\Roaming\pip\pip.i

  • Tomcat 7-dbcp配置数据库连接池详解

    Tomcat 7-dbcp配置数据库连接池详解 原理 关于连接池,大家都晓得用来限定对数据库的连接.基本的原理是预先在缓冲池中放入一定的空闲连接,当程序需要和数据库来交互时,不是直接新建数据库连接而是在连接池中直接取,使用完成后再放回到连接池中.为什么要这样牺牲一个缓冲来存放这些原本就会使用的连接呢?在上面讲了一个好处就是可以限定连接数,这样不会造成N多的数据库连接最后宕机:额外有了这样一个连接池,也可以来监听这些连接和便于管理. 配置 1.拷贝相关的jar 要知道连接池不是用来直接操作数据库的

  • Spring Boot启动过程(五)之Springboot内嵌Tomcat对象的start教程详解

    标题和Spring Boot启动过程(四)之Spring Boot内嵌Tomcat启动很像,所以特别强调一下,这个是Tomcat对象的. 从TomcatEmbeddedServletContainer的this.tomcat.start()开始,主要是利用LifecycleBase对这一套容器(engine,host,context及wrapper)进行启动并发布诸如configure_start.before_init.after_start的lifecycleEvent事件给相应的监听器(如

  • kotlin 官方学习教程之基础语法详解

    kotlin 官方学习教程之基础语法详解 Google 在今天的举行了 I/O 大会,大会主要主要展示内有容 Android O(Android 8.0)系统.Google Assistant 语音助手.Google 智能音箱.人工智能.机器学习.虚拟现实等.作为一个 Android 开发者,我关心的当然是 Android O(Android 8.0)系统了,那么关于 Android O 系统的一个重要消息是全面支持 Kotlin 编程语言,使得 Kotlin 成为了 Android 开发的官方

  • 在idea中将创建的java web项目部署到Tomcat中的过程图文详解

    在idea中将创建的java web项目部署到Tomcat中 采用的工具idea 2018.3.6 Tomcat7 1.先创建第一个新项目secondweb(注意勾选JavaEE下的web Application(4.0),窗口下的version对应为4.0,并且保证create web.xml已经被勾选) 2.在创建好的web项目的web/WEB-INF目录下创建两个文件夹:classes和lib.classes用来存放编译后输出的class文件,lib用来存放第三方jar包(下图显示的是创建

  • 使用Tomcat Native提升Tomcat IO效率的方法详解

    简介 IO有很多种,从最开始的Block IO,到nonblocking IO,再到IO多路复用和异步IO,一步一步的将IO的性能提升做到极致. 今天我们要介绍一下怎么使用Tomcat Native来提升Tomcat IO的效率. Tomcat的连接方式 Tomcat中使用连接器来处理与外部客户端的通信.Connecter主要用来接受外部客户端的请求,并转交给处理引擎处理. 在Tomcat中有两种Connector.一种是 HTTP connector, 一种是AJP connector. HT

  • Tomcat核心组件及应用架构详解

    Web 容器是什么? 让我们先来简单回顾一下 Web 技术的发展历史,可以帮助你理解 Web 容器的由来. 早期的 Web 应用主要用于浏览新闻等静态页面,HTTP 服务器(比如 Apache.Nginx)向浏览器返回静态 HTML,浏览器负责解析 HTML,将结果呈现给用户. 随着互联网的发展,我们已经不满足于仅仅浏览静态页面,还希望通过一些交互操作,来获取动态结果,因此也就需要一些扩展机制能够让 HTTP 服务器调用服务端程序. 于是 Sun 公司推出了 Servlet 技术.你可以把 Se

  • Tomcat启动核心流程示例详解

    目录 一.Tomcat的启动核心流程 1.启动的入口 2.init方法 3.load方法 4.start方法 5.核心流程的总结 一.Tomcat的启动核心流程 前面给大家介绍了Tomcat中的生命周期的设计,掌握了这块对于我们分析Tomcat的核心流程是非常有帮助的,也就是我们需要创建相关的核心组件,比如Server,Service肯定都绕不开生命周期的方法. 1.启动的入口 你可以通过脚本来启动Tomcat服务(startup.bat),但如果你看过脚本的命令,你会发现最终调用的还是Boot

随机推荐