> ## Content Index
> Fetch the complete content index at: https://www.richarvin.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Docker一键部署Twenty CRM
- URL: https://www.richarvin.com/docker-yi-jian-bu-shu-twenty-crm/
- Published: 2026-06-04T06:58:56.000Z
- Updated: 2026-06-04T06:58:56.000Z
- Author: Richarvin
- Tags: Docker部署

💡

Twenty CRM 是一款面向现代化团队的开源客户关系管理（CRM）系统。它采用主流的 React + NestJS + PostgreSQL 技术栈构建，不仅拥有类似 Notion 的高颜值、现代化交互界面，更原生集成了对 AI 自动化（如 MCP 协议）的支持。

## 一、项目简介

---

# 项目简介

Twenty CRM 是一款面向现代化团队的开源客户关系管理（CRM）系统。它采用主流的 TypeScript/React技术栈，拥有类似Notion的高颜值交互界面。作为Salesforce的现代化开源替代方案，Twenty完美融合了AI时代的自动化需求（原生支持MCP协议与AI Agents集成）。项目支持完全的自托管（Self-Hosted）部署，旨在帮助企业彻底摆脱云端SaaS的厂商锁死，实现100% 的客户数据自主权。

# 技术生态优势

现代化全栈架构：前端基于React + Tailwind CSS确保极致的响应体验，后端采用NestJS + Node.js提供稳健的API服务，底层数据由PostgreSQL与Redis驱动，技术栈成熟且对开发者极其友好。

AI-Ready（AI 原生就绪）：区别于传统CRM，Twenty从底层即为AI智能体（Agents）和现代大模型编码工具留出了标准接口，支持通过自然语言直接进行数据检索与流转自动化。

 代码即配置（Code-as-Config）：系统的对象、字段和业务逻辑允许直接通过TypeScript 代码或SDK进行定义，这意味着可以将CRM的配置纳入Git版本管理，无缝对接企业现有的CI/CD 自动化运维流水线。

原生容器化支持：官方提供完善的Docker部署生态，支持一键实现微服务架构的容器化编排，极大地降低了私有化部署、数据备份与平滑升级的运维门槛。

## 二、环境准备

---

