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. 重新部署验证,确认问题解决

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

相关推荐
YongCheng_Liang2 小时前
数据库核心概念深度解析:从基础原理到 SQL 分类
运维·数据库·sql
宇钶宇夕2 小时前
CoDeSys入门实战一起学习(六):CoDeSys软件模型核心架构——从分层结构到核心元素
运维·自动化
Web极客码2 小时前
如何在 WordPress 中设置会员内容:简单两步实现注册用户专属访问
运维·wordpress·网站管理·网站维护
林鸿风采2 小时前
Alpine Linux 安装指南:轻量、安全、高效的系统部署实践
linux·运维·安全·alpine
heda32 小时前
zip在linux上解压出错Unicode编码-解决
linux·运维·python
济6172 小时前
linux 系统移植(第四期)--Uboot移植(4)--在U-Boot 中添加自己的开发板(3) -网络驱动修改-- Ubuntu20.04
linux·运维·服务器
java_logo2 小时前
PyTorch Docker 容器化部署与生产运行实践
人工智能·pytorch·docker·pytorch部署·pytorch部署文档·pytorch部署教程·pytorch上部署方案
2301_765715142 小时前
Linux虚拟机NAT模式网络故障解析与修复指南
linux·运维·服务器
OpsEye2 小时前
监控 100 问(四):如何实现 IT 监控自动化
运维·网络·it运维·it·监控·监控系统