Vikunja 2.7.1 Docker Compose 部署指南

基于 Docker Compose 一键部署 Vikunja 2.7.1 + PostgreSQL 18:compose 文件逐项详解、启动验证、数据持久化验证、postgres:18 挂载点变更排障实录;篇末附 Kubernetes Helm Chart 部署形态溯源(k8s 集群实测见后续 K1 批次)。

VikunjaVikunjaDockerDocker Compose自托管任务管理2026/10/25

Vikunja 2.7.1 Docker Compose 部署指南

Vikunja 官方在 Docker Hub 维护 vikunja/vikunja 镜像(API 后端与前端打包在同一镜像内),配合一个数据库容器即可用 Docker Compose 一键拉起完整服务。本文以 v2.7.1 + PostgreSQL 18 为例,实测从编写 compose 文件、启动验证、数据持久化验证到排障的完整过程,并在篇末附 Kubernetes(Helm)部署形态说明。文中命令与回显均来自真实环境实测。

一、环境信息

项目值
操作系统Ubuntu 22.04.5 LTS(x86_64)
Docker 版本Server 29.9.2
Docker Compose 版本v5.6.1
Vikunja 镜像vikunja/vikunja:2.7.1
数据库镜像postgres:18
服务器 IP192.168.146.131
对外端口8134(映射容器内 3456)
Compose 项目名vikunja-2.7.1-stack
演示账号admin / q1w2e3r4

确认 Docker 与 Compose 就绪:

docker version --format 'Server: {{.Server.Version}}'
docker compose version

回显:

Server: 29.9.2
Docker Compose version v5.6.1

二、准备目录与网络

创建工作目录:

mkdir -p /opt/vikunja-stack && cd /opt/vikunja-stack

Vikunja 容器与数据库容器需要互通,创建独立的 bridge 网络(实验环境使用专属网段 10.89.63.0/24,读者可按需调整或省略 --subnet 使用默认分配):

docker network create --subnet 10.89.63.0/24 vikunja-net

三、编写 docker-compose.yml

创建 docker-compose.yml,内容如下:

name: vikunja-2.7.1-stack

services:
  vikunja:
    image: vikunja/vikunja:2.7.1
    container_name: vikunja-2.7.1-web
    environment:
      VIKUNJA_SERVICE_PUBLICURL: http://192.168.146.131:8134/
      VIKUNJA_SERVICE_SECRET: s9vikunjasecret0123456789abcdef
      VIKUNJA_DATABASE_TYPE: postgres
      VIKUNJA_DATABASE_HOST: db
      VIKUNJA_DATABASE_PORT: 5432
      VIKUNJA_DATABASE_USER: vikunja
      VIKUNJA_DATABASE_PASSWORD: q1w2e3r4
      VIKUNJA_DATABASE_DATABASE: vikunja
      VIKUNJA_DATABASE_SSLMODE: disable
      VIKUNJA_SERVICE_TIMEZONE: Asia/Shanghai
    ports:
      - "8134:3456"
    volumes:
      - ./files:/app/vikunja/files
    depends_on:
      db:
        condition: service_healthy
    restart: unless-stopped
    networks:
      - vikunja-net

  db:
    image: postgres:18
    container_name: vikunja-2.7.1-db
    environment:
      POSTGRES_USER: vikunja
      POSTGRES_PASSWORD: q1w2e3r4
      POSTGRES_DB: vikunja
    volumes:
      - ./db:/var/lib/postgresql
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -h localhost -U $$POSTGRES_USER"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 15s
    networks:
      - vikunja-net

networks:
  vikunja-net:
    external: true

关键配置说明:

  • name: vikunja-2.7.1-stack:显式指定 Compose 项目名,资源前缀统一,避免随目录名变化。
  • VIKUNJA_SERVICE_PUBLICURL:Vikunja 全部配置项都支持以 VIKUNJA_ 前缀的环境变量覆盖(层级用下划线拼接)。publicurl 为必填(v2 默认开启 CORS),值为用户实际访问地址,末尾斜杠不可省略。
  • VIKUNJA_SERVICE_SECRET:JWT 签名密钥,不配置则每次重启随机生成、所有已签发令牌失效,生产必须显式固定。
  • depends_on.condition: service_healthy:配合 db 服务的 healthcheck,保证 PostgreSQL 真正可连接后才启动 Vikunja,避免启动期数据库连接失败。
  • db 的挂载点为 ./db:/var/lib/postgresql:不是 /var/lib/postgresql/data,这是 postgres:18 镜像的重大变更,详见第五节排障实录。
  • restart: unless-stopped:宿主机重启后服务自动恢复。

