docker.recipes

Zulip + PostgreSQL + RabbitMQ + Redis

advanced

Threaded group chat with topic organization.

Overview

Zulip is an open-source team chat application that revolutionizes group communication through its unique topic-based threading system. Originally developed by a team of MIT graduates and later acquired by Dropbox before becoming open-source, Zulip combines the real-time nature of chat with the organized structure of email threads. Unlike traditional chat platforms where conversations flow chronologically, Zulip organizes messages into streams and topics, making it easy to follow multiple conversations simultaneously and catch up on missed discussions without losing context. This deployment stack leverages PostgreSQL as Zulip's primary database for storing messages, user data, and organizational information, while RabbitMQ handles the message queuing system for real-time message delivery and background task processing. Redis provides session management and caching capabilities, significantly improving response times for frequently accessed data, while Memcached offers an additional caching layer for database query optimization. Together, these components create a robust messaging infrastructure capable of handling enterprise-scale communication loads. This configuration is ideal for development teams, open-source projects, academic institutions, and organizations that value organized communication over chaotic chat streams. The combination provides enterprise-grade reliability with self-hosted control, making it perfect for teams requiring data sovereignty, custom integrations, or advanced administrative controls that aren't available in hosted chat solutions.

Key Features

  • Topic-based message threading that allows multiple conversations per stream without message interleaving
  • PostgreSQL backend providing ACID compliance for message integrity and complex user permission queries
  • RabbitMQ message queuing enabling real-time message delivery, push notifications, and background email processing
  • Redis-powered session management and real-time presence indicators for online/offline status
  • Memcached query result caching reducing PostgreSQL load for frequently accessed streams and user data
  • Built-in LaTeX and syntax highlighting support for mathematical formulas and code discussions
  • Advanced search capabilities leveraging PostgreSQL full-text search across messages, files, and user content
  • Multi-protocol authentication support including LDAP, SAML, and social login integration

Common Use Cases

  • 1Software development teams needing organized code review discussions and bug tracking conversations
  • 2Academic research groups managing multiple concurrent project discussions with topic separation
  • 3Open-source projects requiring public archives with searchable message history and contributor onboarding
  • 4Remote-first organizations needing asynchronous communication that doesn't lose context across time zones
  • 5Compliance-focused companies requiring self-hosted chat with full message retention and audit capabilities
  • 6Educational institutions managing course discussions with topic-based assignment and lecture threads
  • 7Technical support teams organizing customer issues by product area with persistent conversation history

Prerequisites

  • Minimum 4GB RAM available (2GB for PostgreSQL and Zulip, 1GB for RabbitMQ, 512MB for Redis/Memcached)
  • Docker and Docker Compose v2.0+ installed with BuildKit support enabled
  • Available ports 80, 443, and 5432 for web interface and database connections
  • Valid email SMTP credentials for user registration and notification delivery
  • SSL certificate or domain name for production deployment (self-signed certificates included for development)
  • Basic understanding of message queuing concepts and PostgreSQL database administration

For development & testing. Review security settings, change default credentials, and test thoroughly before production use. See Terms

docker-compose.yml

