Docker部署旧版本系统MySQL5.7+乱码问题解决方案

问题描述

公司需要部署一个周报管理系统,该系统目前在Windows环境下运行良好。现在,计划将其迁移到服务器上进行部署,故将这个活交给我部署,但由于系统较为陈旧,依然使用的是JSP技术栈。同时,还需要拉取tomcat:7-jre8的Docker镜像。更棘手的问题是,系统使用的是MySQL 5.7+版本,而不是当前主流的MySQL 8+,这导致在适配新的UTF-8编码格式时遇到了一些挑战。在使用Docker部署该周报管理系统后,虽然容器成功启动,但访问应用页面时却发现中文内容出现了乱码:

复制代码
æ ´å°±å>>ºç<< 工程å'Œå...±å>>ºé¡¹ç›®ç®¡ç�†ç³>>ç>>Ÿ

同时,应用能够正常访问,但部分功能可能受到影响。

问题分析

通过查看应用日志和配置,我们逐步排查了可能导致乱码的原因:

  1. 应用编码配置:应用的JSP页面和web.xml已经配置了UTF-8编码
  2. Tomcat编码配置:默认Tomcat配置可能没有启用UTF-8编码支持
  3. MySQL字符集配置:数据库初始化和连接可能存在编码不一致问题
  4. 数据库连接参数:使用了不兼容的JDBC连接参数

解决方案

1. 检查应用编码配置

首先确认应用本身已经配置了UTF-8编码:

  • JSP页面 :所有JSP页面都包含<%@ page contentType="text/html;charset=UTF-8"%>
  • web.xml:配置了CharacterEncodingFilter,强制使用UTF-8编码
xml 复制代码
<filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
        <param-name>forceEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

2. 调整Tomcat编码设置

修改Dockerfile的文件,为Tomcat添加UTF-8编码支持:

dockerfile 复制代码
# 设置环境变量,添加UTF-8编码支持
ENV JAVA_OPTS="-Djava.security.egd=file:/dev/./urandom -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8"
# 配置Tomcat URI编码为UTF-8
RUN sed -i 's/<Connector port="8080" protocol="HTTP\/1.1"/<Connector port="8080" protocol="HTTP\/1.1" URIEncoding="UTF-8"/' /usr/local/tomcat/conf/server.xml

以下为我完整的Dockerfile的文件配置

dockerfile 复制代码
# 使用官方Tomcat 7镜像作为基础镜像
FROM tomcat:7-jre8

# 维护者信息
LABEL maintainer="周报管理系统"

# 移除Tomcat默认的ROOT应用
RUN rm -rf /usr/local/tomcat/webapps/ROOT

# 将打包好的WAR文件复制到Tomcat的webapps/weekly目录
COPY ./tomcat /usr/local/tomcat/webapps/weekly

# 暴露Tomcat端口
EXPOSE 8080

# 设置环境变量,添加UTF-8编码支持
ENV JAVA_OPTS="-Djava.security.egd=file:/dev/./urandom -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8"
# 配置Tomcat URI编码为UTF-8
RUN sed -i 's/<Connector port="8080" protocol="HTTP\/1.1"/<Connector port="8080" protocol="HTTP\/1.1" URIEncoding="UTF-8"/' /usr/local/tomcat/conf/server.xml
# 启动Tomcat
CMD ["catalina.sh", "run"]

3. 优化MySQL配置

在docker-compose.yml中添加完整的MySQL字符集配置:

yaml 复制代码
command: >
  --character-set-server=utf8mb4
  --collation-server=utf8mb4_unicode_ci
  --init-connect='SET NAMES utf8mb4'
  --skip-character-set-client-handshake
  --sql-mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

4. 修复数据库连接参数

检查并修复jeeplus.properties中的数据库连接参数。旧版本MySQL驱动不支持某些参数,导致连接失败:

错误配置

properties 复制代码
jdbc.url=jdbc:mysql://mysql:3306/weekly?useUnicode=true&characterEncoding=utf-8&useSSL=false&connectionCollation=utf8mb4_unicode_ci&serverTimezone=Asia/Shanghai

正确配置

properties 复制代码
jdbc.url=jdbc:mysql://mysql:3306/weekly?useUnicode=true&characterEncoding=utf-8&useSSL=false
正确配置的修改:
  1. 去掉了 connectionCollation=utf8mb4_unicode_ci:这个参数与字符集的选择有关,但它通常不需要在 JDBC URL 中显式指定,除非有特别的需求,通常 MySQL 默认就会使用 utf8mb4 编码。
  2. 去掉了 serverTimezone=Asia/Shanghai:这个参数用于设置时区,可能在某些情况下需要,但它并不是必须的,特别是如果 MySQL 服务器的时区配置正确的话。去掉这个参数有时能避免时区冲突问题,尤其是在使用容器或者跨时区部署时。

