docker.recipes

Mattermost Team Chat

intermediate

Enterprise messaging platform with PostgreSQL, Elasticsearch search, and file storage.

Overview

Mattermost is an open-source, self-hosted team collaboration platform designed as an enterprise alternative to Slack and Microsoft Teams. Originally created by SpinPunch in 2016, Mattermost has evolved into a comprehensive messaging solution that prioritizes data sovereignty, security, and integration capabilities. The platform supports unlimited message history, file sharing, voice calls, and extensive plugin ecosystem while maintaining complete control over your data and infrastructure. This enterprise-grade deployment combines Mattermost with PostgreSQL for robust message and metadata storage, Elasticsearch for advanced search capabilities across channels and files, MinIO as S3-compatible object storage for file attachments and media, and NGINX as a high-performance reverse proxy. PostgreSQL ensures ACID compliance for critical chat data while supporting Mattermost's complex relational queries. Elasticsearch enables instant search across thousands of messages and channels with relevance scoring. MinIO provides scalable file storage that's compatible with AWS S3 APIs but remains under your control. This stack is ideal for organizations requiring enterprise-grade team communication with complete data control, compliance teams needing audit trails and data retention policies, development teams wanting extensive integrations and custom bots, and companies migrating from proprietary solutions like Slack while maintaining advanced features. The combination delivers production-ready performance with the flexibility to customize authentication, integrate with existing LDAP/SAML systems, and scale across multiple teams and departments.

Key Features

  • PostgreSQL backend with ACID compliance for reliable message storage and complex user permission queries
  • Elasticsearch integration for full-text search across messages, files, and user profiles with relevance ranking
  • MinIO S3-compatible object storage for unlimited file attachments, image previews, and media sharing
  • NGINX reverse proxy with SSL termination, request buffering, and WebSocket support for real-time messaging
  • Bleve search indexing as fallback when Elasticsearch is unavailable, stored in persistent Docker volumes
  • Multi-database support through PostgreSQL's JSON capabilities for plugin data and custom integrations
  • High-availability file storage with MinIO's erasure coding and bucket lifecycle management
  • Advanced PostgreSQL full-text search capabilities as backup to Elasticsearch cluster

Common Use Cases

  • 1Enterprise team communication replacing Slack or Microsoft Teams with on-premises data control
  • 2Software development teams needing GitLab, Jira, and CI/CD pipeline integrations with custom webhooks
  • 3Healthcare and financial organizations requiring HIPAA/SOX compliance with audit logging and data retention
  • 4Remote-first companies needing persistent chat history, file sharing, and voice/video calling infrastructure
  • 5Government agencies requiring air-gapped communication systems with classified data handling
  • 6Educational institutions managing student and faculty communication across multiple departments
  • 7Managed service providers offering white-labeled team collaboration platforms to clients

Prerequisites

  • Minimum 6GB RAM (PostgreSQL 1GB + Elasticsearch 2GB + MinIO 1GB + Mattermost 1GB + system overhead)
  • Docker Engine 20.10+ and Docker Compose v2 for health check dependencies and network isolation
  • Ports 80, 443, 8065, 9000, and 9001 available for NGINX, Mattermost, and MinIO console access
  • Valid SSL certificates for production deployment with HTTPS termination at NGINX
  • Basic understanding of Mattermost System Console for Elasticsearch configuration and user management
  • PostgreSQL administration knowledge for backup strategies and performance tuning

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 mattermost:
3 image: mattermost/mattermost-team-edition:latest
4 ports:
5 - "8065:8065"
6 environment:
7 MM_SQLSETTINGS_DRIVERNAME: postgres
8 MM_SQLSETTINGS_DATASOURCE: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}?sslmode=disable
9 MM_BLEVESETTINGS_INDEXDIR: /mattermost/bleve-indexes
10 MM_FILESETTINGS_DRIVERNAME: amazons3
11 MM_FILESETTINGS_AMAZONS3ACCESSKEYID: ${MINIO_ACCESS_KEY}
12 MM_FILESETTINGS_AMAZONS3SECRETACCESSKEY: ${MINIO_SECRET_KEY}
13 MM_FILESETTINGS_AMAZONS3BUCKET: mattermost
14 MM_FILESETTINGS_AMAZONS3ENDPOINT: minio:9000
15 MM_FILESETTINGS_AMAZONS3SSL: "false"
16 volumes:
17 - mattermost_data:/mattermost/data
18 - mattermost_logs:/mattermost/logs
19 - mattermost_config:/mattermost/config
20 - mattermost_plugins:/mattermost/plugins
21 - mattermost_bleve:/mattermost/bleve-indexes
22 depends_on:
23 postgres:
24 condition: service_healthy
25 minio:
26 condition: service_started
27 networks:
28 - mm-net
29 restart: unless-stopped
30
31 postgres:
32 image: postgres:16-alpine
33 environment:
34 POSTGRES_USER: ${POSTGRES_USER}
35 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
36 POSTGRES_DB: ${POSTGRES_DB}
37 volumes:
38 - postgres_data:/var/lib/postgresql/data
39 healthcheck:
40 test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
41 interval: 10s
42 timeout: 5s
43 retries: 5
44 networks:
45 - mm-net
46 restart: unless-stopped
47
48 elasticsearch:
49 image: elasticsearch:8.11.0
50 environment:
51 - discovery.type=single-node
52 - xpack.security.enabled=false
53 - ES_JAVA_OPTS=-Xms512m -Xmx512m
54 volumes:
55 - es_data:/usr/share/elasticsearch/data
56 networks:
57 - mm-net
58 restart: unless-stopped
59
60 minio:
61 image: minio/minio:latest
62 ports:
63 - "9000:9000"
64 - "9001:9001"
65 environment:
66 MINIO_ROOT_USER: ${MINIO_ACCESS_KEY}
67 MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY}
68 volumes:
69 - minio_data:/data
70 command: server /data --console-address ":9001"
71 networks:
72 - mm-net
73 restart: unless-stopped
74
75 nginx:
76 image: nginx:alpine
77 ports:
78 - "80:80"
79 - "443:443"
80 volumes:
81 - ./nginx.conf:/etc/nginx/nginx.conf:ro
82 - ./certs:/etc/nginx/certs:ro
83 depends_on:
84 - mattermost
85 networks:
86 - mm-net
87 restart: unless-stopped
88
89volumes:
90 mattermost_data:
91 mattermost_logs:
92 mattermost_config:
93 mattermost_plugins:
94 mattermost_bleve:
95 postgres_data:
96 es_data:
97 minio_data:
98
99networks:
100 mm-net:
101 driver: bridge