四、启动与验证

启动整个栈:

docker compose up -d

回显:

 Container vikunja-2.7.1-db Creating
 Container vikunja-2.7.1-db Created
 Container vikunja-2.7.1-web Creating
 Container vikunja-2.7.1-web Created
 Container vikunja-2.7.1-db Starting
 Container vikunja-2.7.1-db Started
 Container vikunja-2.7.1-db Waiting
 Container vikunja-2.7.1-db Healthy
 Container vikunja-2.7.1-web Starting
 Container vikunja-2.7.1-web Started

可以看到 depends_on + healthcheck 的效果:web 容器等到 db 进入 Healthy 后才启动。查看运行状态:

docker compose ps

回显:

NAME                IMAGE                   COMMAND                  SERVICE   CREATED         STATUS                    PORTS
vikunja-2.7.1-db    postgres:18             "docker-entrypoint.s…"   db        22 minutes ago  Up 22 minutes (healthy)   5432/tcp
vikunja-2.7.1-web   vikunja/vikunja:2.7.1   "/app/vikunja/vikunja"   vikunja   22 minutes ago  Up 22 minutes             0.0.0.0:8134->3456/tcp, [::]:8134->3456/tcp

验证 API:

curl -s http://localhost:8134/api/v1/info | head -c 160

回显(截取):

