Chatwoot是一款聊天对话软件,支持Docker部署Chatwoot,详细过程如下

安装docker及docker compose

# example in ubuntu
apt-get update
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
apt install docker-compose-plugin

查看对应的版本

docker --version
docker compose version

创建配置文件

mkdir chatwoot
cd chatwoot
wget -O .env https://raw.githubusercontent.com/chatwoot/chatwoot/develop/.env.example
wget -O docker-compose.yaml https://raw.githubusercontent.com/chatwoot/chatwoot/develop/docker-compose.production.yaml

编辑修改,注意在.env和docker-compose.yaml二者中的POSTGRES_PASSWORD参数必须一致

nano .env

SECRET_KEY_BASE值可以用以下命令生成,二选一即可

openssl rand -base64 32
head /dev/urandom | tr -dc A-Za-z0-9 | head -c 63 ; echo ''

我的自定义,示范如下

# Learn about the various environment variables at
# https://www.chatwoot.com/docs/self-hosted/configuration/environment-variables/#rails-production-variables

# Used to verify the integrity of signed cookies. so ensure a secure value is set
# SECRET_KEY_BASE should be alphanumeric. Avoid special characters or symbols.
# Use `rake secret` to generate this variable
SECRET_KEY_BASE=ZoxaEZz7M/gviLx4iuLw6e141CBKPGkagPGplBgSyrA=

# Replace with the URL you are planning to use for your app
FRONTEND_URL=http://0.0.0.0:3000
# To use a dedicated URL for help center pages
HELPCENTER_URL=http://0.0.0.0:3000

# If the variable is set, all non-authenticated pages would fallback to the default locale.
# Whenever a new account is created, the default language will be DEFAULT_LOCALE instead of en
# DEFAULT_LOCALE=en

# If you plan to use CDN for your assets, set Asset CDN Host
ASSET_CDN_HOST=

# Force all access to the app over SSL, default is set to false
FORCE_SSL=false

# This lets you control new sign ups on your chatwoot installation
# true : default option, allows sign ups
# false : disables all the end points related to sign ups
# api_only: disables the UI for signup, but you can create sign ups via the account apis
ENABLE_ACCOUNT_SIGNUP=false

# Redis config
# specify the configs via single URL or individual variables
# ref: https://www.iana.org/assignments/uri-schemes/prov/redis
# You can also use the following format for the URL: redis://:password@host:port/db_number
REDIS_URL=redis://redis:6379
# If you are using docker-compose, set this variable's value to be any string,
# which will be the password for the redis service running inside the docker-compose
# to make it secure
REDIS_PASSWORD=ggt8AQE12vtgZPPq76AQx
# Redis Sentinel can be used by passing list of sentinel host and ports e,g. sentinel_host1:port1,sentinel_host2:port2
REDIS_SENTINELS=
# Redis sentinel master name is required when using sentinel, default value is "mymaster".
# You can find list of master using "SENTINEL masters" command
REDIS_SENTINEL_MASTER_NAME=

# By default Chatwoot will pass REDIS_PASSWORD as the password value for sentinels
# Use the following environment variable to customize passwords for sentinels.
# Use empty string if sentinels are configured with out passwords
# REDIS_SENTINEL_PASSWORD=

# Redis premium breakage in heroku fix
# enable the following configuration
# ref: https://github.com/chatwoot/chatwoot/issues/2420
# REDIS_OPENSSL_VERIFY_MODE=none

# Postgres Database config variables
# You can leave POSTGRES_DATABASE blank. The default name of
# the database in the production environment is chatwoot_production
# POSTGRES_DATABASE=
POSTGRES_HOST=postgres
POSTGRES_USERNAME=postgres
POSTGRES_PASSWORD=trrt75XS91MSFFcf32QPmn
RAILS_ENV=development
# Changes the Postgres query timeout limit. The default is 14 seconds. Modify only when required.
# POSTGRES_STATEMENT_TIMEOUT=14s
RAILS_MAX_THREADS=5

# The email from which all outgoing emails are sent
# could user either  `email@yourdomain.com` or `BrandName <email@yourdomain.com>`
MAILER_SENDER_EMAIL=Chatwoot <accounts@chatwoot.com>