docker-compose.yml
1services:
2 zulip:
3 image: zulip/docker-zulip:latest
4 environment:
5 - DB_HOST=postgres
6 - DB_HOST_PORT=5432
7 - DB_USER=zulip
8 - SETTING_MEMCACHED_LOCATION=memcached:11211
9 - SETTING_RABBITMQ_HOST=rabbitmq
10 - SETTING_REDIS_HOST=redis
11 - SECRETS_email_password=${EMAIL_PASSWORD}
12 - SECRETS_rabbitmq_password=${RABBITMQ_PASSWORD}
13 - SECRETS_postgres_password=${POSTGRES_PASSWORD}
14 - SECRETS_secret_key=${SECRET_KEY}
15 - SETTING_EXTERNAL_HOST=localhost
16 - SETTING_ZULIP_ADMINISTRATOR=admin@example.com
17 - SSL_CERTIFICATE_GENERATION=self-signed
18 volumes:
19 - zulip-data:/data
20 ports:
21 - "80:80"
22 - "443:443"
23 depends_on:
24 - postgres
25 - rabbitmq
26 - redis
27 - memcached
28 networks:
29 - zulip-network
30 restart: unless-stopped
31
32 postgres:
33 image: zulip/zulip-postgresql:14
34 environment:
35 - POSTGRES_USER=zulip
36 - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
37 - POSTGRES_DB=zulip
38 volumes:
39 - postgres-data:/var/lib/postgresql/data
40 networks:
41 - zulip-network
42 restart: unless-stopped
43
44 rabbitmq:
45 image: rabbitmq:3-management
46 environment:
47 - RABBITMQ_DEFAULT_USER=zulip
48 - RABBITMQ_DEFAULT_PASS=${RABBITMQ_PASSWORD}
49 volumes:
50 - rabbitmq-data:/var/lib/rabbitmq
51 networks:
52 - zulip-network
53 restart: unless-stopped
54
55 redis:
56 image: redis:alpine
57 volumes:
58 - redis-data:/data
59 networks:
60 - zulip-network
61 restart: unless-stopped
62
63 memcached:
64 image: memcached:alpine
65 networks:
66 - zulip-network
67 restart: unless-stopped
68
69volumes:
70 zulip-data:
71 postgres-data:
72 rabbitmq-data:
73 redis-data:
74
75networks:
76 zulip-network:
77 driver: bridge

.env Template

.env
1# Zulip
2POSTGRES_PASSWORD=secure_postgres_password
3RABBITMQ_PASSWORD=secure_rabbitmq_password
4SECRET_KEY=your-very-long-secret-key-min-50-chars
5EMAIL_PASSWORD=optional_email_password

Usage Notes

  1. 1Zulip at https://localhost
  2. 2Generate realm: manage.py generate_realm_creation_link
  3. 3Topic-based threading
  4. 4Mobile apps available
  5. 5LDAP/SAML auth supported

Individual Services(5 services)

Copy individual services to mix and match with your existing compose files.

zulip
zulip:
  image: zulip/docker-zulip:latest
  environment:
    - DB_HOST=postgres
    - DB_HOST_PORT=5432
    - DB_USER=zulip
    - SETTING_MEMCACHED_LOCATION=memcached:11211
    - SETTING_RABBITMQ_HOST=rabbitmq
    - SETTING_REDIS_HOST=redis
    - SECRETS_email_password=${EMAIL_PASSWORD}
    - SECRETS_rabbitmq_password=${RABBITMQ_PASSWORD}
    - SECRETS_postgres_password=${POSTGRES_PASSWORD}
    - SECRETS_secret_key=${SECRET_KEY}
    - SETTING_EXTERNAL_HOST=localhost
    - SETTING_ZULIP_ADMINISTRATOR=admin@example.com
    - SSL_CERTIFICATE_GENERATION=self-signed
  volumes:
    - zulip-data:/data
  ports:
    - "80:80"
    - "443:443"
  depends_on:
    - postgres
    - rabbitmq
    - redis
    - memcached
  networks:
    - zulip-network
  restart: unless-stopped
postgres
postgres:
  image: zulip/zulip-postgresql:14
  environment:
    - POSTGRES_USER=zulip
    - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
    - POSTGRES_DB=zulip
  volumes:
    - postgres-data:/var/lib/postgresql/data
  networks:
    - zulip-network
  restart: unless-stopped
rabbitmq
rabbitmq:
  image: rabbitmq:3-management
  environment:
    - RABBITMQ_DEFAULT_USER=zulip
    - RABBITMQ_DEFAULT_PASS=${RABBITMQ_PASSWORD}
  volumes:
    - rabbitmq-data:/var/lib/rabbitmq
  networks:
    - zulip-network
  restart: unless-stopped
redis
redis:
  image: redis:alpine
  volumes:
    - redis-data:/data
  networks:
    - zulip-network
  restart: unless-stopped
memcached
memcached:
  image: memcached:alpine
  networks:
    - zulip-network
  restart: unless-stopped

Quick Start

