docker-zulip

Docker Image and configuration for Zulip

Github星跟蹤圖

Welcome to docker-zulip!

docker-zulip stream

This is a container image for running Zulip
(GitHub) in
production. Image available from:

  • Docker Hub (docker pull zulip/docker-zulip:3.2-0)

Current Zulip version: 3.2
Current Docker image version: 3.2-0

Project status: Alpha. While this project works and is
used by many sites in production, configuring is substantially more
error-prone than the normal Zulip installer (which
Just Works). We recommend this project if you want to host Zulip
using Docker, but both setting up and maintaining a Zulip server is
simpler and less error-prone with the normal installer than with Docker.

Overview

This project defines a Docker image for a Zulip server, as well as
sample configuration to run that Zulip web/application server with
each of the major services that Zulip uses in
its own container: redis, postgres, rabbitmq, memcached.

We have configuration and documentation for
Docker Compose and
Kubernetes; contributions are welcome for
documenting other container runtimes and flows.

If you aren't already a Docker expert, we recommend starting by
reading our brief overview of how Docker and containers work in the
next section.

The Docker data storage model

Docker and other container systems are built around shareable
container images. An image is a read-only template with instructions
for creating a container. Often, an image is based on another image,
with a bit of additional customization. For example, Zulip's
zulip-postgresql image extends the standard postgresql image (by
installing a couple postgres extensions). And the zulip image is
built on top of a standard ubuntu image, adding all the code for a Zulip
application/web server.