.env Template

.env
1# PostgreSQL
2POSTGRES_USER=mattermost
3POSTGRES_PASSWORD=secure_postgres_password
4POSTGRES_DB=mattermost
5
6# MinIO
7MINIO_ACCESS_KEY=minioadmin
8MINIO_SECRET_KEY=secure_minio_password

Usage Notes

  1. 1Mattermost at http://localhost:8065
  2. 2Create MinIO bucket 'mattermost' first
  3. 3MinIO Console at http://localhost:9001
  4. 4Enable Elasticsearch in System Console

Individual Services(5 services)

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

mattermost
mattermost:
  image: mattermost/mattermost-team-edition:latest
  ports:
    - "8065:8065"
  environment:
    MM_SQLSETTINGS_DRIVERNAME: postgres
    MM_SQLSETTINGS_DATASOURCE: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}?sslmode=disable
    MM_BLEVESETTINGS_INDEXDIR: /mattermost/bleve-indexes
    MM_FILESETTINGS_DRIVERNAME: amazons3
    MM_FILESETTINGS_AMAZONS3ACCESSKEYID: ${MINIO_ACCESS_KEY}
    MM_FILESETTINGS_AMAZONS3SECRETACCESSKEY: ${MINIO_SECRET_KEY}
    MM_FILESETTINGS_AMAZONS3BUCKET: mattermost
    MM_FILESETTINGS_AMAZONS3ENDPOINT: minio:9000
    MM_FILESETTINGS_AMAZONS3SSL: "false"
  volumes:
    - mattermost_data:/mattermost/data
    - mattermost_logs:/mattermost/logs
    - mattermost_config:/mattermost/config
    - mattermost_plugins:/mattermost/plugins
    - mattermost_bleve:/mattermost/bleve-indexes
  depends_on:
    postgres:
      condition: service_healthy
    minio:
      condition: service_started
  networks:
    - mm-net
  restart: unless-stopped
postgres
postgres:
  image: postgres:16-alpine
  environment:
    POSTGRES_USER: ${POSTGRES_USER}
    POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    POSTGRES_DB: ${POSTGRES_DB}
  volumes:
    - postgres_data:/var/lib/postgresql/data
  healthcheck:
    test:
      - CMD-SHELL
      - pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}
    interval: 10s
    timeout: 5s
    retries: 5
  networks:
    - mm-net
  restart: unless-stopped
elasticsearch
elasticsearch:
  image: elasticsearch:8.11.0
  environment:
    - discovery.type=single-node
    - xpack.security.enabled=false
    - ES_JAVA_OPTS=-Xms512m -Xmx512m
  volumes:
    - es_data:/usr/share/elasticsearch/data
  networks:
    - mm-net
  restart: unless-stopped
minio
minio:
  image: minio/minio:latest
  ports:
    - "9000:9000"
    - "9001:9001"
  environment:
    MINIO_ROOT_USER: ${MINIO_ACCESS_KEY}
    MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY}
  volumes:
    - minio_data:/data
  command: server /data --console-address ":9001"
  networks:
    - mm-net
  restart: unless-stopped
nginx
nginx:
  image: nginx:alpine
  ports:
    - "80:80"
    - "443:443"
  volumes:
    - ./nginx.conf:/etc/nginx/nginx.conf:ro
    - ./certs:/etc/nginx/certs:ro
  depends_on:
    - mattermost
  networks:
    - mm-net
  restart: unless-stopped