terminal
1# 1. Create the compose file
2cat > docker-compose.yml << 'EOF'
3services:
4 zulip:
5 image: zulip/docker-zulip:latest
6 environment:
7 - DB_HOST=postgres
8 - DB_HOST_PORT=5432
9 - DB_USER=zulip
10 - SETTING_MEMCACHED_LOCATION=memcached:11211
11 - SETTING_RABBITMQ_HOST=rabbitmq
12 - SETTING_REDIS_HOST=redis
13 - SECRETS_email_password=${EMAIL_PASSWORD}
14 - SECRETS_rabbitmq_password=${RABBITMQ_PASSWORD}
15 - SECRETS_postgres_password=${POSTGRES_PASSWORD}
16 - SECRETS_secret_key=${SECRET_KEY}
17 - SETTING_EXTERNAL_HOST=localhost
18 - SETTING_ZULIP_ADMINISTRATOR=admin@example.com
19 - SSL_CERTIFICATE_GENERATION=self-signed
20 volumes:
21 - zulip-data:/data
22 ports:
23 - "80:80"
24 - "443:443"
25 depends_on:
26 - postgres
27 - rabbitmq
28 - redis
29 - memcached
30 networks:
31 - zulip-network
32 restart: unless-stopped
33
34 postgres:
35 image: zulip/zulip-postgresql:14
36 environment:
37 - POSTGRES_USER=zulip
38 - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
39 - POSTGRES_DB=zulip
40 volumes:
41 - postgres-data:/var/lib/postgresql/data
42 networks:
43 - zulip-network
44 restart: unless-stopped
45
46 rabbitmq:
47 image: rabbitmq:3-management
48 environment:
49 - RABBITMQ_DEFAULT_USER=zulip
50 - RABBITMQ_DEFAULT_PASS=${RABBITMQ_PASSWORD}
51 volumes:
52 - rabbitmq-data:/var/lib/rabbitmq
53 networks:
54 - zulip-network
55 restart: unless-stopped
56
57 redis:
58 image: redis:alpine
59 volumes:
60 - redis-data:/data
61 networks:
62 - zulip-network
63 restart: unless-stopped
64
65 memcached:
66 image: memcached:alpine
67 networks:
68 - zulip-network
69 restart: unless-stopped
70
71volumes:
72 zulip-data:
73 postgres-data:
74 rabbitmq-data:
75 redis-data:
76
77networks:
78 zulip-network:
79 driver: bridge
80EOF
81
82# 2. Create the .env file
83cat > .env << 'EOF'
84# Zulip
85POSTGRES_PASSWORD=secure_postgres_password
86RABBITMQ_PASSWORD=secure_rabbitmq_password
87SECRET_KEY=your-very-long-secret-key-min-50-chars
88EMAIL_PASSWORD=optional_email_password
89EOF
90
91# 3. Start the services
92docker compose up -d
93
94# 4. View logs
95docker compose logs -f

One-Liner

Run this command to download and set up the recipe in one step:

terminal
1curl -fsSL https://docker.recipes/api/recipes/zulip-complete/run | bash

Troubleshooting

  • Zulip fails to start with database connection errors: Ensure PostgreSQL container is fully initialized before Zulip starts by checking postgres logs for 'database system is ready to accept connections'
  • Messages not delivering in real-time: Verify RabbitMQ management interface at rabbitmq:15672 shows active queues and check RABBITMQ_PASSWORD matches between services
  • Slow page load times and timeouts: Monitor Redis and Memcached connections using redis-cli ping and telnet memcached:11211 to verify caching layers are responsive
  • User registration emails not sending: Validate SMTP settings in EMAIL_PASSWORD environment variable and check Zulip logs for email backend connection errors
  • High memory usage and container restarts: Adjust PostgreSQL shared_buffers and work_mem settings, and monitor RabbitMQ queue depths for message backlog buildup
  • SSL certificate warnings in browser: Replace self-signed certificates with proper domain certificates or configure SETTING_EXTERNAL_HOST to match your actual domain name

Community Notes

Loading...
Loading notes...

Download Recipe Kit

Get all files in a ready-to-deploy package

Includes docker-compose.yml, .env template, README, and license

Ad Space