Dockerfile制作官方Tomcat鏡像及鏡像使用詳解
這兩天學(xué)習(xí)了Dockerfile感覺(jué)這個(gè)地方知識(shí)點(diǎn)挺多的,而且很重要,所以,今天添加一點(diǎn)小筆記。
官方Tomcat鏡像
地址:https://hub.docker.com/_/tomcat/
鏡像的Full Description中,我們可以得到許多信息,這里簡(jiǎn)單介紹幾個(gè):
1.Supported tags and respective Dockerfile links
支持的標(biāo)簽,以及對(duì)應(yīng)的Dockerfile鏈接。一個(gè)Dockerfile可以對(duì)應(yīng)多個(gè)標(biāo)簽,我們將以8.5.16-jre8版本的Dockerfile進(jìn)行分析。
2.How to use this image
如何使用本鏡像,包括了以不同方式運(yùn)行容器的命令,以及一些主要環(huán)境變量。這里講的不夠詳細(xì),我們會(huì)詳細(xì)講解。
準(zhǔn)備知識(shí):APR、Tomcat Native、Tomcat的APR模式
APR是Apache Portable Runtime的簡(jiǎn)寫,其實(shí)就是一組用C語(yǔ)言編寫的動(dòng)態(tài)鏈接庫(kù),提供統(tǒng)一的API接口,用于訪問(wèn)操作系統(tǒng)底層。詳見(jiàn):http://apr.apache.org/。
Tomcat Native的主要作用是為tomcat提供訪問(wèn)本地資源的功能。即利用APR庫(kù),訪問(wèn)網(wǎng)絡(luò)、生成隨機(jī)數(shù)等。Tomcat Native依賴于APR、OpenSSL、JDK。詳見(jiàn):http://tomcat.apache.org/native-doc/。
在配置好Tomcat Native后,可以在tomcat配置文件中開(kāi)啟APR模式。開(kāi)啟之后,Tomcat就會(huì)直接調(diào)用APR庫(kù)訪問(wèn)網(wǎng)絡(luò),不用再通過(guò)jvm中轉(zhuǎn)。
因?yàn)锳PR和Tomcat Native是和具體的操作系統(tǒng)緊密關(guān)聯(lián)的,并不像java應(yīng)用那樣編譯好后就可以跨平臺(tái)使用。所以tomcat默認(rèn)不安裝這些功能,而是根據(jù)需要,以及具體操作系統(tǒng),手工編譯源碼安裝。從一些資料上來(lái)看,開(kāi)啟tomcat的APR模式后,對(duì)tomcat的性能并不一定會(huì)有很大的提升(在某些情況下甚至可能下降)。是否開(kāi)啟APR模式要看具體的情況。個(gè)人認(rèn)為,一般情況下,真到了要挖掘Tomcat性能的時(shí)候,使用tomcat集群將會(huì)是一種更好的解決方案,這對(duì)系統(tǒng)的性能、穩(wěn)定性、可靠性都有提升。
分析Dockerfile(tomcat:8.5.16-jre8)
地址:https://github.com/docker-library/tomcat/blob/master/8.5/jre8/Dockerfile
注意,這里以master分支的Dockerfile鏈接為例,和DockerHub上的Dockerfile鏈接可能會(huì)不一致,不過(guò)不影響我們接下來(lái)的分析。以下就是這個(gè)Dockerfile的內(nèi)容,我加了注釋加以說(shuō)明:
#本鏡像的基礎(chǔ)鏡像。有興趣的話,可以自行在DockerHub上搜索openjdk,分析官方的openjdk鏡像的Dockerfile文件。這里為什么不用oracle提供的jdk(jre)?簡(jiǎn)單地講,版權(quán)問(wèn)題。
FROM openjdk:8-jre
#聲明CATALINA_HOME環(huán)境變量,這個(gè)變量大家都了解。
ENV CATALINA_HOME /usr/local/tomcat
#將Tomcat下的bin路徑加入到PATH環(huán)境變量中。
ENV PATH $CATALINA_HOME/bin:$PATH
#創(chuàng)建tomcat路徑。
RUN mkdir -p "$CATALINA_HOME"
#指定RUN、CMD、ENTRYPOINT命令的當(dāng)前工作路徑。
WORKDIR $CATALINA_HOME
#Tomcat Native路徑配置。
ENV TOMCAT_NATIVE_LIBDIR $CATALINA_HOME/native-jni-lib
#將TOMCAT_NATIVE_LIBDIR加入到LD_LIBRARY_PATH環(huán)境變量中,這樣Tomcat在查找Tomcat Native相關(guān)的動(dòng)態(tài)鏈接庫(kù)時(shí),會(huì)去查找TOMCAT_NATIVE_LIBDIR環(huán)境變量指定的路徑。
ENV LD_LIBRARY_PATH ${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$TOMCAT_NATIVE_LIBDIR
#檢查、更新OpenSSL,這塊的細(xì)節(jié)我沒(méi)深究。
ENV OPENSSL_VERSION 1.1.0f-3
RUN { \
echo 'deb http://deb.debian.org/debian stretch main'; \
} > /etc/apt/sources.list.d/stretch.list \
&& { \
echo 'Package: *'; \
echo 'Pin: release n=stretch'; \
echo 'Pin-Priority: -10'; \
echo; \
echo 'Package: openssl libssl*'; \
echo "Pin: version $OPENSSL_VERSION"; \
echo 'Pin-Priority: 990'; \
} > /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服務(wù)器導(dǎo)入key,用于驗(yàn)證tomcat壓縮文件的簽名,這塊也沒(méi)深究。
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相關(guān)文件的版本。
ENV TOMCAT_MAJOR 8
ENV TOMCAT_VERSION 8.5.16
#Tomcat相關(guān)文件下載地址。
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
#執(zhí)行命令
RUN set -x \
\
#下載Tomcat壓縮文件
&& wget -O tomcat.tar.gz "$TOMCAT_TGZ_URL" \
&& wget -O tomcat.tar.gz.asc "$TOMCAT_ASC_URL" \
#進(jìn)行簽名驗(yàn)證
&& gpg --batch --verify tomcat.tar.gz.asc tomcat.tar.gz \
#解壓Tomcat
&& tar -xvf tomcat.tar.gz --strip-components=1 \
# 刪除供Windows系統(tǒng)使用的.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
#驗(yàn)證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
#容器啟動(dòng)時(shí)執(zhí)行的命令。
CMD ["catalina.sh", "run"]
此Dockerfile的主要功能可歸納為:
1.以openjdk鏡像為基礎(chǔ)鏡像進(jìn)行構(gòu)建。
2.安裝Tomcat Native,及其依賴庫(kù)(比如APR、OpenSSL等)。驗(yàn)證是否正確安裝。
3.下載Tomcat,檢查簽名,解壓、清除無(wú)用文件等。
4.暴露8080端口,配置入口命令。
總的來(lái)說(shuō),此Dockerfile的功能還是比較清晰的,如果要自己構(gòu)建自己的Tomcat鏡像,可以參考本Dockerfile。另外,Tomcat的Dockerfile應(yīng)該是自動(dòng)生成而非手工編寫,因?yàn)榈谝唬琓omcat的有很多版本的Dockerfile,手工維護(hù)工作量大;第二,存在一些我認(rèn)為不是很很合理的地方(比如從key server上獲取很多key)。所以大家在分析一些官方Dockerfile時(shí),如果遇到一些感覺(jué)不是很合理的地方也別太糾結(jié)。
如何使用官方鏡像
$ docker run -d --name tomcat-test -p 8888:8080 tomcat:8.5.16-jre8
以上指令將使用本鏡像啟動(dòng)一個(gè)容器,你可以通過(guò)http://本機(jī)ip:8888訪問(wèn)到容器中的Tomcat。這種方式并沒(méi)有部署應(yīng)用,所以其實(shí)也沒(méi)什么實(shí)際意義。
$ 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
以上指令增加了兩個(gè)volume,將/home/myWebApp掛載到容器中的/usr/local/tomcat/webapps/ROOT,將/home/myWebAppLogs掛載到容器中的/usr/local/tomcat/logs路徑。容器啟動(dòng)后,tomcat的根應(yīng)用將會(huì)是myWebApp(通過(guò)http://本機(jī)ip:8888訪問(wèn)),并且tomcat的日志將會(huì)輸出到/home/myWebAppLogs路徑下。
此后,如果容器被刪除,應(yīng)用和應(yīng)用的日志也不會(huì)隨容器一起刪除。更新應(yīng)用時(shí),只需要更新/home/myWebApp路徑,再重啟容器即可。
如果不想把應(yīng)用掛載到根目錄下,可以更改volume配置,比如:-v /home/myWebApp:/usr/local/tomcat/webapps/myWebApp,再通過(guò)http://本機(jī)ip:8888/myWebApp訪問(wèn)。
注意:如果想把myWebApp內(nèi)部的日志也輸出到/home/myWebAppLogs路徑下,請(qǐng)配置myWebApp的日志文件的輸出路徑為Tomcat日志路徑(相對(duì)路徑),例如:logs/myLog.log。這樣,myWebApp的日志文件將會(huì)輸出至/usr/local/tomcat/logs下(因?yàn)閽燧d了volume,其實(shí)是輸出到/home/myWebAppLogs路徑下)。
從規(guī)范的角度講,其實(shí)這種應(yīng)用部署方式并不值得推薦,因?yàn)椴渴疬€是出現(xiàn)了環(huán)境相關(guān)性。也就是說(shuō),必須先把應(yīng)用目錄、日志目錄指定好,才能進(jìn)行部署。而且如果要一臺(tái)機(jī)上要部署兩個(gè)相同的應(yīng)用進(jìn)行負(fù)載均衡也比較麻煩(要建兩套應(yīng)用和日志目錄,并且修改容器啟動(dòng)命令),難以實(shí)現(xiàn)自動(dòng)化部署。但話又說(shuō)回來(lái),我相信這種部署方式還是會(huì)受到大部分人歡迎的。目前我們公司在測(cè)試環(huán)境中也普遍使用這種模式,以便一臺(tái)測(cè)試服務(wù)器部署多個(gè)應(yīng)用(Tomcat),彼此之間完全沒(méi)有關(guān)聯(lián)和影響。
如果要做到完全環(huán)境無(wú)關(guān)性部署,可以考慮自己在官方Tomcat鏡像的基礎(chǔ)上,構(gòu)建出一個(gè)新的鏡像。在這個(gè)新鏡像的Dockerfile中直接下載并部署myWebApp,并使用某些工具或框架,將Tomcat和myWebApp產(chǎn)生的日志,上傳匯總到一個(gè)統(tǒng)一的日志服務(wù)中。這樣,如果要再部署一個(gè)相同的應(yīng)用,只要給我一臺(tái)裝有Docker環(huán)境的機(jī)器,我執(zhí)行一條指令即可(同一Docker環(huán)境下注意端口沖突)。這種方式有利于自動(dòng)化部署,在服務(wù)器數(shù)量較多的情況下比較合適。當(dāng)然,這種方式也有比較麻煩的地方,就是每發(fā)布以一個(gè)應(yīng)用版本,都要重新構(gòu)建一個(gè)新的鏡像。
關(guān)于自動(dòng)化部署,還可以參考Docker Compose和Kubernetes,這里不做深入(主要是本人對(duì)這塊的了解和應(yīng)用也不夠多)。
官方鏡像的不足
在本鏡像的實(shí)際使用過(guò)程中,還是遇到了一些問(wèn)題:
1.為了照顧到全球的鏡像使用者,官方的openjdk鏡像和Tomcat鏡像都沒(méi)對(duì)時(shí)區(qū)進(jìn)行定制化配置,默認(rèn)為UTC時(shí)間(比北京時(shí)間早八小時(shí))。如果應(yīng)用內(nèi)部也沒(méi)有進(jìn)行時(shí)區(qū)配置,那么應(yīng)用獲取到的系統(tǒng)時(shí)間也將會(huì)是UTC時(shí)間。
2.在某些機(jī)器(或虛擬機(jī))上,jdk的隨機(jī)數(shù)生成器初始化用時(shí)過(guò)長(zhǎng),導(dǎo)致Tomcat啟動(dòng)用時(shí)過(guò)長(zhǎng)。我用過(guò)的阿里云ECS就是這種情況。
這些問(wèn)題將會(huì)在之后我們自己構(gòu)建的Tomcat鏡像中解決。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
使用 Docker 部署 Apache Spark 集群的過(guò)程
本文介紹了如何使用Docker和DockerCompose快速部署一個(gè)包含一個(gè)Master節(jié)點(diǎn)和兩個(gè)Worker節(jié)點(diǎn)的Spark集群,通過(guò)創(chuàng)建docker-compose.yml文件并執(zhí)行相關(guān)命令,可以實(shí)現(xiàn)集群的構(gòu)建和啟動(dòng),感興趣的朋友一起看看吧2025-02-02
docker搭建minio服務(wù)器,解決內(nèi)網(wǎng)穿透后外網(wǎng)無(wú)法訪問(wèn)
這篇文章主要介紹了docker搭建minio服務(wù)器,解決內(nèi)網(wǎng)穿透后外網(wǎng)無(wú)法訪問(wèn)的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09
Docker部署MongoDb的詳細(xì)過(guò)程記錄
這篇文章主要介紹了如何使用Docker?Compose啟動(dòng)MongoDB副本集,包括配置文件編寫、容器啟動(dòng)命令、副本集初始化、角色和用戶創(chuàng)建等步驟,需要的朋友可以參考下2024-12-12
dockerfile中ENTRYPOINT與CMD的結(jié)合使用及區(qū)別
這篇文章主要介紹了dockerfile中ENTRYPOINT與CMD的結(jié)合使用,大家都知道CMD 與 ENTRYPOINT都是用于指定啟動(dòng)容器執(zhí)行的命令,那么他們倆有什么區(qū)別呢,本文給大家詳細(xì)介紹,需要的朋友可以參考下2021-08-08
Docker Compose 與 Harbor 私有倉(cāng)庫(kù)詳解
本文將探討Docker Compose多容器編排工具與Harbor企業(yè)級(jí)私有倉(cāng)庫(kù)的核心技術(shù),幫助讀者掌握從容器管理到鏡像安全存儲(chǔ)的完整解決方案,感興趣的朋友一起看看吧2025-06-06
詳解在Docker容器中運(yùn)行Spring Boot應(yīng)用
本文將以一個(gè)最簡(jiǎn)單的Spring Boot開(kāi)發(fā)的Web應(yīng)用為例,講解如何將其容器化運(yùn)行。本文的重點(diǎn)是構(gòu)建Docker鏡像、運(yùn)行Docker容器。2017-06-06
在OpenWrt設(shè)備上搭建Docker環(huán)境的完整方案
OpenWrt 作為一個(gè)高度可定制的嵌入式 Linux 發(fā)行版,其模塊化設(shè)計(jì)為 Docker 容器化部署提供了可能性,將 Docker 引入 OpenWrt 環(huán)境,能夠帶來(lái)許多優(yōu)勢(shì),所以本文給大家分享了在 OpenWrt 設(shè)備上搭建 Docker 環(huán)境的完整方案,需要的朋友可以參考下2025-04-04
關(guān)于docker無(wú)法正常下載鏡像的問(wèn)題小結(jié)
之前還可以正常下載鏡像,但是一段時(shí)間之后就無(wú)法下載了,猜測(cè)可能是政治原因,無(wú)法連接到國(guó)外服務(wù)器,所以我設(shè)置了阿里云的鏡像加速器,需要的朋友可以參考下2024-06-06