Quick Start

terminal
1# 1. Create the compose file
2cat > docker-compose.yml << 'EOF'
3services:
4 mattermost:
5 image: mattermost/mattermost-team-edition:latest
6 ports:
7 - "8065:8065"
8 environment:
9 MM_SQLSETTINGS_DRIVERNAME: postgres
10 MM_SQLSETTINGS_DATASOURCE: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}?sslmode=disable
11 MM_BLEVESETTINGS_INDEXDIR: /mattermost/bleve-indexes
12 MM_FILESETTINGS_DRIVERNAME: amazons3
13 MM_FILESETTINGS_AMAZONS3ACCESSKEYID: ${MINIO_ACCESS_KEY}
14 MM_FILESETTINGS_AMAZONS3SECRETACCESSKEY: ${MINIO_SECRET_KEY}
15 MM_FILESETTINGS_AMAZONS3BUCKET: mattermost
16 MM_FILESETTINGS_AMAZONS3ENDPOINT: minio:9000
17 MM_FILESETTINGS_AMAZONS3SSL: "false"
18 volumes:
19 - mattermost_data:/mattermost/data
20 - mattermost_logs:/mattermost/logs
21 - mattermost_config:/mattermost/config
22 - mattermost_plugins:/mattermost/plugins
23 - mattermost_bleve:/mattermost/bleve-indexes
24 depends_on:
25 postgres:
26 condition: service_healthy
27 minio:
28 condition: service_started
29 networks:
30 - mm-net
31 restart: unless-stopped
32
33 postgres:
34 image: postgres:16-alpine
35 environment:
36 POSTGRES_USER: ${POSTGRES_USER}
37 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
38 POSTGRES_DB: ${POSTGRES_DB}
39 volumes:
40 - postgres_data:/var/lib/postgresql/data
41 healthcheck:
42 test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
43 interval: 10s
44 timeout: 5s
45 retries: 5
46 networks:
47 - mm-net
48 restart: unless-stopped
49
50 elasticsearch:
51 image: elasticsearch:8.11.0
52 environment:
53 - discovery.type=single-node
54 - xpack.security.enabled=false
55 - ES_JAVA_OPTS=-Xms512m -Xmx512m
56 volumes:
57 - es_data:/usr/share/elasticsearch/data
58 networks:
59 - mm-net
60 restart: unless-stopped
61
62 minio:
63 image: minio/minio:latest
64 ports:
65 - "9000:9000"
66 - "9001:9001"
67 environment:
68 MINIO_ROOT_USER: ${MINIO_ACCESS_KEY}
69 MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY}
70 volumes:
71 - minio_data:/data
72 command: server /data --console-address ":9001"
73 networks:
74 - mm-net
75 restart: unless-stopped
76
77 nginx:
78 image: nginx:alpine
79 ports:
80 - "80:80"
81 - "443:443"
82 volumes:
83 - ./nginx.conf:/etc/nginx/nginx.conf:ro
84 - ./certs:/etc/nginx/certs:ro
85 depends_on:
86 - mattermost
87 networks:
88 - mm-net
89 restart: unless-stopped
90
91volumes:
92 mattermost_data:
93 mattermost_logs:
94 mattermost_config:
95 mattermost_plugins:
96 mattermost_bleve:
97 postgres_data:
98 es_data:
99 minio_data:
100
101networks:
102 mm-net:
103 driver: bridge
104EOF
105
106# 2. Create the .env file
107cat > .env << 'EOF'
108# PostgreSQL
109POSTGRES_USER=mattermost
110POSTGRES_PASSWORD=secure_postgres_password
111POSTGRES_DB=mattermost
112
113# MinIO
114MINIO_ACCESS_KEY=minioadmin
115MINIO_SECRET_KEY=secure_minio_password
116EOF
117
118# 3. Start the services
119docker compose up -d
120
121# 4. View logs
122docker 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/mattermost-enterprise/run | bash

Troubleshooting

  • Mattermost shows 'Database connection failed': Check PostgreSQL health check status and verify POSTGRES_USER/POSTGRES_PASSWORD environment variables match between services
  • File uploads fail with S3 errors: Manually create 'mattermost' bucket in MinIO console at localhost:9001 before first use, verify MINIO_ACCESS_KEY credentials
  • Search returns no results: Enable Elasticsearch in Mattermost System Console > Environment > Elasticsearch, then run bulk indexing job to populate search index
  • 502 Bad Gateway from NGINX: Ensure nginx.conf properly proxies to mattermost:8065 internal hostname, check that Mattermost container is running and healthy
  • PostgreSQL container exits with permission errors: Fix Docker volume ownership with 'docker-compose down && docker volume rm postgres_data' then restart
  • Elasticsearch fails to start with memory errors: Increase Docker Desktop memory allocation above 4GB or reduce ES_JAVA_OPTS heap size for development environments

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