ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

CVAT部署实战:Docker Compose搭建数据标注平台完整指南

CVAT部署实战:Docker Compose搭建数据标注平台完整指南

CVAT(Computer Vision Annotation Tool)在计算机视觉项目里有多重要,做过数据标注的应该都懂。从目标检测的矩形框、多边形分割,到关键点标注、视频跟踪,一个团队要管理成千上万张图的标注任务,用公共的标注平台根本不现实,数据安全、格式定制、标注规范全都卡脖子。自己部署一套CVAT,是目前开源方案里最稳妥的做法。这篇就完整走一遍安装流程,从环境准备、Docker部署、账号创建到存储配置和常见坑,给一套可以直接照着抄的实操记录。

适合谁看?正在搭数据标注平台的算法工程师、做数据中台的开发,以及想从LabelImg这类单机工具切换到团队协作标注的个人或小团队。我默认你有一台Linux服务器,并且对Docker有最基本的概念——知道镜像、容器大概是干什么的就够了,不需要资深。

先说清楚一件事:CVAT官方推荐的部署方式就是Docker Compose,没有第二种更省心的选择。下面的一切都基于这个方案展开。

1. 安装CVAT前的核心认知与方案选型

1.1 CVAT到底能干什么

很多人以为CVAT只是一个画框工具,实际上它是一整套标注管理平台。它解决的不只是“在图片上画一个框”,而是标注任务的完整流程:创建任务、分配标注员、设置标注规范、质检审核、数据导出、团队权限管理。

单纯画框的工具到处都是,但带项目管理能力和多人协作能力的开源工具,CVAT基本是唯一的选择。它的核心功能包括:

  • 支持图像分类、目标检测(矩形框)、多边形/多边形分割、关键点、骨架、视频目标跟踪等常见标注类型
  • 内置自动标注插件,可以通过模型推理结果做预标注,人工只需要微调
  • 支持数据集导入导出,格式覆盖COCO、PASCAL VOC、YOLO、TFRecord等主流格式
  • 多人协作和角色权限划分——管理员、标注员、审核员各司其职
  • 基于Web的界面,标注员不需要安装任何客户端,浏览器打开就能开工

这些功能组合起来,它就不再是一个“小工具”,而是一个数据生产系统。安装部署的复杂度也随之上升,不是双击一个exe就能搞定的事,但对得起它带来的价值。

1.2 为什么首选Docker Compose部署

CVAT官方提供了几种部署路径:Docker Compose、Kubernetes、源码编译,以及一个针对单机场景的简化安装脚本。对绝大多数团队来说,Docker Compose是平衡复杂度与可维护性的最佳解。

为什么不推荐源码编译?CVAT后端依赖的组件非常多,PostgreSQL、Redis、消息队列、模型推理服务、多个Worker进程,手动一个个装好再配置联动,新手至少折腾一整天,而且后续升级非常痛苦。Docker Compose把这些全部编排在几个配置文件里,一条命令拉起全部依赖,升级时拉新镜像就行。

为什么不推荐Kubernetes?除非你的标注规模大到需要跨多台机器弹性伸缩,否则Kubernetes的运维成本远超收益。绝大多数团队的标注任务,一台配置稍好的服务器就绰绰有余,用K8s是在给自己找麻烦。

Docker Compose方案还有一个杀手级优势:它把每个服务拆成独立容器,某个组件崩了不会整个系统瘫掉,排查问题也方便——哪个容器挂了看哪个容器的日志就行。

提示:CVAT的Docker Compose部署方式设计得相对模块化,即使你后面想换存储、挂GPU推理服务,也只需要改配置重启,不需要推倒重来。

2. 安装前的环境准备与依赖检查

2.1 硬件配置建议

CVAT本身不算吃资源,但它依赖的镜像服务和数据库会占不少内存。这里给一个基于实际体验的下限参考:

组件最低建议推荐配置
CPU4核8核及以上
内存8GB16GB
磁盘100GB500GB以上(标注数据非常占空间)
GPU不需要有NVIDIA GPU更好(用于模型辅助标注)

磁盘空间是很多人容易忽略的点。一个视频标注任务的媒体文件可能轻松到几十GB,如果还要跑自动标注,中间产物更占地方。建议给CVAT的数据目录单独挂一块大容量磁盘,不要和系统盘混在一起。

关于GPU,如果你只用CVAT做纯人工标注,CPU完全够用。但如果要用自动标注功能(Auto Annotation),需要接入一个模型服务,这时候GPU能大幅提升推理速度。没有GPU也能跑,只是速度让人着急。

2.2 操作系统与Docker安装

系统方面,主流Linux发行版都可以,我以Debian系为例说明。Windows下虽然有Docker Desktop,但跑CVAT会遇到很多文件权限和路径兼容问题,不建议在生产环境用Windows跑。

