背景

Rocket.Chat是一个基于JavaScript开发的开源聊天平台,常用于架设公司内部的通讯服务。Rocket.Chat使用MongoDB作为存放用户信息和聊天记录的数据库,使用默认方式安装(Docker或Snap)时,会为服务器自动安装5.0版本的MongoDB。但是自5.0版本开始,MongoDB必须在支持AVX指令集的处理器上才能正常运行。

近期友人购入了一台拿铁熊猫LattePanda 3 Delta,考虑到我们经常在公共聊天平台上传递密码等敏感信息,一旦账号被盗后果严重,因此我们考虑使用Rocket.Chat在上面搭建一个私人聊天平台。但是我在搭建过程中遇到了MongoDB无法运行导致Rocket.Chat也不能正常工作的情况,使用 docker logs指令看到MongoDB发生了如下段错误:
1_mongodb5_crash
经查找有关资料发现是因为LattePanda 3 Delta不支持AVX指令集,只能运行4.4.0及以下版本的MongoDB。下面我将记录我的搭建过程,希望对存在类似问题的人有所帮助。

1. 安装Docker并下载Rocket.Chat配置文件

使用Snap安装会直接尝试安装MongoDB 5.0,从而因为MongoDB安装失败导致Rocket.Chat也安装失败,因此只能使用Docker安装。

  1. 安装Docker和Docker Compose,此步骤不过多赘述。

  2. 创建一个空文件夹,用来存放Rocket.Chat的Docker Compose服务配置文件,切换当前目录到该文件夹下并执行以下指令以下载配置文件1

    curl -L https://raw.githubusercontent.com/RocketChat/Docker.Official.Image/master/compose.yml -O
    

    文件内容如下:

    volumes:
      mongodb_data: { driver: local }
    
    services:
      rocketchat:
        image: registry.rocket.chat/rocketchat/rocket.chat:${RELEASE:-latest}
        restart: always
        labels:
          traefik.enable: "true"
          traefik.http.routers.rocketchat.rule: Host(`${DOMAIN:-}`)
          traefik.http.routers.rocketchat.tls: "true"
          traefik.http.routers.rocketchat.entrypoints: https
          traefik.http.routers.rocketchat.tls.certresolver: le
        environment:
          MONGO_URL: "${MONGO_URL:-\
            mongodb://${MONGODB_ADVERTISED_HOSTNAME:-mongodb}:${MONGODB_INITIAL_PRIMARY_PORT_NUMBER:-27017}/\
            ${MONGODB_DATABASE:-rocketchat}?replicaSet=${MONGODB_REPLICA_SET_NAME:-rs0}}"
          MONGO_OPLOG_URL: "${MONGO_OPLOG_URL:\
            -mongodb://${MONGODB_ADVERTISED_HOSTNAME:-mongodb}:${MONGODB_INITIAL_PRIMARY_PORT_NUMBER:-27017}/\
            local?replicaSet=${MONGODB_REPLICA_SET_NAME:-rs0}}"
          ROOT_URL: ${ROOT_URL:-http://localhost:${HOST_PORT:-3000}}
          PORT: ${PORT:-3000}
          DEPLOY_METHOD: docker
          DEPLOY_PLATFORM: ${DEPLOY_PLATFORM:-}
          REG_TOKEN: ${REG_TOKEN:-}
        depends_on:
          - mongodb
        expose:
          - ${PORT:-3000}
        ports:
          - "${BIND_IP:-0.0.0.0}:${HOST_PORT:-3000}:${PORT:-3000}"
    
      mongodb:
        image: docker.io/bitnami/mongodb:${MONGODB_VERSION:-5.0}
        restart: always
        volumes:
          - mongodb_data:/bitnami/mongodb
        environment:
          MONGODB_REPLICA_SET_MODE: primary
          MONGODB_REPLICA_SET_NAME: ${MONGODB_REPLICA_SET_NAME:-rs0}
          MONGODB_PORT_NUMBER: ${MONGODB_PORT_NUMBER:-27017}
          MONGODB_INITIAL_PRIMARY_HOST: ${MONGODB_INITIAL_PRIMARY_HOST:-mongodb}
          MONGODB_INITIAL_PRIMARY_PORT_NUMBER:${MONGODB_INITIAL_PRIMARY_PORT_NUMBER:-27017}
          MONGODB_ADVERTISED_HOSTNAME: ${MONGODB_ADVERTISED_HOSTNAME:-mongodb}
          MONGODB_ENABLE_JOURNAL: ${MONGODB_ENABLE_JOURNAL:-true}
          ALLOW_EMPTY_PASSWORD: ${ALLOW_EMPTY_PASSWORD:-yes}
    
  3. 输入以下指令以下载环境变量配置文件1

    wget https://raw.githubusercontent.com/RocketChat/Docker.Official.Image/master/env.example
    mv env.example .env
    

    文件内容如下:

    ### Rocket.Chat configuration
    
    # Rocket.Chat version
    # see:- https://github.com/RocketChat/Rocket.Chat/releases
    #RELEASE=
    # MongoDB endpoint (include ?replicaSet= parameter)
    #MONGO_URL=
    # MongoDB endpoint to the local database
    #MONGO_OPLOG_URL=
    # IP to bind the process to
    #BIND_IP=
    # URL used to access your Rocket.Chat instance
    #ROOT_URL=
    # Port Rocket.Chat runs on (in-container)
    #PORT=
    # Port on the host to bind to
    #HOST_PORT=
    
    ### MongoDB configuration
    # MongoDB version/image tag
    #MONGODB_VERSION=
    # See:- https://hub.docker.com/r/bitnami/mongodb
    
    ### Traefik config (if enabled)
    # Traefik version/image tag
    #TRAEFIK_RELEASE=
    # Domain for https (change ROOT_URL & BIND_IP accordingly)
    #DOMAIN=
    # Email for certificate notifications
    #LETSENCRYPT_EMAIL=
    

    该文件中的配置在部署时将会替换 compose.yml中使用类似格式 ${arg:-default}标出的参数。

2. 修改MongoDB有关配置

  1. 去掉 .env文件中 #MONGODB_VERSION=前的 #,并在其后输入本次要配置的版本 4.4.0

    MONGODB_VERSION=4.4.0
    
  2. (可选)修改 compose.yml,在 mongodb标签内,与 volumesenvironment标签同级的位置加入以下配置

    expose:
     - ${MONGO_PORT:-27017}
    ports:
     - ${MONGO_BIND_IP:-127.0.0.1}:${MONGO_HOST_PORT:-27017}:27017
    

    这样在容器启动后,MongoDB会部署在主机的 MONGO_HOST_PORT端口上,该端口号在此处默认为 27017,在 .env中可以修改 MONGO_HOST_PORT的值。这么做的好处是便于从主机直接访问MongoDB来进行删除聊天记录等维护操作,同时还有利于其它基于MongoDB的服务共享数据库。如果不映射MongoDB的端口,使用如下指令也可以访问Docker容器内的MongoDB。

    sudo docker exec -it <MongoDB的Container ID> mongo
    

    此处 MONGO_BIND_IP127.0.0.1,这是为了保证只从主机上访问MongoDB,该IP也可以为 0.0.0.0或直接不提供(此时为缺省值 0.0.0.0)。需要注意的是,当该值为 0.0.0.0时,外部主机也可以访问MongoDB,而Rocket.Chat要求MongoDB必须支持匿名访问(至少我没有找到让Rocket.Chat使用指定账户登录MongoDB的方法),如果防火墙配置存在问题,未知第三方就可以匿名登录主机的数据库从而窃取聊天记录。

    Ubuntu可以使用以下指令查看防火墙配置。

    sudo ufw status
    

    仅当 ufw启动,且 27017对外关闭时,才建议 MONGO_BIND_IP0.0.0.0

  3. 启动MongoDB容器
    compose.yml所在的目录中使用如下指令部署容器。

    sudo docker-compose up -d
    

    之后使用如下指令可以查看当前已启动的容器。

    sudo docker ps -a
    

    不出意外的话,应该可以看到MongoDB成功启动,Rocket.Chat容器会在数秒后直接退出,这是因为我们还没有配置Rocke.Chat有关的参数。

3. 修改Rocket.Chat有关配置

  1. 配置 MONGO_URL
    使用如下指令可以看到Rocket.Chat此时的报错如图所示。

    sudo docker logs <Rocket.Chat的Container ID>
    

    2_rocketchat_cant_parse_mongo_url
    经过多次尝试后,我发现这是因为不知道为什么,Docker无法正确识别默认参数中给出的 MONGO_URLMONGO_OPLOG_URL,可以在 .env中直接给出MongoDB的地址。

    .env文件中 #MONGO_URL=#MONGO_OPLOG_URL=前的 #去掉并修改为如下内容。

    MONGO_URL=mongodb://mongodb:27017/rocketchat?replicaSet=rs0&authSource=admin
    MONGO_OPLOG_URL=mongodb://mongodb:27017/local?replicaSet=rs0&authSource=admin
    

    链接中之所以能写 mongodb:27017是因为在MongoDB的容器配置文件中给出了有关参数,链接末尾的 replicaSet=rs0authSource=admin不能省,前者 replicaSet=rs0在原始的 compose.yml配置中也有给出,后者 authSource=admin是Rocket.Chat Docs中给出的配置1,缺少其中任何一个,Rocket.Chat在连接MongoDB时都会发生超时,docker logs查找到的错误信息如下。
    3_rocketchat_cant_access_mongodb
    虽然两个链接本应可以写作 username:password@mongodb:27017来指定登录数据库的账号密码,但经我实测发现这么做不行,依然会导致连接超时。

  2. 配置 ROOT_URL
    再次使用 sudo docker-compose up -d,Rocket.Chat容器能正常运行,但访问 localhost:3000只能看到 Unknown path字样,从 docker logs中能查到如下报错信息。
    4_rocketchat_cant_parse_root_url
    经反复测试后发现是因为Docker无法正确读取 .env中的 ROOT_URL参数,所以只能直接在 compose.yml中修改,即将 compose.yml中的

    ROOT_URL: ${ROOT_URL:-http://localhost:${HOST_PORT:-3000}}
    

    直接改为

    ROOT_URL: <Your Root Url, For example: localhost:3000>
    
  3. (可选)映射上传文件的保存路径
    我希望用户上传的文件保存在文件系统中而不是数据库中,因此需要将Rocket.Chat保存用户上传的文件的路径映射到主机上。

    compose.yml中,rocketchat标签内,与 environmentexposeports标签同级的位置加入以下配置。

    volumes:
     - /home/rocketchat:/app/uploads:rw
    user: root
    

    此处 user: root不能省去,否则Rocket.Chat会因为对目录没有写入权限而使用户无法上传文件。

    在配置完成后,可用管理员账户在Rocket.Chat网页端的 设置 > 文件上传位置找到 存储类型 设置,GridFS表示将上传的文件储存在数据库中,FileSystem表示将上传的文件以文件形式储存在主机上。

    如果使用 FileSystem,需要在下方的 File System标签内设置文件的存储位置,此位置为Docker容器内的路径,在使用上述配置(将容器内 /app/uploads映射到主机 /home/rocketchat)的情况下,需要在此填入

    /app/uploads
    
  4. 启动Rocket.Chat容器
    最后再一次执行

    sudo docker-compose up -d
    

    通过 docker ps -a可以看到Rocket.Chat容器正常运行,浏览器访问 localhost:3000,可以正常显示出Rocket.Chat的网页端界面,到此配置完成。


  1. 参考Rocket.Chat Docs配置文档,链接:Docker & Docker Compose

文章作者: 卡比三卖萌KirCute
本文链接:
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 卡比三卖萌KirCute的博客
运维
喜欢就支持一下吧