Linux 服务器从零部署 kkFileView 完全指南(Docker 方案)

写在前面

做企业信息化这几年,"文件在线预览"这个需求几乎每个项目都会碰到。合同审批要预览 PDF,OA 系统要看 Word 附件,网盘要支持 Excel 和 PPT 的即时查看------如果每次都让用户把文件下载到本地再打开,体验差是一方面,更关键的是存在文件外泄的安全隐患。

kkFileView 是目前国内用得最多的一款开源文件在线预览方案,基于 Spring Boot 构建,支持 Office 全家桶、PDF、图片、音视频、压缩包、CAD 图纸等几十种格式,部署起来也不复杂。但说实话,官方文档写得比较"骨感",真正到生产环境落地的时候,字体问题、配置调优、Nginx 代理、容器编排这些细节,文档里基本没怎么展开。

这篇文章就是我把自己前后折腾了好几套环境的经验整理出来的,从一台全新的 Linux 服务器开始,一步步把 kkFileView 跑起来,跑稳,跑好。


一、先搞清楚 kkFileView 是什么、能干什么

kkFileView 的核心逻辑其实不复杂:你的业务系统把文件的访问 URL 传给它,它在服务端把文件下载下来,用 LibreOffice 做格式转换(比如 docx 转成 PDF,再转成 HTML 或图片),最后把转换结果通过浏览器渲染出来。整个过程对用户透明,用户只看到一个"打开即预览"的效果。

它支持的文件格式非常广,这里列几个大类:

  • 办公文档 :doc、docx、xls、xlsx、ppt、pptx、wps、et、dps
  • PDF 类 :pdf(含扫描件)
  • 图片 :jpg、png、bmp、gif、tiff、webp、svg
  • 文本 :txt、csv、xml、json、yml
  • 压缩包 :zip、rar、7z、tar、gz
  • 音视频 :mp3、mp4、avi、mov、flv、mkv
  • CAD/设计 :dwg、dxf、psd
  • 其他 :markdown、epub、xmind

预览接口只有一个,核心参数就是文件的 URL 地址(需要做 Base64 编码)。这意味着它跟你的业务系统是松耦合的,不管你后端是 Java、Python 还是 Go,只要能拼 URL 就能对接。


二、服务器选型与基础要求

2.1 硬件配置建议

我按实际跑下来的经验给个参考:

场景 CPU 内存 磁盘 说明
开发/测试 2 核 4 GB 20 GB 够用,但别指望并发
小型生产(日活 < 200) 4 核 8 GB 50 GB 推荐起步配置
中型生产(日活 200~1000) 8 核 16 GB 100 GB SSD 建议 SSD,文件转换是 IO 密集型
大型生产 按集群方案走 32 GB+ 按需 需要多实例 + 负载均衡

有几个点要特别注意:

内存是最容易成为瓶颈的资源。 LibreOffice 做文档转换的时候非常吃内存,一个 50 页的 Word 转 PDF 可能瞬间吃掉 500MB 以上。如果同时来了五六个转换请求,4GB 内存的机器基本就扛不住了。我最初用 2GB 内存的测试机跑,稍微大一点的文件直接把容器 OOM Kill 了,后来加到 8GB 才稳定。

磁盘空间别省。 kkFileView 会把转换后的文件缓存在本地,如果你的业务量大、文件类型多,缓存目录会膨胀得很快。另外 Docker 镜像本身、LibreOffice 运行时产生的临时文件,都需要磁盘空间。建议至少预留 50GB,并且把缓存目录挂载到数据盘上。

2.2 操作系统选择

理论上任何能跑 Docker 的 Linux 发行版都行,但我个人推荐以下两个:

  • Ubuntu 22.04 LTS :软件源新,Docker 安装方便,社区资料多,出问题好搜。
  • CentOS 7.9 / Rocky Linux 8/9 :如果你们公司基础设施统一用 CentOS 系,也完全可以。注意 CentOS 7 已经停止维护,新环境建议上 Rocky Linux 或 AlmaLinux。

本文后续的命令会同时给出 Ubuntu 和 CentOS 两个版本,你根据自己的系统选着看就行。

2.3 网络要求

  • 服务器需要能访问外网(至少首次部署时需要,用于拉取 Docker 镜像)。如果是纯内网环境,后面我会讲离线导入镜像的办法。
  • 需要开放 8012 端口(kkFileView 默认端口),或者通过 Nginx 代理后只开放 80/443。

三、操作系统初始化

拿到一台全新的服务器,别急着装东西,先把基础环境收拾干净。

3.1 更新系统软件包

bash 复制代码
# Ubuntu / Debian
sudo apt update && sudo apt upgrade -y

# CentOS / Rocky Linux
sudo yum update -y
# 或者 Rocky Linux 8/9 用 dnf
sudo dnf update -y

3.2 安装基础工具

后面会用到 wget、curl、vim 这些工具,一次性装好:

bash 复制代码
# Ubuntu
sudo apt install -y curl wget vim htop net-tools unzip

# CentOS
sudo yum install -y curl wget vim htop net-tools unzip

3.3 关闭或配置防火墙

开发阶段可以暂时关闭防火墙,生产环境建议只开放需要的端口。