先确认系统里有没有装过Docker:

docker --version

如果提示找不到命令,按下面的流程装。要注意的是:新版本Docker把Compose集成成了插件,不需要单独装docker-compose。

# 安装依赖 apt update apt install -y ca-certificates curl gnupg # 添加Docker官方仓库 install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg chmod a+r /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" | tee /etc/apt/sources.list.d/docker.list > /dev/null # 安装Docker Engine和Compose插件 apt update apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

装完验证一下:

docker --version docker compose version

看到版本号输出了,说明环境OK。Docker服务默认不会随开机自启,需要手动设置:

systemctl enable docker systemctl start docker

这一步走完之后,建议顺手配一下镜像加速器。不是必须的,但如果不配,在国内网络环境下拉取镜像会非常痛苦,CVAT相关的镜像一共好几个GB,慢的时候等到怀疑人生。配置方法是在/etc/docker/daemon.json里加registry-mirrors配置,然后重启Docker。

注意:镜像加速与任何网络代理无关,这是Docker官方提供的镜像分发机制,安全合规,放心配置。

3. 完整安装流程详解

3.1 获取CVAT源码与选择版本

CVAT的部署配置都放在Git仓库里,我们需要把仓库拉下来,用里面的docker-compose配置文件作为基础。

git clone https://github.com/opencv/cvat.git cd cvat

仓库默认在最新开发分支上。开发分支可能有未测试完的新功能,生产环境建议切换到最新的稳定发布版本。

# 查看所有tag,挑最新的稳定版本号 git tag --list git checkout v2.x.x

实操心得:我踩过一次用开发分支部署的坑——某个依赖服务版本升级导致后端偶发报错,排查了一天才发现是分支版本的问题。换成稳定版之后一切正常。所以,生产环境一定用稳定版,别贪新功能。

3.2 配置环境变量文件

CVAT用根目录下的.env文件管理关键配置。仓库里提供了一个模板,复制一份出来改:

cp .env.example .env

最需要关心的是下面几个变量:

# 部署后通过哪个域名或IP访问,默认localhost # 如果要用IP访问,改成服务器的IP地址 CVAT_HOST=localhost # 数据库连接配置,一般情况下保持默认即可 POSTGRES_HOST=* POSTGRES_DBNAME=cvat POSTGRES_USER=cvat POSTGRES_PASSWORD=请改成强密码 # 初始管理员账号的邮箱,创建超级用户时会用到 DJANGO_SUPERUSER_EMAIL=admin@example.com # 初始管理员密码 DJANGO_SUPERUSER_PASSWORD=请改成强密码

CVAT_HOST这个变量容易踩坑。如果填了localhost,那只能在服务器本机通过浏览器访问;要让局域网内其他机器访问,必须改成服务器的内网IP,或者绑定一个域名。

数据库和后台管理员的密码,强烈建议改成强密码。CVAT可能暴露在办公网甚至公网上,弱密码等于把标注数据的大门敞开。

3.3 启动服务并确认初始化完成

真正拉起整个平台的命令只有一条:

docker compose up -d

首次执行时,Docker会拉取所有依赖镜像并构建UI镜像,耗时取决于网络状况,通常十几分钟到半小时不等。执行完后查看容器状态:

docker compose ps

正常情况下你会看到一堆状态为Up的容器,包括:

  • cvat_server:后端API服务
  • cvat_ui:前端界面
  • cvat_db:PostgreSQL数据库
  • cvat_redis:缓存与消息队列
  • cvat_worker_default:标注任务Worker
  • cvat_worker_webhooks:Webhooks推送Worker(如果启用了)

容器状态都正常不代表系统已经就绪。数据库初始化、数据迁移、默认数据写入这些步骤是在首次启动时完成的,需要额外等待一段时间。验证就绪的方法是看后端日志:

docker compose logs -f cvat_server

日志里连续输出迁移操作,最后出现启动成功的标志(比如Starting ASGI/Channels development server或者类似的监听提示),说明服务已经可以用了。

注意:如果修改过.env文件里的密码或host配置,必须重建容器才能生效,执行docker compose up -d --force-recreate。

3.4 创建管理员账号

在.env里配置了DJANGO_SUPERUSER相关变量后,首次启动时CVAT会自动创建超级用户。但官方提供的自动化创建逻辑在部分版本里可能依赖一些附加条件,如果登录时发现账号不存在,可以手动创建:

docker compose exec -it cvat_server python manage.py createsuperuser

按提示输入用户名、邮箱、密码。创建完成后,浏览器访问http://你的服务器IP:8080,就能看到登录页面,用刚创建的账号登录。

登录成功后进入主页,看到左侧的“Tasks”栏就说明整个系统已经跑通了。接下来可以试着创建一个项目、建一个任务、上传一张图片,完整走一遍标注流程,确认功能都正常。

