通过Docker部署禅道丢失数据的一次吐血踩坑

  1. 问题描述
  2. 原因排查
  3. 最后总结

问题描述

事情的经过是这样的,使用禅道官方Docker镜像站点提供的docker-compose.yml文件部署禅道服务。在docker-compose.yml文件中修改了禅道镜像名,同时也修改了容器挂载的主机路径,修改后的文件docker-compose.yml内容如下:

version: '2'

networks:
  zentao-net:
    driver: bridge

services:

# mysql service for zentao
  zentao-mysql:
    image: mariadb:10.6
    container_name: zentao-mysql
    ports:
      - '3307:3306'
    volumes:
      - '/usr/local/zentao/db:/var/lib/mysql'
    environment:
      - MYSQL_ROOT_PASSWORD=pass4Zentao
      - MYSQL_DATABASE=zentao
    networks:
      - zentao-net

# redis service for zentao
#  zentao-redis:
#    image: redis:3.2.12-alpine3.8
#    container_name: zentao-redis
#    networks:
#      - zentao-net

# zentao service
  zentao:
    #image: hub.zentao.net/app/zentao:${TAG:-latest}
    image: easysoft/zentao:latest
    container_name: zentao
    ports:
      - '8085:80'
    volumes:
      - '/usr/local/zentao/data:/data'
    depends_on:
      - zentao-mysql
    environment:
      - ZT_MYSQL_HOST=zentao-mysql
      - ZT_MYSQL_PORT=3306
      - ZT_MYSQL_USER=root
      - ZT_MYSQL_PASSWORD=pass4Zentao
      - ZT_MYSQL_DB=zentao
     # - PHP_SESSION_TYPE=redis
     # - PHP_SESSION_PATH=tcp://zentao-redis:6379
     # - PHP_REDIS_SENTINEL=1  
      - PHP_MAX_EXECUTION_TIME=120
      - PHP_MAX_INPUT_VARS=2000
      - PHP_MEMORY_LIMIT=512M
      - PHP_POST_MAX_SIZE=128M
      - PHP_UPLOAD_MAX_FILESIZE=128M
      - LDAP_ENABLED=false
      - SMTP_ENABLED=false
      - SMTP_FROMNAME=禅道旗舰版
      - SMTP_HOST=192.168.50.182
      - SMTP_PORT=25
      - SMTP_USER=root@demo.com
      - SMTP_PASS=password
      - APP_DEFAULT_PORT=80
      - APP_DOMAIN=zentao.demo.com
      - PROTOCOL_TYPE=http
      - EASYSOFT_DEBUG=true
      - DEBUG=1
      - IS_CONTAINER=true
      - LINK_GIT=false
      - GIT_TYPE=gitea
      - GIT_INSTANCE_NAME=demo
      - GIT_USERNAME=user
      - GIT_PASSWORD=password
      - GIT_DOMAIN=https://git.demo.com
      # - GIT_TOKEN=token-example
      - LINK_CI=false
      - CI_TYPE=jenkins
      - CI_URL=https://jenkins.demo.com
      - CI_USERNAME=user
      - CI_PASSWORD=password
      # - CI_TOKEN=token-example
      - LINK_SCAN=false
      - SCAN_TYPE=sonarqube
      - SCAN_URL=https://sonarqube.demo.com
      - SCAN_USERNAME=user
      - SCAN_PASSWORD=password
    networks:
      - zentao-net

# persistence for mysql and zentao
#volumes:
#  zentao_db:
#    driver: local
#  zentao_data:
#    driver: local

修改后的docker-compose.yml与官方提供的docker-compose.yml内容差异如下:

服务使用了一段时间后遇到了服务器硬盘空间不够的问题,于是想迁移禅道服务的相关目录到指定路径。一开始并没有多想,因为已经明确将禅道服务的数据目录和对应MySQL数据目录都分别挂载到主机的/usr/local/zentao/data/usr/local/zentao/db目录下,以为只需要先将容器停止,将目录迁移到新的路径后再重启Docker容器即可。但是迁移目录到新的路径之后(将/usr/local/zentao/data迁移到/data/opt/zentao/data,将/usr/local/zentao/db迁移到/data/opt/zentao/db)重启禅道服务的Docker容器服务,再次访问时居然跳到了安装界面!

连接到禅道服务的数据库,发现数据库zentao是空的!!!

再次去禅道服务的MySQL数据挂载目录/data/opt/zentao/db查看:

$ ls -a /data/opt/zentao/db/zentao/
total 4
-rw-rw---- 1 polkitd input 67 Aug 17 10:46 db.opt

只有一个db.opt文件,并没有相关的表数据信息!!!

尝试着重新将docker-compose.yml文件中的挂载路径恢复为原来的配置,重新启动Docker容器之后再次访问依然进入了安装界面!!!

也就是说,只要修改了docker-compose.yml文件的挂载路径,重启禅道服务的Docker容器之后,再次访问时必然进入到安装界面!!!

最重要的是,数据也莫名其妙地丢失了,根本无法重新找回之前的数据。

原因排查

后来经过反复实验后发现,之所以会出现这个问题,是因为擅自更改了docker-compose.yml文件中禅道服务的镜像名导致的!

# zentao service
  zentao:
    #image: hub.zentao.net/app/zentao:${TAG:-latest}
    image: easysoft/zentao:latest # 这里修改镜像是有问题的,会导致对应的MySQL服务数据丢失

只要使用其默认配置的禅道服务镜像名就不会有任何问题!
也就是说禅道服务的镜像easysoft/zentao:latest在我使用的时候是有问题的,后来经过确认是easysoft/zentao:16.0这个镜像有问题,切忌切忌!!!

$ docker image ls
# id为bbba77b62d94的禅道镜像有问题,会导致数据库表丢失
REPOSITORY                  TAG       IMAGE ID       CREATED         SIZE
easysoft/zentao             16.0      bbba77b62d94   2 years ago     699MB
easysoft/zentao             latest    bbba77b62d94   2 years ago     699MB

经过此次事件也再次告诫自己:数据备份是多么重要啊,一定要定时做数据备份,即使出现意外损失也能小一些。
切记切记!!!

最后总结

在使用Docker方式部署应用时,一定要使用官方提供的方式进行;另外,一定要验证数据目录是否已经成功挂载到主机目录,并且可以实现备份。


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达,在下面评论区告诉我^_^^_^