{"version":"v2.7.1","frontend_url":"http://192.168.146.131:8134/","motd":"","link_sharing_enabled":true,"max_file_size":"20MB","max_items_per_page":50,"availabl

验证前端页面可达:

curl -s -o /dev/null -w "HTTP %{http_code}\n" http://localhost:8134/

回显:

HTTP 200

五、排障实录:postgres:18 挂载点变更

初次编写 compose 文件时,沿用了 postgres 镜像沿用多年的经典写法 ./db:/var/lib/postgresql/data,结果 db 容器启动即退出(exit code 1),日志如下:

docker logs vikunja-2.7.1-db

回显:

Error: in 18+, these Docker images are configured to store database data in a
       format which is compatible with "pg_ctlcluster" (specifically, using
       major-version-specific directory names).  This better reflects how
       PostgreSQL itself works, and how upgrades are to be performed.

       See also https://github.com/docker-library/postgres/pull/1259

       Counter to that, there appears to be PostgreSQL data in:
         /var/lib/postgresql/data (unused mount/volume)

       This is usually the result of upgrading the Docker image without
       upgrading the underlying database using "pg_upgrade" (which requires both
       versions).

       The suggested container configuration for 18+ is to place a single mount
       at /var/lib/postgresql which will then place PostgreSQL data in a
       subdirectory, allowing usage of "pg_upgrade --link" without mount point
       boundary issues.

原因:从 postgres:18 起,官方镜像改用与 pg_ctlcluster 兼容的目录布局,数据实际存放在 /var/lib/postgresql/<主版本号>/docker/ 之下,以便未来用 pg_upgrade --link 做原地大版本升级。因此 18+ 版本要求把挂载点放在 /var/lib/postgresql(父目录),而不是旧的 /var/lib/postgresql/data。

修复方法:将 db 服务的挂载改为 ./db:/var/lib/postgresql,重新 docker compose up -d 即可健康启动。Vikunja 官方文档的 compose 示例已同步采用该写法。如果读者选择 postgres:17 及更早版本,则仍可沿用 /var/lib/postgresql/data。

六、功能验证与数据持久化

6.1 注册与创建项目

注册演示账号并登录获取 token(过程与裸机安装一致,此处略去中间回显):

curl -s -X POST http://localhost:8134/api/v1/register \
  -H "Content-Type: application/json" \
  -d '{"username":"admin","password":"q1w2e3r4","email":"admin@quzuo.local"}'

创建项目:

TOKEN=<登录返回的 token>
curl -s -X PUT http://localhost:8134/api/v1/projects \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title":"Compose 验证项目"}'

回显(解析后):

项目ID: 2 | 标题: Compose 验证项目

6.2 数据持久化验证

compose 栈的数据持久化依赖三处 bind mount:db 的 ./db(数据库文件)与 web 的 ./files(任务附件)。执行整体停止再启动:

docker compose down
docker compose up -d

down 回显:

 Container vikunja-2.7.1-web Stopping
 Container vikunja-2.7.1-web Stopped
 Container vikunja-2.7.1-web Removing
 Container vikunja-2.7.1-web Removed
 Container vikunja-2.7.1-db Stopping
 Container vikunja-2.7.1-db Stopped
 Container vikunja-2.7.1-db Removing
 Container vikunja-2.7.1-db Removed

容器被删除重建后,重新登录并列出项目:

TOKEN=$(curl -s -X POST http://localhost:8134/api/v1/login -H "Content-Type: application/json" -d '{"username":"admin","password":"q1w2e3r4"}' | python3 -c "import sys,json;print(json.load(sys.stdin)['token'])")
curl -s "http://localhost:8134/api/v1/projects" -H "Authorization: Bearer $TOKEN"

回显(解析后):

项目ID: 1 | 标题: Inbox
项目ID: 2 | 标题: Compose 验证项目

容器删除重建后账号与项目数据完好,持久化验证通过。

七、常用运维命令

查看实时日志:

docker compose logs -f vikunja

进入数据库容器执行 SQL 备份:

docker compose exec db pg_dump -U vikunja vikunja > backup-$(date +%F).sql

升级镜像版本(修改 compose 中镜像 tag 后执行):

docker compose pull
docker compose up -d

完全卸载(保留 ./db 与 ./files 数据目录,如需彻底删除请手动清理):

docker compose down
docker network rm vikunja-net

八、Kubernetes 部署形态(附节)

Vikunja 官方维护 Helm Chart,可直接部署到 Kubernetes 集群。本节内容基于官方 Chart 与文档溯源整理(查询日期 2026-10-25),k8s 集群实测见后续 K1 批次,本节仅给出经溯源核实的部署指引。

Chart 基本信息:

项目值
Chart 名称vikunja
Chart 版本2.5.0
appVersion2.7.1
最低集群版本kubeVersion >= 1.19
依赖基于 bjw-s common library 1.5.1 构建
制品地址oci://ghcr.io/go-vikunja/helm-chart/vikunja

Chart 以 OCI 制品形式分发,不依赖传统 helm repo add,直接安装:

helm install vikunja oci://ghcr.io/go-vikunja/helm-chart/vikunja \
  --version 2.5.0 \
  --namespace vikunja --create-namespace

values.yaml 关键项(继承 bjw-s common library 的结构):

values 路径作用
vikunja.ingress.mainIngress 入口配置(主机名、TLS、注解)
configMaps.config.data.config.yml以 ConfigMap 形式注入 Vikunja 的 config.yml 内容
persistence.data附件与数据目录的 PVC 持久化声明
env / envFrom环境变量注入,可引用 Secret 存放数据库口令与 service.secret

典型的自定义 values 片段示例(溯源自官方 Chart 结构,供参考):

configMaps:
  config:
    data:
      config.yml: |
        service:
          publicurl: "https://vikunja.example.com/"
        database:
          type: postgres
          host: postgres-rw.database.svc
          user: vikunja
          database: vikunja
persistence:
  data:
    enabled: true
    size: 1Gi
vikunja:
  ingress:
    main:
      enabled: true
      hosts:
        - host: vikunja.example.com
          paths:
            - path: /

生产部署建议:数据库口令与 service.secret 通过 Secret + envFrom 注入,不要明文写入 values;数据库推荐集群外托管或独立的 PostgreSQL Operator;附件 PVC 与数据库需纳入备份策略。以上配置项的实际集群验证将在 K1 批次完成并单独成文。

九、参考链接