这一步的验证不可跳过。很多情况下服务看似起来了,但媒体上传、标注保存等功能可能因为数据库初始化不完整而报错,提前走一遍流程能尽早发现问题。

4. 存储方案配置与调优

4.1 本地存储的默认方案

CVAT默认把所有上传的图片、视频、标注结果都存放在Docker卷(volume)里。好处是省事,不需要额外配置;坏处是数据跟Docker生命周期绑定,如果执行docker compose down时带上了-v参数,所有数据会被删得干干净净。

我见过不止一次因为手滑执行docker compose down -v然后数据全没了的惨案。数据卷默认在/var/lib/docker/volumes/下面,目录名类似cvat_cvat_data。想备份的话,直接把对应卷目录打包就行。

4.2 迁移到独立数据目录

标注数据大且增长快,强烈建议把存储挂载到一个专门的大容量磁盘目录,而不是依赖默认的Docker卷。修改docker-compose.yml中相关服务的卷映射:

volumes: cvat_data: driver: local driver_opts: type: none o: bind device: /data/cvat_data # 换成你的数据盘目录

这样数据就直接落在宿主机目录里,备份、迁移、扩容都方便很多。修改完成后同样需要重建容器:

docker compose up -d --force-recreate

实操心得:如果是在云服务器上部署,建议把数据目录放在独立的云硬盘上。万一实例需要重装系统,数据盘可以拆下来挂到新实例上,直接续命,不需要重新上传几百GB的标注数据。

4.3 对象存储扩展

当数据规模再上一个台阶,本地磁盘就不够看了。CVAT支持接入S3兼容的对象存储,比如MinIO或者各大云厂商的对象存储服务。

启用方式是在.env里配置相关变量:

# 打开对象存储开关 CVAT_S3_ENABLED=True # 配置连接信息 CVAT_S3_ENDPOINT_URL=http://minio.example.com CVAT_S3_ACCESS_KEY_ID=你的AccessKey CVAT_S3_SECRET_ACCESS_KEY=你的SecretKey CVAT_S3_BUCKET_NAME=cvat-bucket

这里有一段设计细节值得说一下:CVAT上传媒体文件时,并不是直接一个文件就传到对象存储,而是会先写入本地临时目录,再由Worker异步上传。这样做是为了避免对象存储的网络波动影响标注界面的响应速度。

对象存储方案适合数据量在TB级别以上、或者有多套服务共享同一份数据存储的场景。但对数据安全和隐私要求高的场景,慎用公共对象存储,注意数据在哪里存放。

4.4 磁盘空间管理经验

跑了一段时间后,最烦人的问题就是磁盘满了。CVAT的存储消耗主要有三块:上传的原始媒体文件、标注任务导出文件、Docker镜像和日志。

处理建议:

  • 定期执行docker system prune -a清理无用镜像,但注意这会同时清理掉未运行的容器,操作前确认没有需要保留的东西
  • 查看各容器日志占用,/var/lib/docker/containers/<容器ID>/下的json.log文件可能非常大,需要合理控制日志量
  • 标注完成且已导出的任务,及时在Tasks列表里删除,释放媒体文件空间;如果不想删任务数据,可以先把数据导出到NAS等长期存储再删

磁盘监控一定要提前做,不要等到满了才处理。写一个简单的磁盘告警脚本,超过阈值就通知,比任何优化技巧都管用。

5. 常见问题与排查技巧实录

5.1 容器起不来或一直重启

先看状态和日志:

docker compose ps docker compose logs --tail=100 cvat_server

常见的三类原因:

第一是端口被占用。CVAT默认用8080端口,如果服务器上已经有其他服务占了这个端口,容器会启动失败。改.env里的端口映射:

# 把8080改成你想要的端口 CVAT_PORT=8090

第二是内存不足。Docker Compose拉起的容器加起来至少需要4-5GB内存,小内存服务器上如果开了MySQL、Redis之类的其他服务,可能导致容器被OOM杀掉。用free -h看内存占用,用docker stats看各容器的实际内存使用,确定瓶颈后扩容或减少其他服务的负载。

第三是数据库没有初始化完成,前端访问接口时报DB连接错误。这时不要急着重启所有容器,多等几分钟,关注cvat_db容器的日志,等数据库初始化彻底结束再说。如果还是不行,可以考虑重置数据库卷再重新初始化(注意:这个操作会清空已有数据)。

5.2 浏览器无法访问界面

服务都正常运行但浏览器打不开,常见原因有:

  • CVAT_HOST配置的是localhost,但你不是在服务器本机访问。改成服务器IP后docker compose up -d --force-recreate重建
  • 服务器的防火墙没放行对应端口。检查iptables/firewalld/安全组里是否放通了8080等端口
  • 访问的是HTTPS地址,但CVAT默认走HTTP。确认URL里用的是http://而不是https://