总结,正确配置 去除了多余的配置项,确保了简单且有效的连接配置。

重新部署验证

  1. 停止并移除旧容器

    bash 复制代码
    docker-compose down
  2. 删除旧数据卷(如果需要重新初始化数据):

    bash 复制代码
    docker volume rm weekly_mysql_data
  3. 重新构建镜像并启动容器

    bash 复制代码
    docker-compose up -d --build
  4. 验证部署结果

    bash 复制代码
    # 查看容器状态
    docker-compose ps
    
    # 查看应用日志
    docker-compose logs -f tomcat
  5. 访问应用验证

    复制代码
    http://172.16.xxx.xxx:8082/weekly/a/login

分享一下docker-compose.yml 的配置

yml 复制代码
# 创建一个新的用户定义网络,手动指定一个未被占用的子网
networks:
  weekly_network:
    driver: bridge
    ipam:
      config:
        - subnet: 10.0.0.0/24  # 使用一个未被占用的私有网络子网

services:
  # MySQL数据库服务
  mysql:
    image: mysql:5.7.44
    container_name: weekly_mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: root_password  # 替换为你的根密码
      MYSQL_DATABASE: weekly              # 数据库名
      MYSQL_USER: weekly_user             # 数据库用户名
      MYSQL_PASSWORD: weekly_password     # 数据库密码
    ports:
      - "3308:3306"
    volumes:
      - ./mysql/weekly.sql:/docker-entrypoint-initdb.d/init.sql  # 初始化脚本
      - mysql_data:/var/lib/mysql  # 数据持久化
    command: >
      --character-set-server=utf8mb4
      --collation-server=utf8mb4_unicode_ci
      --init-connect='SET NAMES utf8mb4'
      --skip-character-set-client-handshake
      --sql-mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
    networks:
      - weekly_network

  # Tomcat应用服务
  tomcat:
    build: .
    container_name: weekly_tomcat
    restart: always
    depends_on:
      - mysql
    ports:
      - "8082:8080"
    environment:
      - SPRING_PROFILES_ACTIVE=prod
    volumes:
      - tomcat_logs:/usr/local/tomcat/logs  # 日志持久化
    networks:
      - weekly_network

volumes:
  mysql_data:
    driver: local
  tomcat_logs:
    driver: local

预防措施

  1. 统一编码标准:确保应用、Tomcat、MySQL和数据库连接都使用UTF-8编码
  2. 适配驱动版本:根据MySQL版本选择合适的JDBC驱动,避免使用不兼容的连接参数
  3. 详细日志记录:启用应用和数据库的详细日志,便于排查问题
  4. 定期备份数据:确保数据安全,便于恢复
  5. 测试编码兼容性:在开发环境中测试多语言支持,确保编码正确
  6. 使用utf8mb4字符集:支持完整的Unicode字符,包括emoji表情

总结

通过系统性地排查和解决,我们成功解决了周报管理系统Docker部署中的乱码问题。主要解决步骤包括:

  1. 调整Tomcat配置,确保启用UTF-8编码支持
  2. 优化MySQL配置,统一字符集设置
  3. 修复数据库连接参数,确保与驱动版本兼容
  4. 重新部署验证,确认问题解决

如果觉得有帮助,欢迎点赞收藏!有问题欢迎评论区交流~

相关推荐
架构师老Y10 小时前
009、容器编排实战:Kubernetes上的Python服务
python·容器·kubernetes
SpikeKing10 小时前
VibeCoding - OpenClaw 公网访问配置指南 (自动化)
运维·自动化·vibecoding·openclaw
ulias21217 小时前
Linux系统中的权限问题
linux·运维·服务器
青花瓷18 小时前
Ubuntu下OpenClaw的安装(豆包火山API版)
运维·服务器·ubuntu
问简19 小时前
docker 镜像相关
运维·docker·容器
Dream of maid19 小时前
Linux(下)
linux·运维·服务器
齐鲁大虾19 小时前
统信系统UOS常用命令集
linux·运维·服务器
Benszen20 小时前
Docker容器化技术实战指南
运维·docker·容器
ZzzZZzzzZZZzzzz…20 小时前
Nginx 平滑升级:从 1.26.3 到 1.28.0,用户无感知
linux·运维·nginx·平滑升级·nginx1.26.3·nginx1.28.0
Hommy8820 小时前
【开源剪映小助手】Docker 部署
docker·容器·开源·github·aigc