#SMTP domain key is set up for HELO checking
SMTP_DOMAIN=chatwoot.com
# Set the value to "mailhog" if using docker-compose for development environments,
# Set the value as "localhost" or your SMTP address in other environments
# If SMTP_ADDRESS is empty, Chatwoot would try to use sendmail(postfix)
SMTP_ADDRESS=
SMTP_PORT=1025
SMTP_USERNAME=
SMTP_PASSWORD=
# plain,login,cram_md5
SMTP_AUTHENTICATION=
SMTP_ENABLE_STARTTLS_AUTO=true
# Can be: 'none', 'peer', 'client_once', 'fail_if_no_peer_cert', see http://api.rubyonrails.org/classes/ActionMailer/Base.html
SMTP_OPENSSL_VERIFY_MODE=peer
# Comment out the following environment variables if required by your SMTP server
# SMTP_TLS=
# SMTP_SSL=
# SMTP_OPEN_TIMEOUT
# SMTP_READ_TIMEOUT

# Mail Incoming
# This is the domain set for the reply emails when conversation continuity is enabled
MAILER_INBOUND_EMAIL_DOMAIN=
# Set this to the appropriate ingress channel with regards to incoming emails
# Possible values are :
# relay for Exim, Postfix, Qmail
# mailgun for Mailgun
# mandrill for Mandrill
# postmark for Postmark
# sendgrid for Sendgrid
RAILS_INBOUND_EMAIL_SERVICE=
# Use one of the following based on the email ingress service
# Ref: https://edgeguides.rubyonrails.org/action_mailbox_basics.html
# Set this to a password of your choice and use it in the Inbound webhook
RAILS_INBOUND_EMAIL_PASSWORD=

MAILGUN_INGRESS_SIGNING_KEY=
MANDRILL_INGRESS_API_KEY=

# Creating Your Inbound Webhook Instructions for Postmark and Sendgrid:
# Inbound webhook URL format:
#    https://actionmailbox:[YOUR_RAILS_INBOUND_EMAIL_PASSWORD]@[YOUR_CHATWOOT_DOMAIN.COM]/rails/action_mailbox/[RAILS_INBOUND_EMAIL_SERVICE]/inbound_emails
# Note: Replace the values inside the brackets; do not include the brackets themselves.
# Example: https://actionmailbox:mYRandomPassword3@chatwoot.example.com/rails/action_mailbox/postmark/inbound_emails
# For Postmark
# Ensure the 'Include raw email content in JSON payload' checkbox is selected in the inbound webhook section.

# Storage
ACTIVE_STORAGE_SERVICE=local

# Amazon S3
# documentation: https://www.chatwoot.com/docs/configuring-s3-bucket-as-cloud-storage
S3_BUCKET_NAME=
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_REGION=

# Log settings
# Disable if you want to write logs to a file
RAILS_LOG_TO_STDOUT=true
LOG_LEVEL=info
LOG_SIZE=500
# Configure this environment variable if you want to use lograge instead of rails logger
#LOGRAGE_ENABLED=true

### This environment variables are only required if you are setting up social media channels

# Facebook
# documentation: https://www.chatwoot.com/docs/facebook-setup
FB_VERIFY_TOKEN=
FB_APP_SECRET=
FB_APP_ID=

# https://developers.facebook.com/docs/messenger-platform/instagram/get-started#app-dashboard
IG_VERIFY_TOKEN=

# Twitter
# documentation: https://www.chatwoot.com/docs/twitter-app-setup
TWITTER_APP_ID=
TWITTER_CONSUMER_KEY=
TWITTER_CONSUMER_SECRET=
TWITTER_ENVIRONMENT=

#slack integration
SLACK_CLIENT_ID=
SLACK_CLIENT_SECRET=

# Google OAuth
GOOGLE_OAUTH_CLIENT_ID=
GOOGLE_OAUTH_CLIENT_SECRET=
GOOGLE_OAUTH_CALLBACK_URL=

### Change this env variable only if you are using a custom build mobile app
## Mobile app env variables
IOS_APP_ID=L7YLMN4634.com.chatwoot.app
ANDROID_BUNDLE_ID=com.chatwoot.app

