You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

解答

你的思路方向对,但有两个关键问题需要修正:

  1. WAR包解压时机:Tomcat启动时才会自动解压WAR包到webapps/ROOT目录,所以当前脚本执行sed时,$DB_CONFIG_FILE这个文件还不存在,自然无法修改。但如果先启动catalina.sh run,这个命令会阻塞脚本执行,后面的sed根本不会运行。

  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 13:35:15