bash 复制代码
# Ubuntu (ufw)
sudo ufw allow 22/tcp      # SSH
sudo ufw allow 80/tcp      # HTTP
sudo ufw allow 443/tcp     # HTTPS
sudo ufw allow 8012/tcp    # kkFileView(如果不用 Nginx 代理的话)
sudo ufw enable

# CentOS (firewalld)
sudo systemctl start firewalld
sudo systemctl enable firewalld
sudo firewall-cmd --zone=public --add-port=22/tcp --permanent
sudo firewall-cmd --zone=public --add-port=80/tcp --permanent
sudo firewall-cmd --zone=public --add-port=443/tcp --permanent
sudo firewall-cmd --zone=public --add-port=8012/tcp --permanent
sudo firewall-cmd --reload

如果你用的是阿里云、腾讯云这类云服务器,除了系统防火墙,还要去云控制台的安全组里把对应端口放行,这一步很多人会忘。

3.4 设置时区(可选但建议)

bash 复制代码
sudo timedatectl set-timezone Asia/Shanghai

四、安装 Docker

这是整个部署的核心前置步骤。kkFileView 的 Docker 镜像里已经打包好了 JDK 1.8、LibreOffice 以及所有运行时依赖,所以宿主机上不需要单独装 Java 或 LibreOffice。

4.1 一键安装(推荐)

Docker 官方提供了一键安装脚本,适用于绝大多数 Linux 发行版:

bash 复制代码
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

如果你的服务器在国内,访问 Docker 官方源可能比较慢,可以用阿里云的镜像脚本:

bash 复制代码
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun

4.2 手动安装(Ubuntu)

如果你更习惯手动控制安装过程:

bash 复制代码
# 卸载旧版本(如果有的话)
sudo apt remove -y docker docker-engine docker.io containerd runc

# 安装依赖
sudo apt install -y ca-certificates curl gnupg lsb-release

# 添加 Docker 官方 GPG 密钥
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

# 添加软件源
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 安装 Docker Engine
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

4.3 手动安装(CentOS / Rocky Linux)

bash 复制代码
# 卸载旧版本
sudo yum remove -y docker docker-client docker-client-latest docker-common \
    docker-latest docker-latest-logrotate docker-logrotate docker-engine

# 安装依赖
sudo yum install -y yum-utils

# 添加 Docker 软件源
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

# 安装
sudo yum install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

4.4 启动 Docker 并设置开机自启

bash 复制代码
sudo systemctl start docker
sudo systemctl enable docker

4.5 配置 Docker 镜像加速(国内服务器强烈建议)

国内服务器直接拉 Docker Hub 的镜像,速度感人,经常超时。配一个镜像加速器能省很多事:

bash 复制代码
sudo mkdir -p /etc/docker

sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": [
    "https://docker.1ms.run",
    "https://docker.xuanyuan.me"
  ],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m",
    "max-file": "3"
  },
  "storage-driver": "overlay2"
}
EOF

sudo systemctl daemon-reload
sudo systemctl restart docker

注意:镜像加速站的可用性经常变化,如果上面的地址不好使,可以搜一下当前可用的加速地址替换进去。

4.6 将当前用户加入 docker 组

默认情况下,执行 docker 命令需要 sudo。把当前用户加到 docker 组里就不用每次都输密码了:

bash 复制代码
sudo groupadd docker 2>/dev/null
sudo usermod -aG docker $USER
newgrp docker

执行完之后,需要退出当前终端重新登录 才能完全生效。验证一下:

bash 复制代码
docker run hello-world

能看到 "Hello from Docker!" 的输出就说明安装成功了。

4.7 验证 Docker 版本

bash 复制代码
docker --version
docker compose version

建议 Docker Engine 版本不低于 20.10.0,Docker Compose 不低于 v2.x。


五、关于 Java 环境的说明

这里单独拿出来说一下,因为很多人会纠结"要不要在宿主机上装 Java"。

结论是:如果你用 Docker 部署 kkFileView,宿主机上不需要装 Java。

kkFileView 的 Docker 镜像内部已经包含了完整的 JDK 1.8 运行环境。容器是隔离的,它自己带自己的 Java,跟宿主机没关系。

但如果你有以下情况,可能还是需要在宿主机装 Java:

  • 你打算用非 Docker 方式部署(直接跑 jar 包)
  • 你的服务器上还有其他 Java 应用需要跑
  • 你需要在宿主机上用 Java 做一些辅助工作

如果有需要,安装方式如下:

bash 复制代码
# Ubuntu
sudo apt install -y openjdk-8-jdk

# CentOS
sudo yum install -y java-1.8.0-openjdk-devel

# 验证
java -version

再次强调:Docker 部署方案下,这一步可以跳过。


六、拉取并运行 kkFileView 容器

6.1 拉取镜像

bash 复制代码
docker pull keking/kkfileview:4.1.0

如果你不指定版本号,用 latest 也行,但我建议生产环境锁定版本号,避免某天自动更新导致不兼容:

bash 复制代码
# 也可以拉 latest
docker pull keking/kkfileview

如果你的服务器无法访问外网 (纯内网环境),可以在有网的机器上先把镜像下载下来,然后传到内网服务器导入:

bash 复制代码
# 在有网的机器上下载离线包
wget https://kkview.cn/resource/kkFileView-4.1.0-docker.tar

# 传到内网服务器后加载
docker load -i kkFileView-4.1.0-docker.tar

或者用 docker savedocker load 的方式:

bash 复制代码
# 有网机器上导出
docker save -o kkfileview-4.1.0.tar keking/kkfileview:4.1.0

# 内网机器上导入
docker load -i kkfileview-4.1.0.tar

6.2 创建必要的目录结构

在正式运行之前,先在宿主机上规划好目录结构。我建议统一放在 /data/opt 下面:

bash 复制代码
sudo mkdir -p /data/kkfileview/config
sudo mkdir -p /data/kkfileview/file
sudo mkdir -p /data/kkfileview/logs
sudo mkdir -p /data/kkfileview/fonts

各目录的用途:

  • config :存放 application.properties 配置文件
  • file :存放预览产生的缓存文件
  • logs :日志目录
  • fonts :中文字体文件

6.3 首次启动:提取配置文件

第一次跑的时候,我们先用一个临时容器把默认的配置文件拷贝出来,方便后续修改:

bash 复制代码
# 启动一个临时容器
docker run -d --name kkfileview-temp keking/kkfileview:4.1.0

# 等几秒钟让容器完全启动,然后拷贝配置文件
docker cp kkfileview-temp:/opt/kkFileView-4.1.0/config/application.properties /data/kkfileview/config/

# 拷贝完成后删除临时容器
docker stop kkfileview-temp
docker rm kkfileview-temp

注意:容器内的路径可能因版本不同而有差异。如果上面的路径不对,可以先 docker exec -it kkfileview-temp bash 进去 find / -name "application.properties" 找一下实际路径。4.4.0 版本的路径可能是 /opt/kkFileView-4.4.0/config/

6.4 正式运行容器

基础启动命令:

bash 复制代码
docker run -d \
  --name kkfileview \
  -p 8012:8012 \
  --restart=always \
  keking/kkfileview:4.1.0

生产环境推荐启动命令(带配置挂载和资源限制):

bash 复制代码
docker run -d \
  --name kkfileview \
  -p 8012:8012 \
  -v /data/kkfileview/config/application.properties:/opt/kkFileView-4.1.0/config/application.properties \
  -v /data/kkfileview/file:/opt/kkFileView-4.1.0/file \
  -v /data/kkfileview/logs:/opt/kkFileView-4.1.0/log \
  -v /data/kkfileview/fonts:/usr/share/fonts/chinese \
  -e KK_JVM_OPTIONS="-Xms1g -Xmx2g -XX:MaxDirectMemorySize=1g" \
  --memory=4g \
  --memory-swap=4g \
  --restart=always \
  keking/kkfileview:4.1.0

各参数含义逐一说明:

参数 作用
-d 后台运行
--name kkfileview 容器命名,方便后续管理
-p 8012:8012 端口映射,宿主机 8012 → 容器 8012
-v ...application.properties 挂载自定义配置文件
-v .../file 持久化预览缓存文件
-v .../log 持久化日志
-v .../fonts 挂载中文字体
-e KK_JVM_OPTIONS JVM 内存参数
--memory=4g 容器最大内存限制
--restart=always 容器异常退出或服务器重启后自动拉起

6.5 验证服务是否正常

bash 复制代码
# 查看容器状态
docker ps | grep kkfileview

# 查看启动日志
docker logs -f kkfileview

日志里看到类似 Started ServerApplication in x.xxx seconds 的字样,说明服务已经起来了。

然后在浏览器里访问:

arduino 复制代码
http://你的服务器IP:8012

能看到 kkFileView 的首页(有一个文件上传预览的演示界面),就说明部署成功了。


七、使用 Docker Compose 管理(推荐)

单个容器用 docker run 跑没问题,但如果你后续还要加 Nginx、Redis 之类的组件,或者想做更精细的配置管理,用 Docker Compose 会方便很多。所有配置写在一个 yml 文件里,一条命令启停,版本管理也方便。

7.1 编写 docker-compose.yml

bash 复制代码
mkdir -p /data/kkfileview && cd /data/kkfileview
vim docker-compose.yml

写入以下内容:

yaml 复制代码
version: '3.8'

services:
  kkfileview:
    image: keking/kkfileview:4.1.0
    container_name: kkfileview
    restart: always
    ports:
      - "8012:8012"
    volumes:
      - ./config/application.properties:/opt/kkFileView-4.1.0/config/application.properties
      - ./file:/opt/kkFileView-4.1.0/file
      - ./logs:/opt/kkFileView-4.1.0/log
      - ./fonts:/usr/share/fonts/chinese
    environment:
      - KK_JVM_OPTIONS=-Xms1g -Xmx2g -XX:MaxDirectMemorySize=1g
    deploy:
      resources:
        limits:
          memory: 4g
        reservations:
          memory: 1g
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8012"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s
    logging:
      driver: "json-file"
      options:
        max-size: "100m"
        max-file: "3"

7.2 启动与管理

bash 复制代码
# 启动(后台运行)
docker compose up -d

# 查看状态
docker compose ps

# 查看日志
docker compose logs -f kkfileview

