Hi! 😃 Today we’re going to take a deep dive into how to easily and systematically build Mattermost, a powerful tool for team communication, using Docker Compose and .env
files. This is a guide for developers, team leaders, and anyone who dreams of an efficient collaboration environment! 🚀
—.
📚 Table of Contents
- **Getting Started: Why Docker Compose and .env?
- Pre-requisites 🛠️
- Verify your Docker and Docker Compose installation
- Set up your project directory structure
- Creating an .env file – the power of environment variables **Preparation.
- Importance of .env files
- Key variable definitions and examples
- Create docker-compose.yml – Defining services 🐳
- Understanding the basic structure
- Define PostgreSQL database service
- Define the Mattermost application service
- Define the Nginx reverse proxy service (optional, recommended)
- Set up volumes and network
- Setting up Nginx (optional, but recommended) 🌐
- Why use Nginx
- Example Nginx configuration file (
nginx/app.conf
)
- Start the Mattermost service 🚀
- Running and verifying the service
- Initial Mattermost setup
- Additional Tips and Considerations 💡
- Harden your security
- Data backup strategy
- Update Management
- Troubleshooting
- Apply SSL/TLS (HTTPS)
- Conclusion 🎉
—.
1. Getting started: Why Docker Compose and .env?
Mattermost is an open source collaboration platform that offers similar functionality to Slack, but with the advantage of being self-hosted, which allows for greater data sovereignty and security. To keep Mattermost running reliably, you need to manage multiple components together, including databases, applications, and more.
This is where Docker Compose and the .env file come into play. ✨
- Docker Compose: A tool that allows you to define and manage multiple Docker containers together. With a single
docker-compose.yml
file, you can spin up and down databases, Mattermost apps, and even Nginx reverse proxies all at once, making deploying and managing services incredibly convenient. - .env file: Used to manage environment variables. You can manage sensitive or frequently changing configuration values such as database passwords, API keys, port numbers, etc. by separating them from the
docker-compose.yml
file. This is good for security and makes it easier to switch settings between environments (dev/production).
In this guide, we’ll walk you through how to utilize these two tools to build Mattermost securely and efficiently.
—.
2. Prerequisites 🛠️
Before we get started, there are a few things you’ll need
Verify your Docker and Docker Compose installation
The first thing you need to make sure is that you have Docker and Docker Compose installed on your system. Open a terminal (or command prompt) and run the following commands to verify that they are installed
docker --version
docker compose version # or docker-compose --version (legacy versions)
If you don’t have it installed, download and install the version for your operating system from the Docker official website (docs.docker.com/get-docker/). When you install Docker Desktop, Docker and Docker Compose are installed together.
Set up your project directory structure
We recommend creating the following directory structure to keep Mattermost-related files organized.
mattermost_project/.
├── .env # Environment variable file
├── docker-compose.yml # Docker Compose configuration file
├── data/ # Volume where Mattermost and DB data will be stored (persistent data)
│ ├── mattermost/ # Mattermost file storage
│ └── postgres/ # PostgreSQL data
└── nginx/ # Nginx configuration files
└── app.conf # Nginx reverse proxy settings
You can run the following command in the terminal to create the directory structure:
mkdir mattermost_project
cd mattermost_project
mkdir -p data/mattermost data/postgres nginx
touch .env docker-compose.yml nginx/app.conf
—]
3. Create your .env file – the power of environment variables 💪.
The .env
file is used to define sensitive information (passwords) or values that may vary depending on the environment (ports, URLs). Create this file in the same directory as docker-compose.yml
and add the following contents
Importance of the .env file
- Security: Do not expose sensitive information, such as passwords, directly in the
docker-compose.yml
file. It is common practice not to commit.env
files to a Git repository (in addition to.gitignore
) - Flexibility: You can easily apply different settings for development, staging, and production environments – just replace the
.env
file for each environment. - Reusability: Use
docker-compose.yml
universally, and manage only environment-specific values in your.env
file.
Key variable definitions and examples
Copy and paste the following into your mattermost_project/.env
file, replacing the “ part with your actual values.
# --- General Settings ---]
# The domain or IP address where the Mattermost service will be hosted.
# This should be set in the Mattermost system console -> Environment -> Site URL.
MM_SITEURL=http://your-domain.com:8065 # or http://:8065
# Port on which the Mattermost app will be exposed externally (if not using Nginx).
# If using Nginx, Nginx will use 80/443 and Mattermost will access the internal 8065 port.
HOST_PORT=8065
# Mattermost app container internal port (no change required)
mm_app_port=8065
# Host path where the container volume will be stored
DATA_DIR=./data
# Mattermost App Settings --- --- Mattermost App Settings
# Mattermost official image version (latest stable version recommended)
MM_VERSION=9.1.0
# --- Database Settings (PostgreSQL) --- # PostgreSQL image version (latest stable recommended)
# PostgreSQL image version (latest stable version recommended)
PG_VERSION=16-alpine
# Database name for Mattermost to use
DB_NAME=mattermost
# User name for Mattermost to access the database as
DB_USER=mmuser
# !!! Important!!! Database user password. Change it to a strong password!
DB_PASSWORD=your_strong_db_password
# --- Nginx Settings (Optional) ---
# HTTP port (80) on which the Nginx container will be exposed to the outside world (80)
nginx_http_port=80
# HTTPS port (443) on which Nginx containers will be exposed to the outside world (used when SSL/TLS is enabled)
nginx_https_port=443
—]
4. Write docker-compose.yml – Define the Service 🐳
Now let’s configure Docker Compose using the variables defined in the .env
file. Open the mattermost_project/docker-compose.yml
file and write the following contents
Understanding the basic structure
The docker-compose.yml
file is divided into three main sections: services
, volumes
, and networks
.
services
: defines each container (service) to run (e.g.db
,mattermost
,nginx
)volumes
: Defines the volumes for permanently storing the data inside the container on the host machine. The data is preserved even if the container is deleted.networks
: Defines virtual networks for communication between containers.
Defining the PostgreSQL Database Service
All data in Mattermost is stored in a PostgreSQL database.
version: '3.8'
services:
db:
image: postgres:${PG_VERSION}
container_name: mattermost_db
restart: always # always restart on container exit
environment:
# use environment variables imported from the .env file
postgres_db: ${db_name}
postgres_user: ${db_user}
postgres_password: ${db_password}
volumes:
# Mount PostgreSQL data to the host's data/postgres directory.
- ${DATA_DIR}/postgres:/var/lib/postgresql/data
networks:
- # use the same network as the mattermost-network # Mattermost app
healthcheck: # Check DB health
test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d ${DB_NAME}"]
interval: 10s
timeout: 5s
retries: 5
Defining the Mattermost Application Service
The actual Mattermost web application. Set to wait until the database service is ready.
mattermost:
image: mattermost/mattermost-prod-app:${MM_VERSION}
container_name: mattermost_app
restart: always
environment:
# environment variables required for the Mattermost app to connect to the database.
# DB_HOST uses the service name (db) defined in docker-compose.yml
MM_SQLSETTINGS_DRIVERNAME: postgres
MM_SQLSETTINGS_DATASOURCE: postgres://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}?sslmode=disable&connect_timeout=10
mm_servicesettings_siteurl: ${mm_siteurl}
MM_LISTEN_ADDRESS: :${MM_APP_PORT} # Address to listen to inside the container
# SMTP settings (needed for email notifications, etc., add as needed)
# MM_EMAILSETTINGS_SMTPSERVER: smtp.example.com
# mm_emailsettings_smtpport: 587
# MM_EMAILSETTINGS_SMTPUSERNAME: your_email
# MM_EMAILSETTINGS_SMTPPASSWORD: your_email_password
# MM_EMAILSETTINGS_ENABLESMTPAUTH: "true"
# MM_EMAILSETTINGS_ENABLESECURITYBLANKET: "true"
# MM_EMAILSETTINGS_FEEDBACKEMAIL: your_email
# MM_EMAILSETTINGS_FEEDBACKNAME: Mattermost
# MM_EMAILSETTINGS_REPLYTOADDRESS: your_email
# MM_EMAILSETTINGS_SUPPORTEMAIL: your_email
volumes:
# Volumes where Mattermost settings files and data will be stored.
- ${DATA_DIR}/mattermost:/mattermost/data
- ./config.json:/mattermost/config/config.json # Custom configuration file (optional)
ports:
# Ports to access directly from outside if not using Nginx.
# - "${HOST_PORT}:${MM_APP_PORT}"
# port 8065 for Nginx to access from the Mattermost container if using Nginx
- "${HOST_PORT}:${MM_APP_PORT}" # You can leave this open for testing purposes, or comment out this line if you are only using Nginx.
networks:
- mattermost-network
depends_on:
# db service must be started and healthcheck must succeed to start mattermost service
db:
condition: service_healthy
Define the Nginx reverse proxy service (optional, recommended)
Nginx acts as both a web server and a reverse proxy. This makes it easy to enforce SSL (HTTPS), load balance, cache static files, and more. In a production environment, it’s almost essential.
nginx:
image: nginx:alpine
container_name: mattermost_nginx
restart: always
ports:
# expose HTTP port (80) and HTTPS port (443).
- "${NGINX_HTTP_PORT}:80"
# - "${NGINX_HTTPS_PORT}:443" # Uncomment when setting up SSL/TLS
volumes:
# Mount Nginx configuration file to container.
- ./nginx/app.conf:/etc/nginx/conf.d/default.conf
# SSL/TLS certificate volumes (added when setting up SSL/TLS).
# - ./certs:/etc/nginx/certs
networks:
- mattermost-network
depends_on:
# Start Nginx when Mattermost app service is ready
- mattermost
Volume and network settings
Add a volumes
and networks
section to the bottom of the docker-compose.yml
file.
volumes:
# This section is needed because `data/postgres` and `data/mattermost` are mounted directly on the host.
# no explicit `volumes` definition is needed (type: bind mount)
# However, if you want to use anonymous volumes, you can define them here.
# For example:
# db_data:
# mattermost_data:
# networks:
# mattermost-network:
# driver: bridge # use default bridge network
—.
5. Set up Nginx (optional, but recommended) 🌐
Open the mattermost_project/nginx/app.conf
file and write the following content
Why use Nginx
- Reverse proxy: Receives external requests and forwards them to the Mattermost container. This allows the Mattermost app to run on an internal port (8065) rather than a public port, which increases security.
- End SSL/TLS: HTTPS requests are handled by Nginx, and communication with Mattermost can be done over HTTP. Complex SSL settings only need to be done in Nginx, making it easier to manage.
- Static file serving: Nginx can serve static files much more efficiently than Mattermost apps.
- Load balancing: It can act as a load balancer when running multiple Mattermost instances.
Example Nginx configuration file (nginx/app.conf
)
This is a basic reverse proxy setup that forwards HTTP requests to the Mattermost container.
upstream mattermost {
server mattermost_app:${MM_APP_PORT}; # service name and port defined in docker-compose.yml
}
server {
listen 80;
server_name your-domain.com; # change to your real domain or server IP address
# add your SSL/TLS settings here (use a certificate issued by Certbot, etc.)
# listen 443 ssl;
# ssl_certificate /etc/nginx/certs/fullchain.pem; # certificate path
# ssl_certificate_key /etc/nginx/certs/privkey.pem; # private key path
location / {
# Reverse proxy settings
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Ssl on; # when using SSL
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 36000s; # set long for WebSocket connections
proxy_pass http://mattermost; # Forward requests to Mattermost upstream
}
}
—]
6. Start the Mattermost Service 🚀
Now you’re done writing all the configuration files! Let’s start the Mattermost service.
Run and verify the service
Open a terminal in the mattermost_project
directory (i.e., where the docker-compose.yml
and .env
files are located) and run the following command
docker compose up -d
up
: Create and start the services defined in thedocker-compose.yml
file.-d
: Run the container in the background (detached mode).
To verify that the container started successfully, use the following command:
docker compose ps
If the status of all services (db
, mattermost
, nginx
(optional)) shows Up
, you’re good to go! 🎉 .
name command service status ports
mattermost_app "/entrypoint.sh" mattermost running 0.0.0.0:8065->8065/tcp
mattermost_db "docker-entrypoint.sh" db running (healthy) 5432/tcp
mattermost_nginx "/docker-entrypoint.j..." nginx running 0.0.0.0:80->80/tcp
Initial Mattermost Setup
Now open a web browser and connect to the address corresponding to the MM_SITEURL
you defined in your .env
file. For example, http://your-domain.com:8065
or http://:8065
.
The Mattermost team admin account creation screen appears upon initial connection. Follow the instructions to create your account and set up your team.
**Important: After installing Mattermost, please make sure that the MM_SITEURL
in the System Console
-> Environment
-> Site URL
is set to the same as the MM_SITEURL
in your .env
file. If you are using Nginx, it should be the same as the URL you access with Nginx.
—.
7. Additional Tips and Considerations 💡
Here are some additional tips to consider when running Mattermost in production.
Harden your security
- Use strong passwords: Make sure all passwords are strong: database, Mattermost admin account, SMTP, etc.
- Set up a firewall: Set up a firewall on your server to restrict access from the outside to only the ports used by the Mattermost service (e.g. 80, 443).
- Manage .env files: As
.env
files contain sensitive information, add them to.gitignore
and restrict access to them so that they are not included in the version control system (Git).
Data backup strategy
The data
directory defined in docker-compose.yml
contains all persistent data from Mattermost and PostgreSQL. It is very important to back up this directory regularly.
- After stopping the service with the
docker compose stop
command, extract thedata
directory and copy it to another safe place. - You can also use PostgreSQL’s
pg_dump
tool to backup just the database.
Managing updates
To update Mattermost and the PostgreSQL image version:
- In the
.env
file, changeMM_VERSION
andPG_VERSION
to the latest version you want. - Download the latest image with the
docker compose pull
command. - Restart the service with the
docker compose up -d
command. Mattermost automatically migrates the database schema upon update.
Troubleshooting
If the service fails to start properly or encounters problems:
- Check the logs: Check the logs of a specific service with the command
docker compose logs [service name]
(for example,docker compose logs mattermost
ordocker compose logs db
) - Check container status: Check the status of a container with the
docker compose ps
command. - Check for port conflicts: Check if another application is already using the ports (80, 443, 8065, etc.) that Mattermost wants to use.
Enforce SSL/TLS (HTTPS)
In production environments, you must enforce SSL/TLS to connect to Mattermost over HTTPS. If you are using Nginx, you can use Let’s Encrypt and Certbot to obtain and apply a free SSL certificate. This is beyond the scope of this guide, but can be implemented by filling in the listen 443 ssl
and ssl_certificate
, ssl_certificate_key
parts of your Nginx configuration and adding a Certbot container.
—]
8. Conclusion 🎉
Congratulations! 🎉 You should now be able to successfully build and run a Mattermost server utilizing Docker Compose and an .env
file. This will make it easy to deploy and manage Mattermost, and will greatly improve your team’s collaborative productivity.
We hope you and your team enjoy the power of Mattermost and work smarter together! If you have any questions, feel free to leave them in the comments. Happy development!