# https://developers.google.com/android/guides/client-auth (use keytool to print the fingerprint in the first section)
ANDROID_SHA256_CERT_FINGERPRINT=AC:73:8E:DE:EB:56:EA:CC:10:87:02:A7:65:37:7B:38:D4:5D:D4:53:F8:3B:FB:D3:C6:28:64:1D:AA:08:1E:D8

### Smart App Banner
# https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/PromotingAppswithAppBanners/PromotingAppswithAppBanners.html
# You can find your app-id in https://itunesconnect.apple.com
#IOS_APP_IDENTIFIER=1495796682

## Push Notification
## generate a new key value here : https://d3v.one/vapid-key-generator/
# VAPID_PUBLIC_KEY=
# VAPID_PRIVATE_KEY=
#
# for mobile apps
# FCM_SERVER_KEY=

### APM and Error Monitoring configurations
## Elastic APM
## https://www.elastic.co/guide/en/apm/agent/ruby/current/getting-started-rails.html
# ELASTIC_APM_SERVER_URL=
# ELASTIC_APM_SECRET_TOKEN=

## Sentry
# SENTRY_DSN=


## Scout
## https://scoutapm.com/docs/ruby/configuration
# SCOUT_KEY=YOURKEY
# SCOUT_NAME=YOURAPPNAME (Production)
# SCOUT_MONITOR=true

## NewRelic
# https://docs.newrelic.com/docs/agents/ruby-agent/configuration/ruby-agent-configuration/
# NEW_RELIC_LICENSE_KEY=
# Set this to true to allow newrelic apm to send logs.
# This is turned off by default.
# NEW_RELIC_APPLICATION_LOGGING_ENABLED=

## Datadog
## https://github.com/DataDog/dd-trace-rb/blob/master/docs/GettingStarted.md#environment-variables
# DD_TRACE_AGENT_URL=

# MaxMindDB API key to download GeoLite2 City database
# IP_LOOKUP_API_KEY=

## Rack Attack configuration
## To prevent and throttle abusive requests
# ENABLE_RACK_ATTACK=true
# RACK_ATTACK_LIMIT=300
# ENABLE_RACK_ATTACK_WIDGET_API=true
# Comma-separated list of trusted IPs that bypass Rack Attack throttling rules
# RACK_ATTACK_ALLOWED_IPS=127.0.0.1,::1,192.168.0.10

## Running chatwoot as an API only server
## setting this value to true will disable the frontend dashboard endpoints
# CW_API_ONLY_SERVER=false

## Development Only Config
# if you want to use letter_opener for local emails
# LETTER_OPENER=true
# meant to be used in github codespaces
# WEBPACKER_DEV_SERVER_PUBLIC=

# If you want to use official mobile app,
# the notifications would be relayed via a Chatwoot server
ENABLE_PUSH_RELAY_SERVER=true

# Stripe API key
STRIPE_SECRET_KEY=
STRIPE_WEBHOOK_SECRET=

# Set to true if you want to upload files to cloud storage using the signed url
# Make sure to follow https://edgeguides.rubyonrails.org/active_storage_overview.html#cross-origin-resource-sharing-cors-configuration on the cloud storage after setting this to true.
DIRECT_UPLOADS_ENABLED=

#MS OAUTH creds
AZURE_APP_ID=
AZURE_APP_SECRET=

## Advanced configurations
## Change these values to fine tune performance
# control the concurrency setting of sidekiq
SIDEKIQ_CONCURRENCY=5


# AI powered features
## OpenAI key
# OPENAI_API_KEY=

# Housekeeping/Performance related configurations
# Set to true if you want to remove stale contact inboxes
# contact_inboxes with no conversation older than 90 days will be removed
# REMOVE_STALE_CONTACT_INBOX_JOB_STATUS=false

配置docker-compose.yaml文件

nano docker-compose.yaml

示范如下

version: '3'