# 停止
docker compose down

# 重启
docker compose restart

# 更新镜像后重新创建容器
docker compose pull
docker compose up -d

八、核心配置文件详解

kkFileView 的所有行为都由 application.properties 控制。前面我们已经把它从容器里拷出来了,路径在 /data/kkfileview/config/application.properties

下面把生产环境中最常改的配置项拎出来说。

8.1 服务端口与上下文路径

properties 复制代码
# 服务端口,默认 8012,一般不用改
server.port=8012

# 上下文路径,如果你要通过 Nginx 代理到某个子路径下,需要改这里
# 默认是 /,如果 Nginx 代理路径是 /preview,这里就改成 /preview
server.servlet.context-path=/

8.2 文件缓存目录

properties 复制代码
# 预览文件的存储路径,默认是程序根目录下的 file 目录
# 生产环境建议指向一个磁盘空间充裕的路径
file.dir=/opt/kkFileView-4.1.0/file

8.3 缓存过期时间

properties 复制代码
# 缓存过期时间(秒),默认 86400 即 24 小时
# 过期后再次预览会重新转换,如果文件很大转换会很慢
# 根据业务需要调整,设太长占磁盘,设太短影响体验
cache.expired.time=86400

8.4 是否开启文件上传功能

properties 复制代码
# kkFileView 首页有一个演示上传功能
# 生产环境强烈建议关掉,避免被人当文件中转站
file.upload.disable=false

8.5 信任主机配置(安全相关)

properties 复制代码
# 配置信任的主机,防止 SSRF 攻击
# 多个用英文逗号隔开
# 如果不配置,默认信任所有来源(不安全)
trust.host=your-domain.com,192.168.1.0/24

这一项在对接业务系统的时候很重要。如果不限制,任何人都可以构造一个内网地址让 kkFileView 去请求,存在 SSRF 风险。

8.6 LibreOffice 相关

properties 复制代码
# LibreOffice 安装路径(Docker 镜像里一般已经配好了,不用动)
office.home=/opt/libreoffice7.1

# 预览服务端口(LibreOffice 内部通信用的),默认 2002
office.port=2002

# 文档转换超时时间(毫秒),大文件可能需要调大
office.timeout=120000

8.7 修改配置后如何生效

因为配置文件是通过 -v 挂载进容器的,修改完宿主机的文件后,重启容器即可:

bash 复制代码
docker restart kkfileview
# 或者用 compose
docker compose restart kkfileview

九、中文字体安装(非常重要)

这个问题我必须单独拿出来讲,因为 90% 的人第一次部署完都会碰到

Linux 系统默认不带中文字体,而 kkFileView 底层用 LibreOffice 做文档转换,转换的时候如果找不到文档里用到的中文字体(宋体、微软雅黑、黑体等),预览出来就是一堆方块或者乱码。

9.1 获取字体文件

最方便的方式是从一台 Windows 电脑上把字体拷出来。打开 C:\Windows\Fonts 目录,把常用的字体文件复制出来:

  • simsun.ttc (宋体)
  • simhei.ttf (黑体)
  • simkai.ttf (楷体)
  • simfang.ttf (仿宋)
  • msyh.ttc (微软雅黑)
  • arial.ttftimes.ttf (英文基础字体,一般镜像里有)

另外,kkFileView 官方也提供了一个字体包可以直接下载:

bash 复制代码
wget http://kkfileview.keking.cn/fonts.zip
unzip fonts.zip -d /data/kkfileview/fonts/

9.2 放置字体并刷新缓存

因为我们前面已经把 /data/kkfileview/fonts 挂载到了容器内的 /usr/share/fonts/chinese,所以字体文件放到宿主机目录后,还需要在容器内刷新字体缓存:

bash 复制代码
# 进入容器
docker exec -it kkfileview bash

# 安装字体工具(如果容器里没有的话)
apt-get update && apt-get install -y fontconfig

# 刷新字体缓存
fc-cache -fv

# 验证字体是否识别
fc-list | grep -i "sim"

# 退出容器
exit

或者,更推荐的做法是把字体安装步骤固化下来,不用每次手动进容器操作。你可以在字体目录下放一个初始化脚本,或者直接重新构建一个自定义镜像(后面会讲)。

9.3 重启服务使字体生效

bash 复制代码
docker restart kkfileview

然后上传一个包含中文内容的 Word 或 PDF 测试一下,确认显示正常。

9.4 补充说明

如果你的业务涉及 CAD 图纸(dwg 文件),可能还需要额外的工程字体,比如 gbenor.shxgbcbig.shx 这类 SHX 字体,以及 simsun.ttc 等 TrueType 字体。CAD 字体缺失的表现跟文档乱码类似,都是文字变成方块。


十、Nginx 反向代理配置

生产环境里,一般不会让用户直接访问 8012 端口。通常是前面挂一个 Nginx,统一走 80 或 443 端口,顺便把 HTTPS、访问控制、负载均衡这些都做了。

10.1 安装 Nginx

bash 复制代码
# Ubuntu
sudo apt install -y nginx

# CentOS
sudo yum install -y epel-release
sudo yum install -y nginx

# 启动并设置开机自启
sudo systemctl start nginx
sudo systemctl enable nginx

