## 官方Tomcat鏡像 地址: 鏡像的Full Description中,我們可以得到許多信息,這里簡單介紹幾個: 1. Supported tags and respective Dockerfile links 支持的標簽,以及對應(yīng)的Dockerfile鏈接。一個Dockerfile可以對應(yīng)多個標簽,我們將以8.5.16-jre8版本的Dockerfile進行分析。 2. How to use this image 如何使用本鏡像,包括了以不同方式運行容器的命令,以及一些主要環(huán)境變量。這里講的不夠詳細,我們會詳細講解。 ## 準備知識:APR、Tomcat Native、Tomcat的APR模式 APR是Apache Portable Runtime的簡寫,其實就是一組用C語言編寫的動態(tài)鏈接庫,提供統(tǒng)一的API接口,用于訪問操作系統(tǒng)底層。詳見:。 Tomcat Native的主要作用是為tomcat提供訪問本地資源的功能。即利用APR庫,訪問網(wǎng)絡(luò)、生成隨機數(shù)等。Tomcat Native依賴于APR、OpenSSL、JDK。詳見:。 在配置好Tomcat Native后,可以在tomcat配置文件中開啟APR模式。開啟之后,Tomcat就會直接調(diào)用APR庫訪問網(wǎng)絡(luò),不用再通過jvm中轉(zhuǎn)。 因為APR和Tomcat Native是和具體的操作系統(tǒng)緊密關(guān)聯(lián)的,并不像java應(yīng)用那樣編譯好后就可以跨平臺使用。所以tomcat默認不安裝這些功能,而是根據(jù)需要,以及具體操作系統(tǒng),手工編譯源碼安裝。從一些資料上來看,開啟tomcat的APR模式后,對tomcat的性能并不一定會有很大的提升(在某些情況下甚至可能下降)。是否開啟APR模式要看具體的情況。個人認為,一般情況下,真到了要挖掘Tomcat性能的時候,使用tomcat集群將會是一種更好的解決方案,這對系統(tǒng)的性能、穩(wěn)定性、可靠性都有提升。 ## 分析Dockerfile(tomcat:8.5.16-jre8) 地址: 注意,這里以master分支的Dockerfile鏈接為例,和DockerHub上的Dockerfile鏈接可能會不一致,不過不影響我們接下來的分析。以下就是這個Dockerfile的內(nèi)容,我加了注釋加以說明: ``` #本鏡像的基礎(chǔ)鏡像。有興趣的話,可以自行在DockerHub上搜索openjdk,分析官方的openjdk鏡像的Dockerfile文件。這里為什么不用oracle提供的jdk(jre)?簡單地講,版權(quán)問題。 FROM openjdk:8-jre #聲明CATALINA_HOME環(huán)境變量,這個變量大家都了解。 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命令的當前工作路徑。 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)的動態(tài)鏈接庫時,會去查找TOMCAT_NATIVE_LIBDIR環(huán)境變量指定的路徑。 ENV LD_LIBRARY_PATH ${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$TOMCAT_NATIVE_LIBDIR #檢查、更新OpenSSL,這塊的細節(jié)我沒深究。 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,用于驗證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相關(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" \ #進行簽名驗證 && 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 #驗證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 #容器啟動時執(zhí)行的命令。 CMD ["catalina.sh", "run"] ``` 此Dockerfile的主要功能可歸納為: 1. 以openjdk鏡像為基礎(chǔ)鏡像進行構(gòu)建。 2. 安裝Tomcat Native,及其依賴庫(比如APR、OpenSSL等)。驗證是否正確安裝。 2. 下載Tomcat,檢查簽名,解壓、清除無用文件等。 3. 暴露8080端口,配置入口命令。 總的來說,此Dockerfile的功能還是比較清晰的,如果要自己構(gòu)建自己的Tomcat鏡像,可以參考本Dockerfile。另外,Tomcat的Dockerfile應(yīng)該是自動生成而非手工編寫,因為第一,Tomcat的有很多版本的Dockerfile,手工維護工作量大;第二,存在一些我認為不是很很合理的地方(比如從key server上獲取很多key)。所以大家在分析一些官方Dockerfile時,如果遇到一些感覺不是很合理的地方也別太糾結(jié)。 ## 如何使用官方鏡像 ``` $ docker run -d --name tomcat-test -p 8888:8080 tomcat:8.5.16-jre8 ``` 以上指令將使用本鏡像啟動一個容器,你可以通過http://本機ip:8888訪問到容器中的Tomcat。這種方式并沒有部署應(yīng)用,所以其實也沒什么實際意義。 ``` $ 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的根應(yīng)用將會是myWebApp(通過http://本機ip:8888訪問),并且tomcat的日志將會輸出到/home/myWebAppLogs路徑下。 此后,如果容器被刪除,應(yīng)用和應(yīng)用的日志也不會隨容器一起刪除。更新應(yīng)用時,只需要更新/home/myWebApp路徑,再重啟容器即可。 如果不想把應(yīng)用掛載到根目錄下,可以更改volume配置,比如:-v /home/myWebApp:/usr/local/tomcat/webapps/myWebApp,再通過http://本機ip:8888/myWebApp訪問。 **注意**:如果想把myWebApp內(nèi)部的日志也輸出到/home/myWebAppLogs路徑下,請配置myWebApp的日志文件的輸出路徑為Tomcat日志路徑(相對路徑),例如:logs/myLog.log。這樣,myWebApp的日志文件將會輸出至/usr/local/tomcat/logs下(因為掛載了volume,其實是輸出到/home/myWebAppLogs路徑下)。 從規(guī)范的角度講,其實這種應(yīng)用部署方式并不值得推薦,因為部署還是出現(xiàn)了環(huán)境相關(guān)性。也就是說,必須先把應(yīng)用目錄、日志目錄指定好,才能進行部署。而且如果要一臺機上要部署兩個相同的應(yīng)用進行負載均衡也比較麻煩(要建兩套應(yīng)用和日志目錄,并且修改容器啟動命令),難以實現(xiàn)自動化部署。但話又說回來,我相信這種部署方式還是會受到大部分人歡迎的。目前我們公司在測試環(huán)境中也普遍使用這種模式,以便一臺測試服務(wù)器部署多個應(yīng)用(Tomcat),彼此之間完全沒有關(guān)聯(lián)和影響。 如果要做到完全環(huán)境無關(guān)性部署,可以考慮自己在官方Tomcat鏡像的基礎(chǔ)上,構(gòu)建出一個新的鏡像。在這個新鏡像的Dockerfile中直接下載并部署myWebApp,并使用某些工具或框架,將Tomcat和myWebApp產(chǎn)生的日志,上傳匯總到一個統(tǒng)一的日志服務(wù)中。這樣,如果要再部署一個相同的應(yīng)用,只要給我一臺裝有Docker環(huán)境的機器,我執(zhí)行一條指令即可(同一Docker環(huán)境下注意端口沖突)。這種方式有利于自動化部署,在服務(wù)器數(shù)量較多的情況下比較合適。當然,這種方式也有比較麻煩的地方,就是每發(fā)布以一個應(yīng)用版本,都要重新構(gòu)建一個新的鏡像。 關(guān)于自動化部署,還可以參考 `Docker Compose` 和 `Kubernetes` ,這里不做深入(主要是本人對這塊的了解和應(yīng)用也不夠多)。 ## 官方鏡像的不足 在本鏡像的實際使用過程中,還是遇到了一些問題: 1. 為了照顧到全球的鏡像使用者,官方的openjdk鏡像和Tomcat鏡像都沒對時區(qū)進行定制化配置,默認為UTC時間(比北京時間早八小時)。如果應(yīng)用內(nèi)部也沒有進行時區(qū)配置,那么應(yīng)用獲取到的系統(tǒng)時間也將會是UTC時間。 2. 在某些機器(或虛擬機)上,jdk的隨機數(shù)生成器初始化用時過長,導(dǎo)致Tomcat啟動用時過長。我用過的阿里云ECS就是這種情況。 這些問題將會在之后我們自己構(gòu)建的Tomcat鏡像中解決。http://www.cnblogs.com/dfengwei/p/7144937.html