Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions .github/workflows/dockerfile.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,61 @@ jobs:
pod=$(kubectl get pods -n "$namespace" -l app.kubernetes.io/name=zulip --output name)
kubectl -n "$namespace" logs "$pod"
kubectl -n "$namespace" exec "$pod" -c zulip -- cat /var/log/zulip/errors.log

docker-compose-test:
runs-on: ubuntu-latest
timeout-minutes: 10
needs:
- build
env:
GITHUB_CI_IMAGE: ghcr.io/${{ github.repository }}:pr-${{ github.event.pull_request.number }}
steps:
- name: Checkout code
uses: actions/checkout@v5

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Verify Docker Compose config validation
run: |
docker compose \
-f compose.yaml \
-f ci/compose.override.yaml \
--env-file ci/env \
config

- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Start Docker Compose services
run: |
docker compose \
-f compose.yaml \
-f ci/compose.override.yaml \
--env-file ci/env \
up -d --no-build

- name: Wait for services to be healthy
run: |
echo "Waiting for zulip service to be healthy..."
timeout 300 bash -c \
'until docker inspect --format "{{.State.Health.Status}}" $(docker compose ps -q zulip) | grep -q healthy; do sleep 5; done'

- name: Verify all services are running
run: |
docker compose ps
# Check that no services are in a failed state
if docker compose ps | grep -E "(Exit|Restarting)"; then
exit 1
fi

- name: Check service logs for critical errors
if: success() || failure()
continue-on-error: true
run: |
docker compose ps
docker compose logs zulip
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
.idea/
*.tmproj

# Secrets
/.env