10.2 基础 HTTP 代理配置

创建配置文件:

bash 复制代码
sudo vim /etc/nginx/conf.d/kkfileview.conf

写入:

nginx 复制代码
upstream kkfileview_backend {
    server 127.0.0.1:8012;
    keepalive 32;
}

server {
    listen 80;
    server_name preview.yourdomain.com;

    # 如果需要自定义上下文路径,比如 /preview
    # location /preview {
    #     proxy_pass http://kkfileview_backend/;
    # }

    location / {
        proxy_pass http://kkfileview_backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # 文件预览可能比较大,超时时间设长一点
        proxy_connect_timeout 300s;
        proxy_send_timeout 300s;
        proxy_read_timeout 300s;

        # 大文件上传/转换需要
        client_max_body_size 200m;
    }
}

检查配置并重载:

bash 复制代码
sudo nginx -t
sudo systemctl reload nginx

10.3 HTTPS 配置(生产环境必做)

如果你有 SSL 证书(阿里云、腾讯云、Let's Encrypt 都可以),配置如下:

nginx 复制代码
# HTTP 强制跳转 HTTPS
server {
    listen 80;
    server_name preview.yourdomain.com;
    return 301 https://$server_name$request_uri;
}

# HTTPS 主配置
server {
    listen 443 ssl http2;
    server_name preview.yourdomain.com;

    ssl_certificate     /etc/nginx/ssl/yourdomain.com.pem;
    ssl_certificate_key /etc/nginx/ssl/yourdomain.com.key;
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         HIGH:!aNULL:!MD5;
    ssl_session_cache   shared:SSL:10m;
    ssl_session_timeout 10m;

    upstream kkfileview_backend {
        server 127.0.0.1:8012;
        keepalive 32;
    }

    location / {
        proxy_pass http://kkfileview_backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;

        proxy_connect_timeout 300s;
        proxy_send_timeout 300s;
        proxy_read_timeout 300s;

        client_max_body_size 200m;
    }
}

注意:如果配了 HTTPS,kkFileView 的 application.properties 里有一项 base.url 需要同步改成 https://preview.yourdomain.com,否则预览链接会拼错协议头。

10.4 使用子路径代理

如果你不想给 kkFileView 单独分配一个域名或子域名,想挂在主站的一个子路径下(比如 https://www.yourdomain.com/preview),需要同时改 Nginx 和 kkFileView 的配置:

Nginx 侧:

nginx 复制代码
location /preview {
    proxy_pass http://127.0.0.1:8012/;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

kkFileView 的 application.properties 侧:

properties 复制代码
server.servlet.context-path=/preview

容器启动时也需要传入环境变量:

bash 复制代码
docker run -d \
  -e KK_BASE_URL="https://www.yourdomain.com/preview" \
  -e KK_CONTEXT_PATH="/preview" \
  -e KK_TRUST_HOST="www.yourdomain.com" \
  -p 8012:8012 \
  keking/kkfileview:4.1.0

十一、安全加固

kkFileView 作为一个文件预览服务,天然会接收到外部传入的 URL,如果不做安全限制,可能被利用来做 SSRF 攻击或者被当作免费的文件转换工具。以下几点在生产环境中务必落实。

11.1 关闭演示上传页面

默认的首页有一个文件上传预览的演示功能,生产环境必须关掉:

properties 复制代码
# application.properties
file.upload.disable=true

11.2 配置信任主机白名单

properties 复制代码
# 只允许来自这些域名的预览请求
trust.host=your-business-domain.com,another-domain.com

11.3 限制访问来源

通过 Nginx 做 IP 白名单或者 Basic Auth:

nginx 复制代码
location / {
    # 只允许内网访问
    allow 10.0.0.0/8;
    allow 172.16.0.0/12;
    allow 192.168.0.0/16;
    deny all;

    proxy_pass http://kkfileview_backend;
    # ... 其他 proxy 配置
}

11.4 容器安全

  • 不要以 --privileged 模式运行容器
  • 限制容器内存(--memory),防止恶意大文件把宿主机内存打满
  • 定期更新镜像版本,关注 kkFileView 的 GitHub 安全公告

11.5 定期清理缓存

预览缓存会持续占用磁盘空间,建议加一个定时清理任务:

bash 复制代码
# 创建清理脚本
cat > /data/kkfileview/clean_cache.sh << 'EOF'
#!/bin/bash
# 清理 7 天前的缓存文件
find /data/kkfileview/file -type f -mtime +7 -delete
echo "[$(date)] Cache cleaned." >> /data/kkfileview/logs/clean.log
EOF

chmod +x /data/kkfileview/clean_cache.sh

# 添加 crontab 定时任务,每天凌晨 3 点执行
(crontab -l 2>/dev/null; echo "0 3 * * * /data/kkfileview/clean_cache.sh") | crontab -

十二、生产环境性能调优

12.1 JVM 参数调整

默认情况下容器内的 JVM 参数比较保守。如果你的服务器内存充裕,可以通过环境变量调大:

bash 复制代码
-e KK_JVM_OPTIONS="-Xms2g -Xmx4g -XX:MaxDirectMemorySize=1g -XX:+UseG1GC"

参数说明:

  • -Xms2g :初始堆内存 2GB
  • -Xmx4g :最大堆内存 4GB
  • -XX:MaxDirectMemorySize=1g :堆外内存上限
  • -XX:+UseG1GC :使用 G1 垃圾回收器,大内存场景下停顿更短

12.2 LibreOffice 转换队列

kkFileView 内部维护了一个文档转换的任务队列。如果并发预览请求多,转换排队会很明显。可以关注以下配置:

properties 复制代码
# 转换任务超时时间(毫秒),大文件建议调大
office.timeout=300000

# 预览接口超时
server.tomcat.connection-timeout=300000

12.3 文件缓存策略

对于频繁预览的文件(比如公司制度文档、产品手册),第一次转换后缓存在本地,后续请求直接走缓存,速度很快。缓存的有效期由 cache.expired.time 控制。

如果你的文件更新频率低,可以把缓存时间设长一些,减少重复转换的开销:

properties 复制代码
# 缓存 7 天
cache.expired.time=604800

12.4 磁盘 IO 优化

如果条件允许,把 /data/kkfileview/file 放到 SSD 上。文档转换过程中有大量的临时文件读写,机械硬盘会成为明显瓶颈。


十三、自定义镜像构建(进阶)

如果你需要把中文字体、自定义配置都打包进镜像,而不是每次启动都挂载一堆目录,可以自己构建一个镜像。这在多节点部署的时候特别有用------镜像里什么都有,拉下来直接跑。

13.1 编写 Dockerfile

dockerfile 复制代码
FROM keking/kkfileview:4.1.0

# 安装字体工具
RUN apt-get update && apt-get install -y fontconfig && rm -rf /var/lib/apt/lists/*

# 拷贝中文字体
COPY fonts/ /usr/share/fonts/chinese/

# 刷新字体缓存
RUN fc-cache -fv

# 拷贝自定义配置文件(如果需要覆盖默认配置)
# COPY config/application.properties /opt/kkFileView-4.1.0/config/application.properties

EXPOSE 8012

13.2 构建镜像

bash 复制代码
cd /data/kkfileview
docker build -t my-kkfileview:4.1.0 .

13.3 使用自定义镜像启动

bash 复制代码
docker run -d \
  --name kkfileview \
  -p 8012:8012 \
  -v /data/kkfileview/file:/opt/kkFileView-4.1.0/file \
  -v /data/kkfileview/logs:/opt/kkFileView-4.1.0/log \
  --restart=always \
  my-kkfileview:4.1.0

字体已经内置在镜像里了,不用再额外挂载。


十四、日常运维命令速查

把常用的操作整理在这里,方便日常查阅。

14.1 容器生命周期管理

bash 复制代码
# 查看运行状态
docker ps -a | grep kkfileview

# 查看容器资源占用(CPU、内存实时数据)
docker stats kkfileview --no-stream

# 进入容器排查问题
docker exec -it kkfileview bash

# 重启
docker restart kkfileview

# 停止
docker stop kkfileview

# 启动已停止的容器
docker start kkfileview

# 删除容器(数据卷不受影响)
docker stop kkfileview && docker rm kkfileview

# 查看容器详细信息(IP、挂载、环境变量等)
docker inspect kkfileview

14.2 日志查看

bash 复制代码
# 实时查看日志
docker logs -f kkfileview

# 查看最近 200 行
docker logs --tail 200 kkfileview

# 查看最近 1 小时的日志
docker logs --since 1h kkfileview

14.3 镜像管理

bash 复制代码
# 查看本地镜像
docker images | grep kkfileview

# 拉取新版本
docker pull keking/kkfileview:4.4.0

# 删除旧镜像
docker rmi keking/kkfileview:4.1.0

14.4 版本升级

bash 复制代码
# 1. 停止并删除旧容器
docker stop kkfileview && docker rm kkfileview

# 2. 拉取新镜像
docker pull keking/kkfileview:4.4.0

# 3. 用新镜像重新启动(注意版本号对应的路径可能变了)
docker run -d \
  --name kkfileview \
  -p 8012:8012 \
  -v /data/kkfileview/config/application.properties:/opt/kkFileView-4.4.0/config/application.properties \
  -v /data/kkfileview/file:/opt/kkFileView-4.4.0/file \
  -v /data/kkfileview/fonts:/usr/share/fonts/chinese \
  --restart=always \
  keking/kkfileview:4.4.0

升级前一定要看清楚新版本的容器内路径是否有变化,以及配置文件是否有新增/废弃的字段。


十五、常见问题排查

15.1 容器启动后立刻退出

bash 复制代码
# 先看退出原因
docker ps -a | grep kkfileview    # 看 STATUS 列
docker logs kkfileview            # 看报错信息

常见原因:

  • 端口被占用:netstat -tlnp | grep 8012 检查一下
  • 内存不够:free -h 看看宿主机剩余内存
  • 配置文件路径写错了:仔细核对 -v 挂载的路径

15.2 预览中文文档出现方块/乱码

这是字体问题,回到第九节,确认:

  1. 字体文件确实放到了正确的目录
  2. 容器内执行了 fc-cache -fv
  3. 重启了容器

15.3 预览大文件超时

  • 调大 office.timeout 的值
  • 调大 Nginx 的 proxy_read_timeout
  • 检查服务器内存是否充足
  • 考虑把 cache.expired.time 设长,让转换结果缓存住

15.4 预览接口返回 500

先看日志:

bash 复制代码
docker logs --tail 100 kkfileview

常见报错:

  • OfficeException: Could not open document :LibreOffice 进程挂了,重启容器一般能解决
  • FileNotFoundException :文件 URL 不可达,检查业务系统传过来的 URL 是否正确
  • OutOfMemoryError :内存不够,加大 JVM 堆或者加服务器内存

15.5 磁盘空间被缓存撑满

bash 复制代码
# 查看缓存目录大小
du -sh /data/kkfileview/file

# 手动清理
find /data/kkfileview/file -type f -mtime +3 -delete

十六、对接业务系统

部署完成后,你的业务系统怎么调用呢?很简单,拼一个 URL 就行。

16.1 预览接口格式

ini 复制代码
http://你的服务器地址:8012/onlinePreview?url={Base64编码的文件URL}

比如你的文件地址是 https://oss.yourdomain.com/files/contract.docx,做 Base64 编码后:

ini 复制代码
aHR0cHM6Ly9vc3MueW91cmRvbWFpbi5jb20vZmlsZXMvY29udHJhY3QuZG9jeA==

最终预览链接:

ini 复制代码
http://preview.yourdomain.com/onlinePreview?url=aHR0cHM6Ly9vc3MueW91cmRvbWFpbi5jb20vZmlsZXMvY29udHJhY3QuZG9jeA==

16.2 前端调用示例

javascript 复制代码
// 假设你有一个文件的下载链接
const fileUrl = 'https://oss.yourdomain.com/files/contract.docx';

// Base64 编码
const encodedUrl = btoa(fileUrl);

// 拼接预览地址
const previewUrl = `http://preview.yourdomain.com/onlinePreview?url=${encodeURIComponent(encodedUrl)}`;

// 打开预览
window.open(previewUrl);

16.3 Java 后端生成预览链接

java 复制代码
import java.util.Base64;
import java.net.URLEncoder;

public class KKFileViewUtil {
    
    private static final String KK_BASE_URL = "http://preview.yourdomain.com";
    
    public static String getPreviewUrl(String fileUrl) {
        String encoded = Base64.getEncoder().encodeToString(fileUrl.getBytes());
        return KK_BASE_URL + "/onlinePreview?url=" + URLEncoder.encode(encoded, "UTF-8");
    }
}

十七、监控与告警建议

生产环境跑起来之后,不能就不管了。建议至少做以下几件事:

17.1 容器健康检查

前面 docker-compose.yml 里已经配了 healthcheck,Docker 会自动检测容器健康状态。你也可以用脚本定期检测:

bash 复制代码
#!/bin/bash
STATUS=$(docker inspect --format='{{.State.Health.Status}}' kkfileview 2>/dev/null)
if [ "$STATUS" != "healthy" ]; then
    echo "[$(date)] kkFileView 状态异常: $STATUS" >> /data/kkfileview/logs/alert.log
    docker restart kkfileview
fi

17.2 磁盘监控

bash 复制代码
# 检查 /data 分区使用率
USAGE=$(df -h /data | awk 'NR==2 {print $5}' | sed 's/%//')
if [ "$USAGE" -gt 85 ]; then
    echo "[$(date)] 磁盘使用率 ${USAGE}%,请及时清理缓存" >> /data/kkfileview/logs/alert.log
fi

17.3 日志轮转

Docker 的 json-file 日志驱动前面已经配了大小限制(100MB × 3 个文件),一般不会撑爆磁盘。但应用日志如果也写文件,建议用 logrotate 管理。


十八、完整的一键部署脚本

最后,把整个流程串起来,写一个可以直接执行的脚本。你把它保存为 deploy_kkfileview.sh,给执行权限,一条命令搞定:

bash 复制代码
#!/bin/bash
set -e

echo "=========================================="
echo "  kkFileView Docker 一键部署脚本"
echo "=========================================="

# ---- 1. 安装 Docker ----
if ! command -v docker &> /dev/null; then
    echo "[1/7] 安装 Docker..."
    curl -fsSL https://get.docker.com | sh
    systemctl start docker
    systemctl enable docker
    usermod -aG docker $USER
    echo "Docker 安装完成。注意:需要重新登录终端才能免 sudo 使用 docker。"
else
    echo "[1/7] Docker 已安装,跳过。"
fi

# ---- 2. 创建目录结构 ----
echo "[2/7] 创建目录结构..."
mkdir -p /data/kkfileview/{config,file,logs,fonts}

# ---- 3. 下载字体包 ----
echo "[3/7] 下载中文字体包..."
if [ ! -f /data/kkfileview/fonts/simsun.ttc ]; then
    wget -q http://kkfileview.keking.cn/fonts.zip -O /tmp/fonts.zip
    unzip -o /tmp/fonts.zip -d /data/kkfileview/fonts/
    rm -f /tmp/fonts.zip
    echo "字体下载完成。"
else
    echo "字体已存在,跳过。"
fi

# ---- 4. 拉取镜像 ----
echo "[4/7] 拉取 kkFileView 镜像..."
docker pull keking/kkfileview:4.1.0

# ---- 5. 提取默认配置 ----
echo "[5/7] 提取默认配置文件..."
if [ ! -f /data/kkfileview/config/application.properties ]; then
    docker run -d --name kkfileview-temp keking/kkfileview:4.1.0
    sleep 10
    docker cp kkfileview-temp:/opt/kkFileView-4.1.0/config/application.properties \
        /data/kkfileview/config/application.properties
    docker stop kkfileview-temp && docker rm kkfileview-temp
    echo "配置文件已提取到 /data/kkfileview/config/"
else
    echo "配置文件已存在,跳过。"
fi

# ---- 6. 启动容器 ----
echo "[6/7] 启动 kkFileView 容器..."
docker run -d \
  --name kkfileview \
  -p 8012:8012 \
  -v /data/kkfileview/config/application.properties:/opt/kkFileView-4.1.0/config/application.properties \
  -v /data/kkfileview/file:/opt/kkFileView-4.1.0/file \
  -v /data/kkfileview/logs:/opt/kkFileView-4.1.0/log \
  -v /data/kkfileview/fonts:/usr/share/fonts/chinese \
  -e KK_JVM_OPTIONS="-Xms1g -Xmx2g -XX:MaxDirectMemorySize=1g" \
  --memory=4g \
  --restart=always \
  keking/kkfileview:4.1.0

# ---- 7. 刷新字体缓存 ----
echo "[7/7] 刷新容器内字体缓存..."
sleep 15
docker exec kkfileview fc-cache -fv > /dev/null 2>&1 || true
docker restart kkfileview

echo ""
echo "=========================================="
echo "  部署完成!"
echo "  访问地址: http://$(hostname -I | awk '{print $1}'):8012"
echo "  配置文件: /data/kkfileview/config/application.properties"
echo "  缓存目录: /data/kkfileview/file"
echo "  日志目录: /data/kkfileview/logs"
echo "=========================================="

使用方式:

bash 复制代码
chmod +x deploy_kkfileview.sh
sudo ./deploy_kkfileview.sh

十九、最后的几点经验

写到这里,技术层面的东西基本都覆盖了。最后分享几个我在实际项目中总结出来的经验,都是踩坑之后才意识到的:

第一,别在生产环境用 latest 标签。 一定要锁定具体版本号。kkFileView 的版本之间偶尔会有不兼容的变更,latest 指向哪个版本你控制不了,哪天自动拉了个新版本下来,配置路径变了,服务就挂了。

第二,字体问题要在部署阶段就解决好,不要等到上线了用户反馈"文件乱码"再去补。 把字体包直接打进自定义镜像里,一劳永逸。

第三,缓存目录一定要挂载到宿主机。 如果不挂载,容器一删缓存全没了,所有文件都要重新转换,大文件转换一次可能就是几十秒,用户体验会很差。

第四,做好容量规划。 我见过一个客户的缓存目录半年涨了 80GB,最后磁盘满了整个服务挂掉。定期清理 + 磁盘告警,这两个动作不能省。

第五,如果你的文件存储用的是 OSS(阿里云 OSS、腾讯 COS、MinIO 等),确保文件下载链接有过期时间或者鉴权机制。 kkFileView 是通过 URL 去下载文件的,如果你的文件链接是永久公开且无需鉴权的,存在被爬取的风险。


附录:官方文档与资源地址

部署和运维过程中难免会遇到本文未覆盖到的边缘场景或新版本特性变更,建议收藏以下官方资源作为补充参考:

提示:官方文档更新频率不算高,部分配置项在新版本中可能有调整。遇到文档与实际表现不一致时,优先以 GitHub 仓库的 README 和 Issues 区为准,那里通常有最新的解决方案和社区反馈。

相关推荐
OpenCloudOS18 分钟前
高危|Linux 内核 XFS reflink 本地提权漏洞修复指南
linux·网络·安全
小HANN35 分钟前
保姆级实战:CentOS7 搭建 LAMP 环境部署 WordPress 个人博客
linux·运维·服务器·经验分享
奈斯先生Vector1 小时前
从“能调用”到“可替换”:Coze 多模型 API 编排层设计指南
linux·运维·人工智能·ubuntu·平面·ios
AAA代码批发商1 小时前
Days 32 Linux 多线程:线程分离属性、多进程 vs 多线程、线程同步互斥锁、信号量
linux·笔记
李少兄1 小时前
Linux 服务器从零部署 kkFileView 完全指南(Docker 方案)
linux·服务器·docker
小张同学a.1 小时前
OpenStack 私有云实战 3—— Neutron 网络服务与 Dashboard 控制台部署
linux·运维·服务器·openstack
DogDaoDao1 小时前
HarmonyOS 深度解析:从微内核到 ArkTS 工程实战
android·linux·ios·华为·程序员·harmonyos·harmonyos next
从零开始的嵌入式之旅2 小时前
day31
linux·c语言·经验分享·笔记·嵌入式硬件
Horn Still Sounds2 小时前
Linux系统编程进阶:进程回收、程序替换与多线程并发模型
linux·运维·服务器·c语言