- VPS一台 最低配置2核4G 带宽1M即可
- 服务器系统：本文演示的系统是Ubuntu-24.04.1(LTS)
- 是否备案：如果服务器在国外，站点无须备案；如果服务器在国内，网站必须备案。
- 域名一个
- 图床一个（又拍云、阿里云oss、腾讯云cos、七牛云等）
- 为了便于后期的升级维护以及卸载，利用docker+Nginx Proxy Manager部署
- 安装好Docker、Docker-compose、Nginx Proxy Manager（[安装教程](https://www.richarvin.com/ubuntu-da-jian-docker-bu-shu-wordpress-bo-ke/)）
- SSH工具：[FinalShell官网](https://www.hostbuf.com/?ref=richarvin.com)
- 项目地址：[Github官网](https://github.com/twentyhq/twenty?ref=richarvin.com)
- 官方软硬件配置要求请参考以下链接：[Twenty官网](https://docs.twenty.com/developers/extend/apps/getting-started/quick-start?ref=richarvin.com)

[官方文档](https://docs.twenty.com/developers/extend/apps/getting-started/quick-start?ref=richarvin.com)

## 三、部署过程

---

### 系统初始化，更新索引

```bash
#更新索引库
sudo apt-get update
```

### 创建部署目录

```bash
# 创建Twenty部署目录
mkdir -p /root/data/docker_workspace/twenty
# 进入目录
cd /root/data/docker_workspace/twenty
```

### 获取 docker-compose.yml和env环境配置文件

```bash
# 获取compose文件
curl -o docker-compose.yml \
https://raw.githubusercontent.com/twentyhq/twenty/main/packages/twenty-docker/docker-compose.yml
# 获取.env环境配置文件
curl -o .env \
https://raw.githubusercontent.com/twentyhq/twenty/refs/heads/main/packages/twenty-docker/.env.example
```

### 编辑环境变量文件

```bash
# 编辑环境变量文件
nano .env
```

### 修改成以下内容

```bash
TAG=latest

PG_DATABASE_USER=postgres
PG_DATABASE_PASSWORD=INSERT_GENERATED_SECRET_HERE
PG_DATABASE_HOST=db
PG_DATABASE_PORT=5432
REDIS_URL=redis://redis:6379

SERVER_URL=http://localhost:3000

# Use openssl rand -base64 32 for each secret
ENCRYPTION_KEY=INSERT_GENERATED_SECRET_HERE
FALLBACK_ENCRYPTION_KEY=INSERT_GENERATED_SECRET_HERE
APP_SECRET=INSERT_GENERATED_SECRET_HERE

STORAGE_TYPE=local

# STORAGE_S3_REGION=eu-west3
# STORAGE_S3_NAME=my-bucket
# STORAGE_S3_ENDPOINT=
# STORAGE_S3_ACCESS_KEY_ID=
# STORAGE_S3_SECRET_ACCESS_KEY=

```

其中四个密码：`PG_DATABASE_PASSWORD`、`ENCRYPTION_KEY`、`FALLBACK_ENCRYPTION_KEY`、`APP_SECRET`均使用`openssl rand -base64 32`命令随机生成，首次部署的时候，`FALLBACK_ENCRYPTION_KEY`密码为空。其他三个密码必须是独立的。 

### 效果如下

```bash
TAG=latest

PG_DATABASE_USER=postgres
PG_DATABASE_PASSWORD=hLR5qvru8VgX2m+5rw2mpEcb2y1iB09lXqOfSdO0jAI=
PG_DATABASE_HOST=db
PG_DATABASE_PORT=5432
REDIS_URL=redis://redis:6379

SERVER_URL=http://47.168.92.48:3000    # 改为你的服务器IP

DISABLE_DB_MIGRATIONS=false
DISABLE_CRON_JOBS_REGISTRATION=false

# Use openssl rand -base64 32 for each secret
ENCRYPTION_KEY=r8SOZy9wu2P1k6jwkOhlNDXf11/dW7cHvLTmTGQgBH0=
FALLBACK_ENCRYPTION_KEY=
APP_SECRET=+JWPNq8lmvxo45hMsHbtZ9GJBQltOmp6qSHr1DaeYbE=

STORAGE_TYPE=local

# STORAGE_S3_REGION=eu-west3
# STORAGE_S3_NAME=my-bucket
# STORAGE_S3_ENDPOINT=
# STORAGE_S3_ACCESS_KEY_ID=
# STORAGE_S3_SECRET_ACCESS_KEY=

```

请在服务器内部和云平台的安全组中开启3000端口。如果是生产环境中，.env中的`SERVER_URL`值请改为自己已经解析好的域名 

官网的`docker-compose.yml`文件里面关于healthy的检测太过严格，启动容器的时候经常会导致失败

![](https://picture.richarvin.com/202606/202606040002.webp)

放宽 healthcheck，修改 docker-compose.yml如下，可复制直接替换

```yml
name: twenty

services:
  server:
    image: twentycrm/twenty:${TAG:-latest}
    volumes:
      - server-local-data:/app/packages/twenty-server/.local-storage
    ports:
      - "3000:3000"
    environment:
      NODE_PORT: 3000
      PG_DATABASE_URL: postgres://${PG_DATABASE_USER:-postgres}:${PG_DATABASE_PASSWORD:-postgres}@${PG_DATABASE_HOST:-db}:${PG_DATABASE_PORT:-5432}/default
      SERVER_URL: ${SERVER_URL}
      REDIS_URL: ${REDIS_URL:-redis://redis:6379}
      DISABLE_DB_MIGRATIONS: ${DISABLE_DB_MIGRATIONS}
      DISABLE_CRON_JOBS_REGISTRATION: ${DISABLE_CRON_JOBS_REGISTRATION}

      STORAGE_TYPE: ${STORAGE_TYPE}
      STORAGE_S3_REGION: ${STORAGE_S3_REGION}
      STORAGE_S3_NAME: ${STORAGE_S3_NAME}
      STORAGE_S3_ENDPOINT: ${STORAGE_S3_ENDPOINT}

      ENCRYPTION_KEY: ${ENCRYPTION_KEY}
      FALLBACK_ENCRYPTION_KEY: ${FALLBACK_ENCRYPTION_KEY}
      APP_SECRET: ${APP_SECRET:-}
      # MESSAGING_PROVIDER_GMAIL_ENABLED: ${MESSAGING_PROVIDER_GMAIL_ENABLED}
      # CALENDAR_PROVIDER_GOOGLE_ENABLED: ${CALENDAR_PROVIDER_GOOGLE_ENABLED}
      # AUTH_GOOGLE_CLIENT_ID: ${AUTH_GOOGLE_CLIENT_ID}
      # AUTH_GOOGLE_CLIENT_SECRET: ${AUTH_GOOGLE_CLIENT_SECRET}
      # AUTH_GOOGLE_CALLBACK_URL: ${AUTH_GOOGLE_CALLBACK_URL}
      # AUTH_GOOGLE_APIS_CALLBACK_URL: ${AUTH_GOOGLE_APIS_CALLBACK_URL}

      # CALENDAR_PROVIDER_MICROSOFT_ENABLED: ${CALENDAR_PROVIDER_MICROSOFT_ENABLED}
      # MESSAGING_PROVIDER_MICROSOFT_ENABLED: ${MESSAGING_PROVIDER_MICROSOFT_ENABLED}
      # AUTH_MICROSOFT_ENABLED: ${AUTH_MICROSOFT_ENABLED}
      # AUTH_MICROSOFT_CLIENT_ID: ${AUTH_MICROSOFT_CLIENT_ID}
      # AUTH_MICROSOFT_CLIENT_SECRET: ${AUTH_MICROSOFT_CLIENT_SECRET}
      # AUTH_MICROSOFT_CALLBACK_URL: ${AUTH_MICROSOFT_CALLBACK_URL}
      # AUTH_MICROSOFT_APIS_CALLBACK_URL: ${AUTH_MICROSOFT_APIS_CALLBACK_URL}

      # EMAIL_FROM_ADDRESS: ${EMAIL_FROM_ADDRESS:-contact@yourdomain.com}
      # EMAIL_FROM_NAME: ${EMAIL_FROM_NAME:-"John from YourDomain"}
      # EMAIL_DRIVER: ${EMAIL_DRIVER:-smtp}
      # EMAIL_SMTP_HOST: ${EMAIL_SMTP_HOST:-smtp.gmail.com}
      # EMAIL_SMTP_PORT: ${EMAIL_SMTP_PORT:-465}
      # EMAIL_SMTP_USER: ${EMAIL_SMTP_USER:-}
      # EMAIL_SMTP_PASSWORD: ${EMAIL_SMTP_PASSWORD:-}

    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    healthcheck:
      test: curl -f http://localhost:3000/healthz || exit 1
      interval: 20s
      timeout: 10s
      retries: 10
      start_period: 120s
    restart: always

  worker:
    image: twentycrm/twenty:${TAG:-latest}
    volumes:
      - server-local-data:/app/packages/twenty-server/.local-storage
    command: ["yarn", "worker:prod"]
    environment:
      PG_DATABASE_URL: postgres://${PG_DATABASE_USER:-postgres}:${PG_DATABASE_PASSWORD:-postgres}@${PG_DATABASE_HOST:-db}:${PG_DATABASE_PORT:-5432}/default
      SERVER_URL: ${SERVER_URL}
      REDIS_URL: ${REDIS_URL:-redis://redis:6379}
      DISABLE_DB_MIGRATIONS: "true" # it already runs on the server
      DISABLE_CRON_JOBS_REGISTRATION: "true" # it already runs on the server

      STORAGE_TYPE: ${STORAGE_TYPE}
      STORAGE_S3_REGION: ${STORAGE_S3_REGION}
      STORAGE_S3_NAME: ${STORAGE_S3_NAME}
      STORAGE_S3_ENDPOINT: ${STORAGE_S3_ENDPOINT}

      ENCRYPTION_KEY: ${ENCRYPTION_KEY}
      FALLBACK_ENCRYPTION_KEY: ${FALLBACK_ENCRYPTION_KEY}
      APP_SECRET: ${APP_SECRET:-}
      # MESSAGING_PROVIDER_GMAIL_ENABLED: ${MESSAGING_PROVIDER_GMAIL_ENABLED}
      # CALENDAR_PROVIDER_GOOGLE_ENABLED: ${CALENDAR_PROVIDER_GOOGLE_ENABLED}
      # AUTH_GOOGLE_CLIENT_ID: ${AUTH_GOOGLE_CLIENT_ID}
      # AUTH_GOOGLE_CLIENT_SECRET: ${AUTH_GOOGLE_CLIENT_SECRET}
      # AUTH_GOOGLE_CALLBACK_URL: ${AUTH_GOOGLE_CALLBACK_URL}
      # AUTH_GOOGLE_APIS_CALLBACK_URL: ${AUTH_GOOGLE_APIS_CALLBACK_URL}

      # CALENDAR_PROVIDER_MICROSOFT_ENABLED: ${CALENDAR_PROVIDER_MICROSOFT_ENABLED}
      # MESSAGING_PROVIDER_MICROSOFT_ENABLED: ${MESSAGING_PROVIDER_MICROSOFT_ENABLED}
      # AUTH_MICROSOFT_ENABLED: ${AUTH_MICROSOFT_ENABLED}
      # AUTH_MICROSOFT_CLIENT_ID: ${AUTH_MICROSOFT_CLIENT_ID}
      # AUTH_MICROSOFT_CLIENT_SECRET: ${AUTH_MICROSOFT_CLIENT_SECRET}
      # AUTH_MICROSOFT_CALLBACK_URL: ${AUTH_MICROSOFT_CALLBACK_URL}
      # AUTH_MICROSOFT_APIS_CALLBACK_URL: ${AUTH_MICROSOFT_APIS_CALLBACK_URL}

      # EMAIL_FROM_ADDRESS: ${EMAIL_FROM_ADDRESS:-contact@yourdomain.com}
      # EMAIL_FROM_NAME: ${EMAIL_FROM_NAME:-"John from YourDomain"}
      # EMAIL_DRIVER: ${EMAIL_DRIVER:-smtp}
      # EMAIL_SMTP_HOST: ${EMAIL_SMTP_HOST:-smtp.gmail.com}
      # EMAIL_SMTP_PORT: ${EMAIL_SMTP_PORT:-465}
      # EMAIL_SMTP_USER: ${EMAIL_SMTP_USER:-}
      # EMAIL_SMTP_PASSWORD: ${EMAIL_SMTP_PASSWORD:-}

    depends_on:
      db:
        condition: service_healthy
      server:
        condition: service_healthy
    restart: always

  db:
    image: postgres:16
    volumes:
      - db-data:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: ${PG_DATABASE_NAME:-default}
      POSTGRES_PASSWORD: ${PG_DATABASE_PASSWORD:-postgres}
      POSTGRES_USER: ${PG_DATABASE_USER:-postgres}
    healthcheck:
      test: pg_isready -U ${PG_DATABASE_USER:-postgres} -h localhost -d postgres
      interval: 5s
      timeout: 5s
      retries: 10
    restart: always

  redis:
    image: redis
    restart: always
    command: ["--maxmemory-policy", "noeviction"]
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 5s
      retries: 10

volumes:
  db-data:
  server-local-data:

```

### 启动 Docker 容器

```bash
docker compose up -d
```

![](https://picture.richarvin.com/202606/202306040003.webp)

使用你的服务器地址:3000端口访问

![](https://picture.richarvin.com/202606/202606040004.webp)

使用电子邮件注册登录后初始化数据库

![](https://picture.richarvin.com/202606/202606040005.webp)

![](https://picture.richarvin.com/202606/202606040006.webp)

![](https://picture.richarvin.com/202606/202606040007.webp)

![](https://picture.richarvin.com/202606/202606040008.webp)

### 域名访问

可参考下面的文章去Nginx Proxy Manager里设置域名访问

[Ubuntu搭建docker部署wordpress博客Title：在Ubuntu上使用Docker部署WordPress博客：详细教程与Nginx Proxy Manager配置 Description：学习如何在Ubuntu服务器上使用Docker搭建WordPress博客。通过详细步骤，安装Docker、Nginx Proxy Manager（NPM）和WordPress，并在NPM管理界面进行域名绑定和证书申请，实现用自定义域名访问博客。 Tags：Ubuntu Docker WordPress, Nginx Proxy Manager, 自定义域名, 证书申请, 配置教程.![](https://static.ghost.org/v5.0.0/images/link-icon.svg)知行笔记Richarvin![](https://picture.richarvin.com/202403/202403190006.webp)](https://www.richarvin.com/ubuntu-da-jian-docker-bu-shu-wordpress-bo-ke/)

## 卸载

---

### 进入目录

```bash
# 进入自己的项目路径
cd /root/data/docker_workspace/twenty

# 停止并删除所有容器
docker compose down

# Twenty的数据都在下面两个volume里，分别删除
docker volume rm twenty_db-data
docker volume rm twenty_server-local-data

# 删除镜像
docker rmi twentycrm/twenty:latest

# 回到目录上层
cd /root/data/docker_workspace

# 删除项目文件
rm -rf twenty
```

---