# dev files
docker-compose-dev.yml
kubernetes/*-dev.yml
Expand Down
3 changes: 3 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -73,5 +73,8 @@ COPY certbot-deploy-hook /sbin/certbot-deploy-hook
VOLUME ["$DATA_DIR"]
EXPOSE 25 80 443

HEALTHCHECK --interval=10s --timeout=5s --retries=3 --start-period=300s \
CMD curl -isfL --insecure http://localhost/health || exit 1

ENTRYPOINT ["/sbin/entrypoint.sh"]
CMD ["app:run"]
21 changes: 21 additions & 0 deletions ci/compose.override.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
secrets:
zulip__postgres_password:
environment: "ZULIP__POSTGRES_PASSWORD"
zulip__memcached_password:
environment: "ZULIP__MEMCACHED_PASSWORD"
zulip__rabbitmq_password:
environment: "ZULIP__RABBITMQ_PASSWORD"
zulip__redis_password:
environment: "ZULIP__REDIS_PASSWORD"
zulip__secret_key:
environment: "ZULIP__SECRET_KEY"
zulip__email_password:
environment: "ZULIP__EMAIL_PASSWORD"

services:
zulip:
image: "${GITHUB_CI_IMAGE:?error}"
environment:
SETTING_EXTERNAL_HOST: "zulip.example.net"
SETTING_ZULIP_ADMINISTRATOR: "admin@example.net"
6 changes: 6 additions & 0 deletions ci/env
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
ZULIP__POSTGRES_PASSWORD=postgres_password
ZULIP__MEMCACHED_PASSWORD=memcached_password
ZULIP__RABBITMQ_PASSWORD=rabbitmq_password
ZULIP__REDIS_PASSWORD=redis_password
ZULIP__SECRET_KEY=django_secret_key
ZULIP__EMAIL_PASSWORD=outgoing_email_password
128 changes: 128 additions & 0 deletions compose.override.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
---
secrets:
## You can either set these secrets in a file named .env in this directory, or
## change these from "environment:" to "file:" with a path to store them on
## disk. Be sure that files, if you use them, do not contain trailing
## newlines!
##
## You may also add additional secrets here, prefixed with zulip__, (and also
## in the "secrets:" block inside the "zulip" service, below) in order to
## propagate them into Zulip's /etc/zulip/zulip-secrets.conf
##
## --> https://docs.docker.com/reference/compose-file/secrets/
## https://docs.docker.com/compose/how-tos/use-secrets/
zulip__postgres_password:
## Note that you need to do a manual `ALTER ROLE` query if you
## change this on a system after booting the postgres container
## the first time on a host. Instructions are available in README.md.
environment: "ZULIP__POSTGRES_PASSWORD"
zulip__memcached_password:
environment: "ZULIP__MEMCACHED_PASSWORD"
zulip__rabbitmq_password:
environment: "ZULIP__RABBITMQ_PASSWORD"
zulip__redis_password:
environment: "ZULIP__REDIS_PASSWORD"
zulip__secret_key:
environment: "ZULIP__SECRET_KEY"
zulip__email_password:
environment: "ZULIP__EMAIL_PASSWORD"

services:
zulip:
build:
args:
## If you want to build zulip from a different repo/branch, you can
## change these and run:
##
## docker compose build zulip
ZULIP_GIT_URL: https://github.com/zulip/zulip.git
ZULIP_GIT_REF: "11.4"
environment:
## See https://github.com/zulip/docker-zulip#configuration for
## details on this section and how to discover the many
## additional settings that are supported here.
##
## The following two settings are required:
SETTING_EXTERNAL_HOST: "localhost.localdomain"
SETTING_ZULIP_ADMINISTRATOR: "admin@example.com"

## Most deploys do SSL termination outside of the container; Zulip
## automatically generates a self-signed certificate to use on port443.
## Uncomment this to set up an auto-renewed Lets Encrypt certificate
## inside the container -- this requires that SETTING_EXTERNAL_HOST be
## accessible from the public network.
##
# SSL_CERTIFICATE_GENERATION: "certbot"

## By default, port 80 redirects to port 443, as is suitable for exposing
## publicly. To handle traffic directly on port 80 (if doing SSL
## termination in an outer reverse proxy), uncomment this.
##
# DISABLE_HTTPS: True

## If you're using a reverse proxy, you will also need to provide the
## comma-separated set of IP addresses (or CIDR ranges) to trust here.
##
## --> https://zulip.readthedocs.io/en/stable/production/reverse-proxies.html
##
# LOADBALANCER_IPS: "10.0.0.0/8"

## Outgoing email settings
##
## --> https://zulip.readthedocs.io/en/stable/production/email.html
##
# SETTING_EMAIL_HOST: "smtp.example.com"
# SETTING_EMAIL_HOST_USER: "noreply@example.com"
# SETTING_EMAIL_PORT: "587"
# SETTING_EMAIL_USE_SSL: False
# SETTING_EMAIL_USE_TLS: True

## Uncomment to enable the incoming email gateway. You will need to
## ensure that email to emaildomain.example.com is routed to this host
## (e.g. via MX record)
##
## --> https://zulip.readthedocs.io/en/stable/production/email-gateway.html
##
# SETTING_EMAIL_GATEWAY_PATTERN: "%s@emaildomain.example.com"

## A comma-separated list of authentication backends to enable. Note that
## this ZULIP_AUTH_BACKENDS takes the place of
## SETTINGS_AUTHENTICATION_BACKENDS. This defaults to just
## EmailAuthBackend.
##
## --> https://zulip.readthedocs.io/en/stable/production/authentication-methods.html
##
# ZULIP_AUTH_BACKENDS: "EmailAuthBackend,GoogleAuthBackend"

## Uncomment this when configuring the mobile push notifications service.
## After setting these, you will need to register the server:
##
## docker compose exec -it -u zulip zulip /home/zulip/deployments/current/manage.py register_server
##
## --> https://zulip.readthedocs.io/en/stable/production/mobile-push-notifications.html
##
# SETTING_ZULIP_SERVICE_PUSH_NOTIFICATIONS: True
# SETTING_ZULIP_SERVICE_SUBMIT_USAGE_STATISTICS: True

## By default, files uploaded by users and profile pictures are
## stored directly on the Zulip server. You can configure files
## to be stored in Amazon S3 or a compatible data store
## here.
##
## If you want to use the S3 backend, you must set
## SETTING_LOCAL_UPLOADS_DIR to None as well as configuring the
## other fields.
##
## --> https://zulip.readthedocs.io/en/latest/production/upload-backends.html
##
# SETTING_LOCAL_UPLOADS_DIR: "None"
# SETTING_S3_AUTH_UPLOADS_BUCKET: ""
# SETTING_S3_AVATAR_BUCKET: ""
# SETTING_S3_ENDPOINT_URL: "None"
# SETTING_S3_REGION: "None"

## For a complete list of possible settings, see:
## --> https://github.com/zulip/zulip/blob/11.4/zproject/prod_settings_template.py
secrets:
## Add any additional zulip__ secrets that you defined above.
[]
113 changes: 113 additions & 0 deletions compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
---
services:
database:
image: "zulip/zulip-postgresql:14"
restart: unless-stopped
secrets:
- zulip__postgres_password
environment:
POSTGRES_DB: "zulip"
POSTGRES_USER: "zulip"
POSTGRES_PASSWORD_FILE: /run/secrets/zulip__postgres_password
volumes:
- "postgresql-14:/var/lib/postgresql/data:rw"
attach: false
memcached:
image: "memcached:alpine"
restart: unless-stopped
command:
- "sh"
- "-euc"
- |
echo 'mech_list: plain' > "$$SASL_CONF_PATH"
echo "zulip@$$HOSTNAME:$$(cat $$MEMCACHED_PASSWORD_FILE)" > "$$MEMCACHED_SASL_PWDB"
echo "zulip@localhost:$$(cat $$MEMCACHED_PASSWORD_FILE)" >> "$$MEMCACHED_SASL_PWDB"
exec memcached -S
secrets:
- zulip__memcached_password
environment:
SASL_CONF_PATH: "/home/memcache/memcached.conf"
MEMCACHED_SASL_PWDB: "/home/memcache/memcached-sasl-db"
MEMCACHED_PASSWORD_FILE: /run/secrets/zulip__memcached_password
attach: false
rabbitmq:
image: "rabbitmq:4.1"
restart: unless-stopped
command:
- "sh"
- "-euc"
- |
export RABBITMQ_DEFAULT_PASS="$$(cat $$RABBITMQ_PASSWORD_FILE)"
echo 'default_user = $$(RABBITMQ_DEFAULT_USER)' >> /etc/rabbitmq/rabbitmq.conf
echo 'default_pass = $$(RABBITMQ_DEFAULT_PASS)' >> /etc/rabbitmq/rabbitmq.conf
exec docker-entrypoint.sh rabbitmq-server
secrets:
- zulip__rabbitmq_password
environment:
RABBITMQ_DEFAULT_USER: "zulip"
RABBITMQ_PASSWORD_FILE: /run/secrets/zulip__rabbitmq_password
volumes:
- "rabbitmq:/var/lib/rabbitmq:rw"
attach: false
redis:
image: "redis:alpine"
restart: unless-stopped
command:
- "sh"
- "-euc"
- '/usr/local/bin/docker-entrypoint.sh --requirepass "$$(cat $$REDIS_PASSWORD_FILE)"'
secrets:
- zulip__redis_password
environment:
REDIS_PASSWORD_FILE: /run/secrets/zulip__redis_password
volumes:
- "redis:/data:rw"
attach: false
zulip:
image: "zulip/docker-zulip:11.4-0"
restart: unless-stopped
build:
context: .
ports:
- name: smtp
target: 25
published: 25
app_protocol: smtp
- name: http
target: 80
published: 80
app_protocol: http
- name: https
target: 443
published: 443
app_protocol: https
secrets:
- zulip__postgres_password
- zulip__memcached_password
- zulip__rabbitmq_password
- zulip__redis_password
- zulip__secret_key
- zulip__email_password
environment:
# Default hostnames; configure your application in compose.override.yaml
DB_HOST: "database"
DB_HOST_PORT: "5432"
SETTING_MEMCACHED_LOCATION: "memcached:11211"
SETTING_RABBITMQ_HOST: "rabbitmq"
SETTING_REDIS_HOST: "redis"
volumes:
- "zulip:/data:rw"
ulimits:
nofile:
soft: 1000000
hard: 1048576
depends_on:
- database
- memcached
- rabbitmq
- redis
volumes:
zulip:
postgresql-14:
rabbitmq:
redis:
Loading