Tomcat与Docker:如何在catalina.sh启动后执行shell脚本?
问题描述
背景
我尝试运行一个基于Tomcat和Docker的网站,需要修改database.properties文件中的一行内容,以连接到MySQL容器。
已完成操作
docker-compose.yaml配置
version: '3.8' services: tomcat-web: build: context: . dockerfile: ./Dockerfile.dev ports: - 8800:8080
Dockerfile.dev配置
FROM tomcat:8.0-alpine WORKDIR /usr/local/tomcat # 复制shell脚本并设置可执行权限 COPY --chmod=0755 startup.sh /usr/local/tomcat/bin/startup.sh # 清理/usr/local/tomcat/webapps/目录,让Tomcat可以解压web.war RUN rm -rf /usr/local/tomcat/webapps/* COPY target/web.war /usr/local/tomcat/webapps/ROOT.war EXPOSE 8080 CMD ["sh", "/usr/local/tomcat/bin/startup.sh"]
删除/usr/local/tomcat/webapps/*下的所有内容是参考Stack Overflow的建议。
startup.sh脚本
# 修改database.properties中的端口(从3306改为3311) DB_CONFIG_FILE=/usr/local/tomcat/webapps/ROOT/WEB-INF/classes/database.properties MYSQL_CONTAINER_PORT=3311 sed -i 's~^database.url=jdbc:mysql://127.0.0.1/database_name.*database.url=jdbc:mysql://127.0.0.1:3311/database_name~' $DB_CONFIG_FILE sh /usr/local/tomcat/bin/catalina.sh run
原database.properties内容
database.url=jdbc:mysql://127.0.0.1/database_name
问题
网站的Docker容器成功启动,但database.properties文件未被修改。
预期与疑问
期望修改后的database.properties内容如下:
database.url=jdbc:mysql://127.0.0.1:3311/database_name
请问是否需要先执行catalina.sh让其展开ROOT.WAR,再执行sed命令?比如这样:
sh /usr/local/tomcat/bin/catalina.sh run # 修改database.properties中的端口(从3306改为3311) DB_CONFIG_FILE=/usr/local/tomcat/webapps/ROOT/WEB-INF/classes/database.properties MYSQL_CONTAINER_PORT=3311 sed -i 's~^database.url=jdbc:mysql://127.0.0.1/database_name.*database.url=jdbc:mysql://127.0.0.1:3311/database_name~' $DB_CONFIG_FILE
解答
你的思路方向对,但有两个关键问题需要修正:
WAR包解压时机:Tomcat启动时才会自动解压WAR包到
webapps/ROOT目录,所以当前脚本执行sed时,$DB_CONFIG_FILE这个文件还不存在,自然无法修改。但如果先启动catalina.sh run,这个命令会阻塞脚本执行,后面的sed根本不会运行。sed命令语法错误:你写的
sed替换格式有误,正确格式应该是s/原字符串/替换字符串/,你现在把原字符串和替换字符串连在一起,没有用分隔符分开。正确写法如下:
sed -i 's~^database.url=jdbc:mysql://127.0.0.1/database_name~database.url=jdbc:mysql://127.0.0.1:3311/database_name~' $DB_CONFIG_FILE
正确的startup.sh写法
需要先让Tomcat完成WAR包解压,再修改配置,最后启动Tomcat:
# 先启动Tomcat后台进程,等待WAR包解压 sh /usr/local/tomcat/bin/catalina.sh start # 等待几秒确保WAR包完全解压(时间可根据实际情况调整) sleep 5 # 修改database.properties中的端口 DB_CONFIG_FILE=/usr/local/tomcat/webapps/ROOT/WEB-INF/classes/database.properties MYSQL_CONTAINER_PORT=3311 sed -i 's~^database.url=jdbc:mysql://127.0.0.1/database_name~database.url=jdbc:mysql://127.0.0.1:'"$MYSQL_CONTAINER_PORT"'/database_name~' $DB_CONFIG_FILE # 停止后台的Tomcat进程,再以前台方式启动(保持容器运行) sh /usr/local/tomcat/bin/catalina.sh stop sh /usr/local/tomcat/bin/catalina.sh run
更优方案:构建镜像时修改WAR包内配置
其实可以在构建镜像时直接修改WAR包里的database.properties,省去启动后修改的步骤,更高效:
FROM tomcat:8.0-alpine WORKDIR /usr/local/tomcat # 复制WAR包到临时目录 COPY target/web.war /tmp/web.war # 解压WAR包,修改配置,重新打包 RUN mkdir -p /tmp/web && \ unzip /tmp/web.war -d /tmp/web && \ sed -i 's~^database.url=jdbc:mysql://127.0.0.1/database_name~database.url=jdbc:mysql://127.0.0.1:3311/database_name~' /tmp/web/WEB-INF/classes/database.properties && \ cd /tmp/web && zip -r /usr/local/tomcat/webapps/ROOT.war . && \ rm -rf /tmp/web /tmp/web.war # 清理webapps目录 RUN rm -rf /usr/local/tomcat/webapps/* EXPOSE 8080 CMD ["sh", "/usr/local/tomcat/bin/catalina.sh run"]
这样构建镜像时就完成了配置修改,启动容器后直接可用,避免了启动后修改的繁琐操作。
内容的提问来源于stack exchange,提问作者marc
相关产品推荐
相关产品推荐

