Glitchtip is a open-source exception monitoring system, it's similar to Sentry, which collects errors reported from your applications and helps you discover errors in real time and also helps you to understand the health of your applications.
What are we doing today?
In this tutorial we will setup Glitchtip on Docker using Traefik as our Load Balancer and SSL terminations for LetsEncrypt certificates, then we will create a Python Flask application and initiate a error so that we can see how these errors are collected by Glitchtip and we will also add an Webhook Server to demonstrate logging errors to a Webhook Endpoint for further development on errors.
So that we can see our exceptions in our applications like this:
Assumptions
I will assume that you have docker and docker-compose installed. If you need more info on Traefik you can have a look at their website, but I have also written a post on setting up Traefik v2 in detail, but we will touch on that in this post.
Code Source
I will publish the code for this tutorial under my Github Repository:
Environment Details
I have 3 DNS Entries:
- Glitchtip:
gc.civo.rbkr.xyz
- Flask App:
flask-app.civo.rbkr.xyz
- Webhook:
flask-webhook.civo.rbkr.xyz
Which all points to the host running Glitchtip.
Directory Structure
First create the directory structure for our glitchtip demo and change to the directory:
mkdir glitchtip-tutorial cd glitchtip-tutorial
Create the traefik directory for acme.json
where certificate data will be stored, create the file and change permissions on the file:
mkdir traefik touch traefik/acme.json chmod 600 traefik/acme.json
Traefik
Open the docker-compose.yml
and add the first bit which will Traefik, ensure that you replace me@example.com
with your email under certificatesResolvers.letsencrypt.acme.email
:
version: '3.8' x-logging: &default-logging driver: "json-file" options: max-size: "1m" services: glitchtip-traefik: image: traefik:2.4 container_name: glitchtip-traefik restart: unless-stopped volumes: - ./traefik/acme.json:/acme.json - /var/run/docker.sock:/var/run/docker.sock networks: - glitchtip ports: - 80:80 - 443:443 command: - '--api' - '--providers.docker=true' - '--providers.docker.exposedByDefault=false' - '--entrypoints.http=true' - '--entrypoints.http.address=:80' - '--entrypoints.http.http.redirections.entrypoint.to=https' - '--entrypoints.http.http.redirections.entrypoint.scheme=https' - '--entrypoints.https=true' - '--entrypoints.https.address=:443' - '--certificatesResolvers.letsencrypt.acme.email=me@example.com' - '--certificatesResolvers.letsencrypt.acme.storage=acme.json' - '--certificatesResolvers.letsencrypt.acme.httpChallenge.entryPoint=http' - '--log=true' - '--log.level=INFO' logging: driver: "json-file" options: max-size: "1m" networks: glitchtip: name: glitchtip
You can now start Traefik so long:
docker-compose up -d
Glitchtip
Now we will add the Glitchtip components, you can refer to their documentation if you want to read more into these configuration options. Add the following services below glitchtip-traefk
:
glitchtip-postgres: image: postgres:13 container_name: glitchtip-postgres restart: unless-stopped environment: POSTGRES_HOST_AUTH_METHOD: "trust" POSTGRES_DB: postgres POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres PGDATA: /var/lib/postgresql/data/pgdata volumes: - ./data/postgres:/var/lib/postgresql/data networks: - glitchtip healthcheck: test: ["CMD", "pg_isready", "-U", "postgres"] interval: 5s retries: 5 logging: *default-logging glitchtip-redis: image: redis container_name: glitchtip-redis restart: unless-stopped networks: - glitchtip healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 30s retries: 50 logging: *default-logging glitchtip-web: image: glitchtip/glitchtip container_name: glitchtip-web restart: unless-stopped depends_on: glitchtip-traefik: condition: service_started glitchtip-postgres: condition: service_healthy glitchtip-redis: condition: service_healthy environment: DATABASE_URL: postgres://postgres:postgres@glitchtip-postgres:5432/postgres REDIS_URL: redis://glitchtip-redis:6379/0 SECRET_KEY: jsdf93892309fhufhr PORT: 8000 EMAIL_URL: "${EMAIL_URL}" DEFAULT_FROM_EMAIL: ${EMAIL_FROM_ADDRESS} GLITCHTIP_DOMAIN: "https://gt.civo.rbkr.xyz" ENABLE_OPEN_USER_REGISTRATION: "True" GLITCHTIP_MAX_EVENT_LIFE_DAYS: 90 networks: - glitchtip labels: - 'traefik.enable=true' - 'traefik.http.routers.glitchtip.rule=Host(`gt.civo.rbkr.xyz`)' - 'traefik.http.routers.glitchtip.entrypoints=https' - 'traefik.http.routers.glitchtip.tls=true' - 'traefik.http.routers.glitchtip.tls.certresolver=letsencrypt' - 'traefik.http.routers.glitchtip.service=glitchtip-service' - 'traefik.http.services.glitchtip-service.loadbalancer.server.port=8000' logging: *default-logging glitchtip-worker: image: glitchtip/glitchtip container_name: glitchtip-worker restart: unless-stopped command: celery -A glitchtip worker -B -l INFO depends_on: glitchtip-postgres: condition: service_healthy glitchtip-redis: condition: service_healthy environment: DATABASE_URL: postgres://postgres:postgres@glitchtip-postgres:5432/postgres REDIS_URL: redis://glitchtip-redis:6379/0 SECRET_KEY: jsdf93892309fhufhr PORT: 8000 EMAIL_URL: "${EMAIL_URL}" DEFAULT_FROM_EMAIL: ${EMAIL_FROM_ADDRESS} GLITCHTIP_DOMAIN: "https://gt.civo.rbkr.xyz" networks: - glitchtip logging: *default-logging glitchtip-migrate: image: glitchtip/glitchtip container_name: glitchtip-migrate depends_on: glitchtip-postgres: condition: service_healthy glitchtip-redis: condition: service_healthy command: "./manage.py migrate" environment: DATABASE_URL: postgres://postgres:postgres@glitchtip-postgres:5432/postgres REDIS_URL: redis://glitchtip-redis:6379/0 SECRET_KEY: jsdf93892309fhufhr PORT: 8000 EMAIL_URL: "${EMAIL_URL}" DEFAULT_FROM_EMAIL: ${EMAIL_FROM_ADDRESS} GLITCHTIP_DOMAIN: "https://gt.civo.rbkr.xyz" networks: - glitchtip logging: *default-logging
Ensure that you change the following:
-
EMAIL_URL
eg.smtp://apikey:your-password@smtp.sendgrid.net:587
(sendgrid offers free mail delivery) -
DEFAULT_FROM_EMAIL
eg.no-reply@yourdomain.com
- Your FQDN for glitchtip in
'traefik.http.routers.glitchtip.rule=Host()'
Once your configuration is updated, start glitchtip:
docker-compose pull docker-compose up -d
Once all the services are started you should be able to access the UI and will look more or less like this:
Since ENABLE_OPEN_USER_REGISTRATION
is set to True
, we can register our user:
Once you register you will be logged in and on the organization page to create a organization:
For this tutorial, I will be using the name my-org
:
I will go ahead and create a application in my organisation called flask-service-dev
and I will be selecting Python Flask for this tutorial, and I want to associate this project to a team called engineering
, at the bottom select team and create your team:
Once the team has been created and selected, select the framework and name your service:
Once you created your project you will get a getting started guide on how to configure your application:
On the right hand side you will get the configuration values, which we will use as environment variables on our application that we want to emit errors to glitchtip:
https://6ee24c1a446347b99e9574edfe990393@gt.civo.rbkr.xyz/1
https://gt.civo.rbkr.xyz/api/1/security/?glitchtip_key=6ee24c1a446347b99e9574edfe990393
Now that we have signed up we can disable ENABLE_OPEN_USER_REGISTRATION
by setting it to False
in the docker-compose.yml
, then run docker-compose up -d
.
Optional: Glitchtip is written in Django, so you can also use the following method to manage users and access the admin panel on /admin
:
$ docker-compose run glitchtip-migrate ./manage.py createsuperuser Creating glitchdip_glitchtip-migrate_run ... done Email: me@example.com Password: Password (again): Superuser created successfully.
Python Flask App
Now we will create the application that we want to monitor for errors on glitchtip. From the glitchtip-tutorial
directory, create the application code and dockerfile for our python flask app:
mkdir flask-app touch flask-app/requirements.txt touch flask-app/app.py touch flask-app/Dockerfile
First add the requirements in flask-app/requirements.txt
:
flask==1.1.2 sentry-sdk[flask] gunicorn==20.0.4
Next our dockerfile in flask-app/Dockerfile
:
FROM python:3.8-slim ADD requirements.txt /src/requirements.txt ADD run.sh /src/run.sh RUN chmod +x /src/run.sh RUN pip install --upgrade -r /src/requirements.txt ADD app.py /src/app.py CMD ["/src/run.sh"]
Our boot script that will start flask using gunicorn in flask-app/run.sh
:
#!/bin/sh gunicorn app:app \ --workers 2 \ --threads 2 \ --bind 0.0.0.0:80 \ --capture-output \ --access-logfile '-' \ --error-logfile '-'
Then our application code in flask-app/app.py
:
import os import logging from flask import Flask import sentry_sdk from sentry_sdk.integrations.flask import FlaskIntegration GLITCHTIP_DSN = os.environ['DSN'] sentry_sdk.init( dsn=GLITCHTIP_DSN, integrations=[FlaskIntegration()] ) app = Flask(__name__) app.config['DEBUG'] = False @app.before_first_request def setup_logging(): app.logger.addHandler(logging.StreamHandler()) app.logger.setLevel(logging.INFO) app.logger.info('logs enabled') @app.route('/') def root(): return 'hello, world' @app.route('/log-error') def log_error(): app.logger.error('logging error with glitchtip') return 'logged error' @app.route('/trigger-error') def trigger_error(): division_by_zero = 1 / 0 if __name__ == '__main__': app.logger.info('starting server') app.run()
Then we add this section to our docker-compose.yml
:
glitchtip-flask-app: build: context: flask-app dockerfile: Dockerfile container_name: glitchtip-flask-app restart: unless-stopped depends_on: glitchtip-traefik: condition: service_started environment: DSN: "https://6ee24c1a446347b99e9574edfe990393@gt.civo.rbkr.xyz/1" networks: - glitchtip labels: - 'traefik.enable=true' - 'traefik.http.routers.app.rule=Host(`flask-app.civo.rbkr.xyz`)' - 'traefik.http.routers.app.entrypoints=https' - 'traefik.http.routers.app.tls=true' - 'traefik.http.routers.app.tls.certresolver=letsencrypt' - 'traefik.http.routers.app.service=app-service' - 'traefik.http.services.app-service.loadbalancer.server.port=80' logging: *default-logging
So now our full docker-compose.yml
should look like this more or less:
--- version: '3.8' x-logging: &default-logging driver: "json-file" options: max-size: "1m" services: glitchtip-traefik: image: traefik:2.4 container_name: glitchtip-traefik restart: unless-stopped volumes: - ./traefik/acme.json:/acme.json - /var/run/docker.sock:/var/run/docker.sock networks: - glitchtip ports: - 80:80 - 443:443 command: - '--api' - '--providers.docker=true' - '--providers.docker.exposedByDefault=false' - '--entrypoints.http=true' - '--entrypoints.http.address=:80' - '--entrypoints.http.http.redirections.entrypoint.to=https' - '--entrypoints.http.http.redirections.entrypoint.scheme=https' - '--entrypoints.https=true' - '--entrypoints.https.address=:443' - '--certificatesResolvers.letsencrypt.acme.email=me@example.com' - '--certificatesResolvers.letsencrypt.acme.storage=acme.json' - '--certificatesResolvers.letsencrypt.acme.httpChallenge.entryPoint=http' - '--log=true' - '--log.level=INFO' logging: driver: "json-file" options: max-size: "1m" glitchtip-postgres: image: postgres:13 container_name: glitchtip-postgres restart: unless-stopped environment: POSTGRES_HOST_AUTH_METHOD: "trust" POSTGRES_DB: postgres POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres PGDATA: /var/lib/postgresql/data/pgdata volumes: - ./data/postgres:/var/lib/postgresql/data networks: - glitchtip healthcheck: test: ["CMD", "pg_isready", "-U", "postgres"] interval: 5s retries: 5 logging: *default-logging glitchtip-redis: image: redis container_name: glitchtip-redis restart: unless-stopped networks: - glitchtip healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 30s retries: 50 logging: *default-logging glitchtip-web: image: glitchtip/glitchtip container_name: glitchtip-web restart: unless-stopped depends_on: glitchtip-traefik: condition: service_started glitchtip-postgres: condition: service_healthy glitchtip-redis: condition: service_healthy environment: DATABASE_URL: postgres://postgres:postgres@glitchtip-postgres:5432/postgres REDIS_URL: redis://glitchtip-redis:6379/0 SECRET_KEY: jsdf93892309fhufhr PORT: 8000 EMAIL_URL: "${EMAIL_URL}" DEFAULT_FROM_EMAIL: ${EMAIL_FROM_ADDRESS} GLITCHTIP_DOMAIN: "https://gt.civo.rbkr.xyz" ENABLE_OPEN_USER_REGISTRATION: "False" GLITCHTIP_MAX_EVENT_LIFE_DAYS: 90 networks: - glitchtip labels: - 'traefik.enable=true' - 'traefik.http.routers.glitchtip.rule=Host(`gt.civo.rbkr.xyz`)' - 'traefik.http.routers.glitchtip.entrypoints=https' - 'traefik.http.routers.glitchtip.tls=true' - 'traefik.http.routers.glitchtip.tls.certresolver=letsencrypt' - 'traefik.http.routers.glitchtip.service=glitchtip-service' - 'traefik.http.services.glitchtip-service.loadbalancer.server.port=8000' logging: *default-logging glitchtip-worker: image: glitchtip/glitchtip container_name: glitchtip-worker restart: unless-stopped command: celery -A glitchtip worker -B -l INFO depends_on: glitchtip-postgres: condition: service_healthy glitchtip-redis: condition: service_healthy environment: DATABASE_URL: postgres://postgres:postgres@glitchtip-postgres:5432/postgres REDIS_URL: redis://glitchtip-redis:6379/0 SECRET_KEY: jsdf93892309fhufhr PORT: 8000 EMAIL_URL: "${EMAIL_URL}" DEFAULT_FROM_EMAIL: ${EMAIL_FROM_ADDRESS} networks: - glitchtip logging: *default-logging glitchtip-migrate: image: glitchtip/glitchtip container_name: glitchtip-migrate depends_on: glitchtip-postgres: condition: service_healthy glitchtip-redis: condition: service_healthy command: "./manage.py migrate" environment: DATABASE_URL: postgres://postgres:postgres@glitchtip-postgres:5432/postgres REDIS_URL: redis://glitchtip-redis:6379/0 SECRET_KEY: jsdf93892309fhufhr PORT: 8000 EMAIL_URL: "${EMAIL_URL}" DEFAULT_FROM_EMAIL: ${EMAIL_FROM_ADDRESS} GLITCHTIP_DOMAIN: "https://gt.civo.rbkr.xyz" networks: - glitchtip logging: *default-logging glitchtip-flask-app: build: context: flask-app dockerfile: Dockerfile container_name: glitchtip-flask-app restart: unless-stopped depends_on: glitchtip-traefik: condition: service_started environment: DSN: "https://6ee24c1a446347b99e9574edfe990393@gt.civo.rbkr.xyz/1" networks: - glitchtip labels: - 'traefik.enable=true' - 'traefik.http.routers.app.rule=Host(`flask-app.civo.rbkr.xyz`)' - 'traefik.http.routers.app.entrypoints=https' - 'traefik.http.routers.app.tls=true' - 'traefik.http.routers.app.tls.certresolver=letsencrypt' - 'traefik.http.routers.app.service=app-service' - 'traefik.http.services.app-service.loadbalancer.server.port=80' logging: *default-logging networks: glitchtip: name: glitchtip
Build the flask-app
container and start the service:
docker-compose up --build -d
Making a test request:
$ curl -IL http://flask-app.civo.rbkr.xyz HTTP/1.1 308 Permanent Redirect Location: https://flask-app.civo.rbkr.xyz/ Date: Tue, 28 Sep 2021 06:00:27 GMT Content-Length: 18 Content-Type: text/plain; charset=utf-8 HTTP/2 200 content-type: text/html; charset=utf-8 date: Tue, 28 Sep 2021 06:00:27 GMT server: gunicorn/20.0.4 content-length: 12
Logging Exceptions to Glitchtip
Now let's access the endpoints that will cause an exception, let's first make a request to /trigger-error
, then head over to "Issues", or if you have multiple projects, select your organization, then select your project's issues:
From the issues view, we can see we had one issue:
When we select the issue, we can see more information about this exception, such as the useragent info, the request path, where in our application the exception was raised etc:
As you can see, Glitchtip also provide information deeper in the stack where the exception was raised from:
There's a lot of information, but what I also found nice, was that it logs span_id and trace_id, the sdk version etc:
If we have a look at the /log-error
, which will just log an error event, from the issues view, we can see we had one issue:
When we select the issue, we can see more information about this exception, such as the useragent info, the request path, etc:
Alerting
We can setup alerting for every time we receive an exception, to do so, head over to "Settings", "Projects" and you will find "Project Alerts":
When we select "Create New Alert", you will get the alert configuration and by default the alert will be configured to the email address of the team members of the project.
If we "Add Alert Recipient", you will see that we have the option to add a "Webhook URL", so let's go back to our docker-compose.yml
and setup a Python Flask Webhook:
glitchtip-flask-webhook: build: context: flask-webhook dockerfile: Dockerfile container_name: glitchtip-flask-webhook restart: unless-stopped depends_on: glitchtip-traefik: condition: service_started networks: - glitchtip labels: - 'traefik.enable=true' - 'traefik.http.routers.webhook.rule=Host(`flask-webhook.civo.rbkr.xyz`)' - 'traefik.http.routers.webhook.entrypoints=https' - 'traefik.http.routers.webhook.tls=true' - 'traefik.http.routers.webhook.tls.certresolver=letsencrypt' - 'traefik.http.routers.webhook.service=webhook-service' - 'traefik.http.services.webhook-service.loadbalancer.server.port=80' logging: *default-logging healthcheck: test: ["CMD", "curl", "-f", "http://localhost:80/health"] interval: 5s timeout: 3s retries: 60
Then we create our flask-webhook directory:
mkdir flask-webhook
Create the required files, first our application flask-webhook/app.py
:
import logging from flask import Flask, request, jsonify app = Flask(__name__) app.config['DEBUG'] = False @app.before_first_request def setup_logging(): app.logger.addHandler(logging.StreamHandler()) app.logger.setLevel(logging.INFO) @app.route('/', methods=['POST']) def webhook(): payload = request.get_json(force=True) app.logger.info(payload) return jsonify(payload) @app.route('/health', methods=['GET']) def health(): payload = {'status': 'up'} return jsonify(payload) if __name__ == '__main__': app.logger.info('starting server') app.run()
Then our flask-webhook/Dockerfile
:
FROM python:3.8-slim RUN apt update && apt install curl -y WORKDIR /src ADD requirements.txt /src/requirements.txt ADD run.sh /src/run.sh RUN chmod +x /src/run.sh RUN pip install --upgrade -r /src/requirements.txt ADD app.py /src/app.py CMD ["/src/run.sh"]
Then our flask-webhook/requirements.txt
:
flask==1.1.2 gunicorn==20.0.4
Then when everything is in place, build and start the container:
docker-compose up --build -d
Once the application has started, from Settings, Projects, Project Alerts, when we add a new alert recipient, we select the webhook as a recipient type and add our webhook url:
Now we should see:
Select submit and then invoke the /trigger-error
url:
$ curl -I https://flask-app.civo.rbkr.xyz/trigger-error HTTP/2 500 content-type: text/html; charset=utf-8 date: Tue, 28 Sep 2021 09:36:29 GMT server: gunicorn/20.0.4 content-length: 290
Now when we look at the logs of our webhook container:
$ docker-compose logs -f glitchtip-flask-webhook ... glitchtip-flask-webhook | {'alias': 'GlitchTip', 'text': 'GlitchTip Alert', 'attachments': [{'title': 'ZeroDivisionError: division by zero', 'title_link': 'https://gt.civo.rbkr.xyz/my-org/issues/2', 'text': 'trigger_error', 'image_url': None, 'color': '#e52b50'}], 'sections': [{'activityTitle': 'ZeroDivisionError: division by zero', 'activitySubtitle': '[View Issue FLASK-SERVICE-DEV-1](https://gt.civo.rbkr.xyz/my-org/issues/2)'}]}
If we prettify it, you can see we can consume this information and do our own integrations:
>>> print(json.dumps(e, indent=2)) { "alias": "GlitchTip", "text": "GlitchTip Alert", "attachments": [ { "title": "ZeroDivisionError: division by zero", "title_link": "https://gt.civo.rbkr.xyz/my-org/issues/2", "text": "trigger_error", "image_url": null, "color": "#e52b50" } ], "sections": [ { "activityTitle": "ZeroDivisionError: division by zero", "activitySubtitle": "[View Issue FLASK-SERVICE-DEV-1](https://gt.civo.rbkr.xyz/my-org/issues/2)" } ] }
And our email notification will look like this:
The Complete Compose
This will be published to my github repository, but the complete docker-compose.yml
:
--- version: '3.8' x-logging: &default-logging driver: "json-file" options: max-size: "1m" services: glitchtip-traefik: image: traefik:2.4 container_name: glitchtip-traefik restart: unless-stopped volumes: - ./traefik/acme.json:/acme.json - /var/run/docker.sock:/var/run/docker.sock networks: - glitchtip ports: - 80:80 - 443:443 command: - '--api' - '--providers.docker=true' - '--providers.docker.exposedByDefault=false' - '--entrypoints.http=true' - '--entrypoints.http.address=:80' - '--entrypoints.http.http.redirections.entrypoint.to=https' - '--entrypoints.http.http.redirections.entrypoint.scheme=https' - '--entrypoints.https=true' - '--entrypoints.https.address=:443' - '--certificatesResolvers.letsencrypt.acme.email=email@example.com' - '--certificatesResolvers.letsencrypt.acme.storage=acme.json' - '--certificatesResolvers.letsencrypt.acme.httpChallenge.entryPoint=http' - '--log=true' - '--log.level=INFO' logging: driver: "json-file" options: max-size: "1m" glitchtip-postgres: image: postgres:13 container_name: glitchtip-postgres restart: unless-stopped environment: POSTGRES_HOST_AUTH_METHOD: "trust" POSTGRES_DB: postgres POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres PGDATA: /var/lib/postgresql/data/pgdata volumes: - ./data/postgres:/var/lib/postgresql/data networks: - glitchtip healthcheck: test: ["CMD", "pg_isready", "-U", "postgres"] interval: 5s retries: 5 logging: *default-logging glitchtip-redis: image: redis container_name: glitchtip-redis restart: unless-stopped networks: - glitchtip healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 30s retries: 50 logging: *default-logging glitchtip-web: image: glitchtip/glitchtip container_name: glitchtip-web restart: unless-stopped depends_on: glitchtip-traefik: condition: service_started glitchtip-postgres: condition: service_healthy glitchtip-redis: condition: service_healthy environment: DATABASE_URL: postgres://postgres:postgres@glitchtip-postgres:5432/postgres REDIS_URL: redis://glitchtip-redis:6379/0 SECRET_KEY: jsdf93892309fhufhr PORT: 8000 EMAIL_URL: "${EMAIL_URL}" DEFAULT_FROM_EMAIL: ${EMAIL_FROM_ADDRESS} GLITCHTIP_DOMAIN: "https://gt.civo.rbkr.xyz" ENABLE_OPEN_USER_REGISTRATION: "False" GLITCHTIP_MAX_EVENT_LIFE_DAYS: 90 networks: - glitchtip labels: - 'traefik.enable=true' - 'traefik.http.routers.glitchtip.rule=Host(`gt.civo.rbkr.xyz`)' - 'traefik.http.routers.glitchtip.entrypoints=https' - 'traefik.http.routers.glitchtip.tls=true' - 'traefik.http.routers.glitchtip.tls.certresolver=letsencrypt' - 'traefik.http.routers.glitchtip.service=glitchtip-service' - 'traefik.http.services.glitchtip-service.loadbalancer.server.port=8000' logging: *default-logging glitchtip-worker: image: glitchtip/glitchtip container_name: glitchtip-worker restart: unless-stopped command: celery -A glitchtip worker -B -l INFO depends_on: glitchtip-postgres: condition: service_healthy glitchtip-redis: condition: service_healthy environment: DATABASE_URL: postgres://postgres:postgres@glitchtip-postgres:5432/postgres REDIS_URL: redis://glitchtip-redis:6379/0 SECRET_KEY: jsdf93892309fhufhr PORT: 8000 EMAIL_URL: "${EMAIL_URL}" DEFAULT_FROM_EMAIL: ${EMAIL_FROM_ADDRESS} GLITCHTIP_DOMAIN: "https://gt.civo.rbkr.xyz" networks: - glitchtip logging: *default-logging glitchtip-migrate: image: glitchtip/glitchtip container_name: glitchtip-migrate depends_on: glitchtip-postgres: condition: service_healthy glitchtip-redis: condition: service_healthy command: "./manage.py migrate" environment: DATABASE_URL: postgres://postgres:postgres@glitchtip-postgres:5432/postgres REDIS_URL: redis://glitchtip-redis:6379/0 SECRET_KEY: jsdf93892309fhufhr PORT: 8000 EMAIL_URL: "${EMAIL_URL}" DEFAULT_FROM_EMAIL: ${EMAIL_FROM_ADDRESS} GLITCHTIP_DOMAIN: "https://gt.civo.rbkr.xyz" networks: - glitchtip logging: *default-logging glitchtip-flask-app: build: context: flask-app dockerfile: Dockerfile container_name: glitchtip-flask-app restart: unless-stopped depends_on: glitchtip-traefik: condition: service_started environment: DSN: "https://6ee24c1a446347b99e9574edfe990393@gt.civo.rbkr.xyz/1" networks: - glitchtip labels: - 'traefik.enable=true' - 'traefik.http.routers.app.rule=Host(`flask-app.civo.rbkr.xyz`)' - 'traefik.http.routers.app.entrypoints=https' - 'traefik.http.routers.app.tls=true' - 'traefik.http.routers.app.tls.certresolver=letsencrypt' - 'traefik.http.routers.app.service=app-service' - 'traefik.http.services.app-service.loadbalancer.server.port=80' logging: *default-logging glitchtip-flask-webhook: build: context: flask-webhook dockerfile: Dockerfile container_name: glitchtip-flask-webhook restart: unless-stopped depends_on: glitchtip-traefik: condition: service_started networks: - glitchtip labels: - 'traefik.enable=true' - 'traefik.http.routers.webhook.rule=Host(`flask-webhook.civo.rbkr.xyz`)' - 'traefik.http.routers.webhook.entrypoints=https' - 'traefik.http.routers.webhook.tls=true' - 'traefik.http.routers.webhook.tls.certresolver=letsencrypt' - 'traefik.http.routers.webhook.service=webhook-service' - 'traefik.http.services.webhook-service.loadbalancer.server.port=80' logging: *default-logging healthcheck: test: ["CMD", "curl", "-f", "http://localhost:80/health"] interval: 5s timeout: 3s retries: 60 networks: glitchtip: name: glitchtip
I left the domain endpoints and glitchtip application keys in the code intentionally for demonstration purposes, but deleted the stack after the time of writing.
Thank You
I hope this was helpful, I was really impressed with Glitchtip. If you liked this content, please make sure to share or come say hi on my website or twitter:
- Website: ruan.dev
- Twitter: @ruanbekker
Top comments (0)