Every time you boot a container based on a given image, it's like
booting off a CD-ROM: you get the exact same image (and anything
written to the image's filesystem is lost). To handle persistent
state that needs to persist after the Docker equivalent of a reboot or
upgrades (like uploaded files or the Zulip database), container
systems let you configure certain directories inside the container
from the host system's filesystem.

For example, this project's docker-compose.yml configuration file
specifies a set of volumes where
persistent Zulip data should be stored under
/opt/docker/zulip/ in the container host's file system:

  • /opt/docker/zulip/postgresql/data/ has the postgres container's
    persistent storage (i.e. the database).
  • /opt/docker/zulip/zulip/ has the application server container's
    persistent storage, including the secrets file, uploaded files,
    etc.

This approach of mounting /opt/docker into the container is the
right model if you're hosting your containers from a single host
server, which is how docker-compose is intended to be used. If
you're using Kubernetes, Docker Swarm, or another cloud container
service, then these persistent storage volumes are typically
configured to be network block storage volumes (e.g. an Amazon EBS
volume) so that they can be mounted from any server within the
cluster.

What this means is that if you're using docker-zulip in production
with docker-compose, you'll want to configure your backup system to
do backups on the /opt/docker/zulip directory, in order to ensure
you don't lose data.

Prerequisites

To use docker-zulip, you need the following:

  • An installation of Docker and
    Docker Compose or a Kubernetes runtime
    engine.
  • We recommend at least 2GB of available RAM for
    running a production Zulip server; you'll want 4GB if you're
    building the container (rather than using the prebuilt images). If
    you're just testing and/or aren't expecting a lot of users/messages,
    you can get away with significantly less especially for the
    postgres, memcached, etc. containers, because Docker makes it
    easy to sharply limit the RAM allocated to the services Zulip
    depends on, like redis, memcached, and postgresql (at the cost of
    potential performance issues).
  • This project doesn't support docker-rootless; Zulip needs root
    access to set properties like the maximum number of open file
    descriptions via ulimit (which is important for it to handle
    thousands of connected clients).

Running a Zulip server with docker-compose

To use this project, we recommend starting by cloning the repo (since
you'll want to edit the docker-compose.yml file in this project):

git clone https://github.com/zulip/docker-zulip.git
cd docker-zulip
# Edit `docker-compose.yml` to configure; see docs below

If you're in hurry to try Zulip, you can skip to
start the Zulip server, but for production
use, you'll need to do some configuration.

Configuration

With docker-compose, it is traditional to configure a service by
setting environment variables declared in the zulip -> environment
section of the docker-compose.yml file; this image follows that
convention.

Mandatory settings. You must configure these settings (more
discussion in the main Zulip installation docs):

  • SETTING_EXTERNAL_HOST: The hostname your users will use to
    connect to your Zulip server. If you're testing on your laptop,
    the default of localhost.localdomain is great.
  • SETTING_ZULIP_ADMINISTRATOR: The email address to receive error
    and support emails generated by the Zulip server and its users.

Mandatory settings for serious use. Before you allow
production traffic, you need to also set these:

  • POSTGRES_PASSWORD and SECRETS_postgres_password should both be a
    password for the Zulip container to authenticate to the Postgres
    container. Since you won't use this directly, you just want a long,
    randomly generated string. While SECRETS_postgres_password is
    synced to the Zulip container on every boot, POSTGRES_PASSWORD is
    only accessed by the postgres container on first boot, so if you
    later want to change your postgres password after booting the
    container, you'll need to either do an
    ALTER ROLE query inside the postgres
    container or rebuild the postgres database (only if you don't need
    your data!).
  • RABBITMQ_DEFAULT_PASS and SECRETS_rabbitmq_password are similar,
    just for the RabbitMQ container.
  • MEMCACHED_PASSWORD and SECRETS_memcached_password are similar,
    just for the memcached container.
  • REDIS_PASSWORD and SECRETS_redis_password are similar, just for
    the Redis container.
  • SECRETS_secret_key should be a long (e.g. 50 characters), random
    string. This value is important to keep secret and constant over
    time, since it is used to (among other things) sign login cookies
    (so if you change this, all your users will be forcibly logged out).
  • SETTING_EMAIL_*: Where you configure Zulip's ability to send
    outgoing email.

Other settings. If an environment variable name doesn't start with
SETTINGS or SECRETS in docker-compose.yml, it is specific to the
Docker environment. Standard Zulip server settings
are secrets are set using the following syntax:

  • SETTING_MY_SETTING will become MY_SETTING in
    /etc/zulip/settings.py
  • SECRETS_my_secret will become my_secret in
    /etc/zulip/zulip-secrets.conf.

Reading the comments in the sample
Zulip's settings.py file is the best way to
learn about the full set of Zulip's supported server-level settings.

Most settings in Zulip are just strings, but some are lists (etc.)
which you need to encode in the YAML file. For example,

  • For AUTHENTICATION_BACKENDS, you enter ZULIP_AUTH_BACKENDS as a
    comma-separated list of the backend names
    (E.g. "EmailAuthBackend,GitHubAuthBackend").

SSL Certificates. By default, the image will generate a self-signed cert.
You can set SSL_CERTIFICATE_GENERATION: "certbot" within docker-compose.yml
to enable automatically-renewed Let's Encrypt certificates. By using certbot
here, you are agreeing to the Let's Encrypt
ToS
.

You can also provide an SSL certificate for your Zulip server by
putting it in /opt/docker/zulip/zulip/certs/ (by default, the
zulip container startup script will generate a self-signed certificate and
install it in that directory).

Manual configuration

The way the environment variables configuration process described in
the last section works is that the entrypoint.sh script that runs
when the Docker image starts up will generate a
Zulip settings.py file file based on your settings
every time you boot the container. This is convenient, in that you
only need to edit the docker-compose.yml file to configure your
Zulip server's settings.

An alternative approach is to set MANUAL_CONFIGURATION: "True" and
LINK_SETTINGS_TO_DATA: "True" in docker-compose.yml. If you do that, you
can provide a settings.py file and a zulip-secrets.conf file in
/opt/docker/zulip/zulip/, and the container will use those.

Starting the server

You can boot your Zulip installation with:

docker-compose pull
docker-compose up

This will boot the 5 containers declared in docker-compose.yml. The
docker-compose command will print a bunch of output, and then
eventually hang once everything is happily booted, usually ending with
a bunch of lines like this:

rabbitmq_1, =INFO REPORT==== 27-May-2018::23:26:58 ===
rabbitmq_1, accepting AMQP connection <0.534.0> (172.18.0.3:49504
-> 172.18.0.5:5672)

You can inspect what containers are running in another shell with
docker-compose ps (remember to cd into the docker-zulip
directory first).

If you hit Ctrl-C, that will stop your Zulip server cluster. If
you'd prefer to have the containers run in the background, you can use
docker-compose up -d.

If you want to build the Zulip image yourself, you can do that by
running docker-compose build; see also
the documentation on building a custom Git version version.

Connecting to your Zulip server

You can now connect to your Zulip server. For example, if you set
this up on a laptop with the default port mappings and
SETTING_EXTERNAL_HOST, typing http://localhost/ will take you to
your server. Note that in this default scenario, (1) you'll have to
proceed past a self-signed SSL error, and (2) you won't be able to
login until you create an organization, but visiting the URL is a good
way to confirm that your networking configuration is working
correctly.

You can now follow the normal instructions for how to
create a Zulip organization and log in to your
new Zulip server (though see the following section for how to run
management commands).

Running management commands

From time to time, you'll need to attach a shell to the Zulip
container so that you can run manage.py commands, check logs, etc.
The following are helpful examples:

# Get a (root) shell in the container so you can access logs
docker-compose exec zulip bash
# Create the initial Zulip organization
docker-compose exec -u zulip zulip \
    /home/zulip/deployments/current/manage.py generate_realm_creation_link

Since that process for running management commands is a pain, we recommend
using a wrapper script for running management commands.

Using a custom certificate bundle for outgoing HTTP connections

If you are sitting behind a custom CA and want to build the Zulip
image yourself, special care is required.

The Zulip build process installs packages via yarn and pip, and
these need packages to be configured to use your custom CA
certificates. You will need to get your certificate bundle into the
docker image, either by adding a COPY somewhere or by replacing the
FROMs with a custom ubuntu image that includes your bundle. The
recommended way is to have your own base image which has your bundle
ready at the default /etc/ssl/certs/ca-certificates.crt.

The next and last step is to set up the CUSTOM_CA_CERTIFICATES
argument in docker-compose.yml to point to your CA bundle, e.g.
to /etc/ssl/certs/ca-certificates.crt.

At this point you are ready to build Zulip.

Running a Zulip server with Kubernetes

A Kubernetes pod file is in the kubernetes/ folder; you can run it
with kubectl create -f ./kubernetes/.

You should read the docker-compose section above to understand how
this works, since it's a very similar setup. You'll want to to clone
this repository, and edit the zulip-rc.yml to configure the image, etc.

Installing minikube for testing

The fastest way to get Kubernetes up and running for testing without
signing up for a cloud service is to install
Minikube on your system.

Helm charts

We are aware of two efforts at building Helm Charts for Zulip:

Contributions to finish either of those and get them integrated are
very welcome! If you're interested in helping with this, post on
this thread.

Scaling out and high availability

This image is not designed to make it easy to run multiple copies of
the zulip application server container (and you need to know a lot
about Zulip to do this sort of thing successfully). If you're
interested in running a high-availablity Zulip installation, your best
bet is to get in touch with the Zulip support team at
support@zulip.com.

Networking and reverse proxy configuration

When running your container in production, you may want to put your
Zulip container behind an HTTP proxy.
This wiki page documents how to do this correctly
with nginx.

See also the
Zulip documentation on reverse proxies

By default, Zulip will only interact with user traffic over HTTPS.
However, if your networking environment is such that the Zulip server
is behind a load balancer and you need the Zulip server to respond
over HTTP, you can configure that via setting DISABLE_HTTPS: "True"
in the Docker environment (docker-compose.yml).

Upgrading the Zulip container

You can upgrade your Zulip installation to any newer version of Zulip
with the following instructions. At a high level, the strategy is to
download a new image, stop the zulip container, and then boot it
back up with the new image. When the upgraded zulip container boots
the first time, it will run the necessary database migrations with
manage.py migrate.

If you ever find you need to downgrade your Zulip server, you'll need
to use manage.py migrate to downgrade the database schema manually.

If you are using old galexrt/docker-zulip images (from Zulip 1.8.1 or
older), you need to upgrade the postgres image from
quay.io/galexrt/postgres-zulip-tsearchextras:latest. Refer to the
instructions for upgrading from the old galexrt/docker-zulip
section.

Using docker-compose

  1. (Optional) Upgrading does not delete your data, but it's generally
    good practice to
    back up your Zulip data
    before upgrading to make switching back to the old version
    simple. You can find your docker data volumes by looking at the
    volumes lines in docker-compose.yml
    e.g. /opt/docker/zulip/postgresql/data/.

    Note that docker-zulip did not support for Zulip's built-in
    restore-backup tool before Zulip 3.0.

  2. Pull the new image version, e.g. for 2.0.8 run: docker pull zulip/docker-zulip:2.0.8-0. We recommend always upgrading to the
    latest minor release within a major release series.

  3. Update this project to the corresponding docker-zulip version and
    resolve any merge conflicts in docker-compose.yml.
    This is important as new Zulip releases may require additional
    settings to be specified in docker-compose.yml
    (E.g. authentication settings for memcached became mandatory in
    the 2.1.2 release).

  4. Verify that your updated docker-compose.yml points to the desired image version,
    e.g.:

zulip:
  image: "zulip/docker-zulip:2.0.1-0"
  1. You can execute the upgrade by running:
# Stops the old zulip container; this beings your downtime
docker-compose stop
# Boots the new zulip container; this ends your downtime
docker-compose up
# Deletes the old container images
docker-compose rm

That's it! Zulip is now running the updated version.
You can confirm you're running the latest version by running:

docker-compose exec -u zulip zulip cat /home/zulip/deployments/current/version.py

Upgrading from a Git repository

  1. Edit docker-compose.yml to comment out the image line, and
    specify the Git commit you'd like to build the zulip container from.
    E.g.:
  zulip:
    # image: "zulip/docker-zulip:2.0.1-0"
    build:
      context: .
      args:
        # Change these if you want to build zulip from a different repo/branch
        ZULIP_GIT_URL: https://github.com/zulip/zulip.git
        ZULIP_GIT_REF: master

You can set ZULIP_GIT_URL to any clone of the zulip/zulip git
repository, and ZULIP_GIT_REF to be any ref name in that repository
(e.g. master or 1.9.0 or
445932cc8613c77ced023125248c8b966b3b7528).

  1. Run docker-compose build zulip to build a Zulip Docker image from
    the specified Git version.

Then stop and restart the container as described in the previous section.

Upgrading from the old galexrt/docker-zulip

If you are using an earlier version of galexrt/docker-zulip which
used the quay.io/galexrt/postgres-zulip-tsearchextras:latest
Postgres image, you need to run a few manual steps to upgrade to the
zulip/zulip-postgresql Postgres image (because we've significantly
upgraded the major postgres version).

These instructions assume that you have not changed the default
Postgres data path (/opt/docker/zulip/postgresql/data) in your
docker-compose.yml. If you have changed it, please replace all
occurences of /opt/docker/zulip/postgresql/data with your path.

  1. Make a backup of your Zulip Postgres data dir.

  2. Stop all Zulip containers, except the postgres one (e.g. use
    docker stop and not docker-compose stop).

  3. Create a new (upgraded) Postgres container using a different data directory:

docker run -d \
      --name postgresnew \
      -e POSTGRES_DB=zulip \
      -e POSTGRES_USER=zulip \
      -e POSTGRES_PASSWORD=zulip \
      -v /opt/docker/zulip/postgresql/new:/var/lib/postgresql/data:rw \
      zulip/zulip-postgresql:latest
  1. Use pg_dumpall to dump all data from the existing Postgres container to
    the new Postgres container:
docker-compose exec database pg_dumpall -U postgres, \
    docker exec -i postgresnew psql -U postgres
  1. Stop and remove both Postgres containers:
docker-compose rm --stop database
docker rm --stop postgresnew
  1. Edit your docker-compose.yml to use the
    zulip/zulip-postgresql:latest image for the database container
    (this is the default in zulip/docker-zulip).

  2. Replace the old Postgres data directory with upgraded data directory:

mv /opt/docker/zulip/postgresql/data /opt/docker/zulip/postgresql/old
mv /opt/docker/zulip/postgresql/new /opt/docker/zulip/postgresql/data
  1. Delete the old existing containers:
docker-compose rm
  1. Start Zulip up again:
docker-compose up

That should be it. Your Postgres data has now been updated to use the
zulip/zulip-postgresql image.

Troubleshooting

Common issues include:

  • Invalid configuration resulting in the zulip container not
    starting; check docker-compose ps to see if it started, and then
    read the logs for the Zulip container to see why it failed.
  • A new Zulip setting not being passed through the Docker
    entrypoint.sh script properly. If you
    run into this sort of problem you can work around it by specifying a
    ZULIP_CUSTOM_SETTINGS with one setting per line below, but please
    report an issue so that we can fix this for everyone else.

Community support

You can get community support and tell the developers about your
experiences using this project on
#production-help on
chat.zulip.org, the Zulip community server.

In late May 2018, we completed a complete rewrite of this project's
documentation, so we'd love any and all feedback!

Contributing

We love community contributions, and respond quickly to issues and
PRs. Some particularly useful ways to contribute right now are:

  • Contribute to this documentation by opening issues about what
    confused you or submitting pull requests!
  • Reporting bugs or rough edges!

Credits

Huge thanks to everyone who has contributed. Special thanks to
Alexander Trost, who created
docker-zulip and did a huge amount of the early work required to
make a high-quality Docker image for Zulip possible.

主要指標

概覽
名稱與所有者zulip/docker-zulip
主編程語言Shell
編程語言Shell (語言數: 3)
平台
許可證Apache License 2.0
所有者活动
創建於2015-09-26 12:28:02
推送於2025-04-16 07:52:05
最后一次提交
發布數113
最新版本名稱10.2-0 (發布於 )
第一版名稱1.3.6 (發布於 )
用户参与
星數617
關注者數23
派生數270
提交數821
已啟用問題?
問題數334
打開的問題數42
拉請求數93
打開的拉請求數19
關閉的拉請求數48
项目设置
已啟用Wiki?
已存檔?
是復刻?
已鎖定?
是鏡像?
是私有?