services:
  base: &base
    image: chatwoot/chatwoot:latest
    env_file: .env ## Change this file for customized env variables
    volumes:
      - storage_data:/app/storage

  rails:
    <<: *base
    depends_on:
      - postgres
      - redis
    ports:
      - '3000:3000'
    environment:
      - NODE_ENV=production
      - RAILS_ENV=production
      - INSTALLATION_ENV=docker
    entrypoint: docker/entrypoints/rails.sh
    command: ['bundle', 'exec', 'rails', 's', '-p', '3000', '-b', '0.0.0.0']
    restart: always

  sidekiq:
    <<: *base
    depends_on:
      - postgres
      - redis
    environment:
      - NODE_ENV=production
      - RAILS_ENV=production
      - INSTALLATION_ENV=docker
    command: ['bundle', 'exec', 'sidekiq', '-C', 'config/sidekiq.yml']
    restart: always

  postgres:
    image: pgvector/pgvector:pg16
    restart: always
    ports:
      - '127.0.0.1:5432:5432'
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=chatwoot
      - POSTGRES_USER=postgres
      # Please provide your own password.
      - POSTGRES_PASSWORD=trrt75XS91MSFFcf32QPmn

  redis:
    image: redis:alpine
    restart: always
    command: ["sh", "-c", "redis-server --requirepass \"$REDIS_PASSWORD\""]
    env_file: .env
    volumes:
      - redis_data:/data
    ports:
      - '127.0.0.1:6379:6379'

volumes:
  storage_data:
  postgres_data:
  redis_data:

准备数据库

docker compose run --rm rails bundle exec rails db:chatwoot_prepare

看到**Created database ‘chatwoot_production’**即成功了

​启动

docker compose down
docker compose up -d

执行

curl -I localhost:3000/api

返回HTTP/1.1 200 OK就可以网页访问http://<your-external-ip>:3000进行相关设置了

Access your installation Your Chatwoot installation is complete. Please note that the containers are not exposed to the internet and they only bind to the localhost. Setup something like Nginx or any other proxy server to proxy the requests to the container. If you want to verify whether the installation is working, try curl -I localhost:3000/api to see if it returns 200. Also, you could temporarily drop the 127.0.0.1:3000:3000 for rails to 3000:3000 in the compose file to access your instance at http://:3000. It’s recommended to revert this change back and use Nginx or some proxy server in the front. Run docker compose run --rm rails bundle exec rails db:chatwoot_prepare whenever you decide to update the Chatwoot images to handle the migrations.

nginx配置

server {
    listen 80;
    listen [::]:80;
    server_name example.com;
    root /var/www/example.com;
    index index.html index.htm index.php;
    return 301 https://$server_name$request_uri;
  }
  server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name example.com;
    # root /var/www/example.com;
    set $upstream 127.0.0.1:3000;
    underscores_in_headers on;
    location /.well-known {
      alias /var/www/ssl-proof/chatwoot/.well-known;
    }
  
    location / {
      proxy_pass_header Authorization;
      proxy_pass http://$upstream;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
      proxy_set_header Host $host;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-Forwarded-Ssl on; # Optional
  
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  
      proxy_http_version 1.1;
      proxy_buffering off;
  
      client_max_body_size 0;
      proxy_read_timeout 36000s;
      proxy_redirect off;
    }
    ssl on;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_certificate      /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key  /etc/letsencrypt/live/example.com/privkey.pem;
  }

彻底删除docker部署的chatwoot

删除卷和网络

Chatwoot 会用到 Postgres、Redis 等卷,执行:

docker compose down -v
docker volume ls | grep chatwoot
docker volume rm  chatwoot_postgres_data
docker volume rm  chatwoot_redis_data
docker volume rm  chatwoot_storage_data
# 删除网络
docker network ls | grep chatwoot
docker network rm <网络名>
docker system prune -a --volumes
# 删除残留数据目录(如果映射过宿主机目录)
# 检查 docker-compose.yml 或启动命令,看是否有挂载到宿主机,比如
# volumes:
#   - ./storage:/app/storage
rm -rf ./storage
rm -rf chatwoot

安装chatwoot如果遇到会导致卡死死机现象,通常是配置过低(例如CPU、内存、硬盘空间大小、硬盘IO),内存问题可以通过增加SWAP虚拟内存缓解。也可以设置.env把参数RAILS_MAX_THREADS,SIDEKIQ_CONCURRENCY参数的并发值调整小点。