这里有一个体验上的坑:如果是通过IP访问,浏览器可能会提示不安全或无法访问。CVAT默认以HTTP方式提供服务,如果确实需要HTTPS,需要配置反代(比如你用的Nginx)来终结TLS,并在CVAT端配置信任代理。

5.3 上传大文件超时或失败

标注数据集经常是大尺寸视频,动辄几个GB,上传时容易报超时。这个问题主要出在CVAT后端的请求体大小限制和反向代理配置上,如果你没有部署任何反向代理,那就限制于后端配置本身。

调整cvat_server容器里的DATA_UPLOAD_MAX_MEMORY_SIZE和FILE_UPLOAD_MAX_MEMORY_SIZE配置,或者在前端和后端之间加一层Nginx并调大client_max_body_size参数:

client_max_body_size 10g; proxy_read_timeout 600s; proxy_send_timeout 600s;

还要注意,上传视频时CVAT会把视频抽帧生成预览图,这个过程比较吃CPU。大视频文件上传后可能要等一段时间才能在界面上看到预览,不要误以为是卡死。

5.4 忘了管理员密码

这个简单,直接在后端容器里重置:

docker compose exec -it cvat_server python manage.py changepassword admin

按提示输入新密码即可。如果连管理员用户名都忘了,可以在PostgreSQL里查:

docker compose exec -it cvat_db psql -U cvat -d cvat -c "SELECT username, is_superuser FROM auth_user WHERE is_superuser=true;"

注意:用changerpassword重置的密码立即生效,不需要重启任何容器,刷新浏览器重新登录就行。

5.5 升级版本后页面白屏

CVAT升级很简单:拉新代码、切新tag、docker compose up -d。但偶尔会遇到前端白屏、控制台报错的情况。最常见的原因是浏览器缓存了旧版本的JS文件。

处理方式:强制刷新(Ctrl+Shift+R)或者浏览器无痕窗口打开,一般就能解决。如果还不行,查一下前端容器和后端容器的版本是否匹配——两个镜像版本不一致会导致API调用失败。

如果升级前改了默认的UI配置,升级后配置被重置也会导致页面异常,需要对照升级说明重新配置。

6. 部署后的性能调优与运维建议

6.1 合理调整Worker数量

CVAT的默认配置是1个默认Worker处理所有标注任务。当团队同时标注的任务较多时,单个Worker会成为瓶颈,表现为任务排队时间长、自动标注处理慢。

调整方式:修改docker-compose.yml里worker的服务副本数:

cvat_worker_default: deploy: replicas: 3

或者用docker compose up -d --scale cvat_worker_default=3临时扩容。

这里有个权衡:Worker越多,内存和CPU消耗越大,数据库连接数也会增加。建议根据团队实际并行标注任务数来调整,一般2-4个Worker对中小团队足够了。

6.2 自动标注功能接入

CVAT的自动标注(Auto Annotation)功能是它区别于其他标注工具的亮点。它支持通过API接入外部模型,模型推理结果自动填充标注框、多边形或关键点。

具体接入方式:在docker-compose.yml中启用cvat_auto_annotation服务,按官方文档配置模型服务器地址和推理接口。模型可以用现成的检测模型,也可以是你自己训练的私有模型,通过HTTP服务暴露推理接口。

这是CVAT后续扩展性最强的地方——标注平台不只是人工标注工具,还能成为模型迭代闭环的一环:用模型预标注,人工修正,导出数据再训练,模型越用越准。

6.3 备份策略

最后说备份,这个每次都必须强调。CVAT的数据核心是数据库,媒体文件和标注结果实际可以重建,但任务元数据、标注规范的数据库一旦丢了,恢复成本极高。

最低限度的备份方案:

# 备份数据库 docker compose exec cvat_db pg_dump -U cvat -d cvat > /backup/cvat_db_$(date +%Y%m%d).sql # 备份媒体数据目录(根据你挂载的路径调整) tar -czf /backup/cvat_data_$(date +%Y%m%d).tar.gz /data/cvat_data

可以用crontab写定时任务,每日备份数据库,每周备份媒体文件。恢复流程:先重建空环境,再恢复数据库dump,再把媒体数据解压到对应目录,就能回到备份时的状态。

我在实际运维中发现,很多团队的数据丢失都不是因为硬件故障,而是升级失败后误操作删除了数据卷。所以升级前务必先备份,这条没有例外。

CVAT部署完成只是第一步,真正考验人的是日常运维和数据管理。把这套环境跑起来之后,建议花点时间摸一遍任务创建、数据集导出、模型辅助标注这几个核心流程,把团队的实际标注规范配置进去。后面不管是几十万张图的检测项目,还是视频跟踪的时序标注,都能稳稳接住。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进