Skip to content
Merged
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
47 changes: 47 additions & 0 deletions .github/workflows/docker-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -213,3 +213,50 @@ jobs:
sleep $((attempt * 5))
done
done

attach-release-assets:
name: Attach release assets
runs-on: ubuntu-latest
needs: [build-backend, build-frontend]
if: startsWith(github.ref, 'refs/tags/v')
permissions:
# contents: write so gh release upload can attach files to the
# GitHub Release for this tag. The release itself is created
# manually beforehand with curated notes; this job only adds
# the docker-compose.release.yml and .env.example files.
contents: write

steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1

- name: Bake version into docker-compose.release.yml
# Replaces `${FABRIK_VERSION:-latest}` with `${FABRIK_VERSION:-<tag>}`
# so the compose file shipped with v1.2.3 defaults to
# onemli/fabrik-*:1.2.3 without losing the env-var override path.
run: |
set -euo pipefail
VERSION="${GITHUB_REF#refs/tags/v}"
sed -i "s|\${FABRIK_VERSION:-latest}|\${FABRIK_VERSION:-${VERSION}}|g" docker-compose.release.yml
echo "Pinned default FABRIK_VERSION to ${VERSION}:"
grep "FABRIK_VERSION" docker-compose.release.yml

- name: Upload compose and env files to release
# Fails clearly if the release doesn't yet exist for this tag —
# the expectation is that `gh release create v<x.y.z>` ran first.
# `--clobber` lets re-runs replace previously-uploaded copies.
#
# `.env.example` is copied to `env.example` (no leading dot)
# before upload because GitHub's release asset storage strips
# leading dots and serves dotfiles as `default.env.example`,
# which breaks the README's curl URL.
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
VERSION="${GITHUB_REF#refs/tags/v}"
cp .env.example env.example
gh release upload "v${VERSION}" \
docker-compose.release.yml \
env.example \
--clobber
echo "Uploaded docker-compose.release.yml and env.example to release v${VERSION}"
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
[![Docker Frontend](https://img.shields.io/docker/pulls/onemli/fabrik-frontend?style=flat-square&label=frontend%20pulls&color=2563eb&logo=docker&logoColor=white)](https://hub.docker.com/r/onemli/fabrik-frontend)
[![Docs](https://img.shields.io/badge/docs-fabrikops.com-7c3aed?style=flat-square)](https://docs.fabrikops.com/fabrik/)

[![published](https://static.production.devnetcloud.com/codeexchange/assets/images/devnet-published.svg)](https://developer.cisco.com/codeexchange/github/repo/onemli/fabrik)
[![Run in Cisco Cloud IDE](https://static.production.devnetcloud.com/codeexchange/assets/images/devnet-runable-icon.svg)](https://developer.cisco.com/codeexchange/devenv/onemli/fabrik/)
[![Cisco Developed](https://static.production.devnetcloud.com/codeexchange/assets/images/cisco-developed.svg)](https://developer.cisco.com/codeexchange/github/repo/onemli/fabrik)

[**Docs**](https://docs.fabrikops.com/fabrik/) · [**Quickstart**](https://docs.fabrikops.com/fabrik/getting-started/) · [**Releases**](https://github.com/onemli/fabrik/releases) · [**Discussions**](https://github.com/onemli/fabrik/discussions) · [**Report a bug**](https://github.com/onemli/fabrik/issues)

<br>
Expand Down Expand Up @@ -60,7 +64,7 @@ You need Docker 24+ and Docker Compose v2. That's it.
```bash
mkdir fabrik && cd fabrik
curl -fLo docker-compose.yml https://github.com/onemli/fabrik/releases/latest/download/docker-compose.release.yml
curl -fLo .env.example https://github.com/onemli/fabrik/releases/latest/download/.env.example
curl -fLo .env.example https://github.com/onemli/fabrik/releases/latest/download/env.example
cp .env.example .env
```

Expand Down
232 changes: 232 additions & 0 deletions docker-compose.release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
# Fabrik — release-time docker-compose
#
# This is the compose file users download from a GitHub release. It pulls
# pre-built images from Docker Hub (no local build context, no source tree
# required) and is meant to be paired with a release-managed .env.
#
# Pin a specific version by exporting FABRIK_VERSION before bringing the
# stack up, e.g.:
# echo "FABRIK_VERSION=1.2.1" >> .env
# docker compose pull
# docker compose up -d
#
# The default is `latest`, which floats with whatever the most recent
# successful build pushed.

services:
postgres:
image: postgres:17-alpine
container_name: fabrik-postgres
mem_limit: 512m
env_file:
- .env
environment:
- TZ=${TZ:-UTC}
- POSTGRES_DB=${POSTGRES_DB:-fabrik}
- POSTGRES_USER=${POSTGRES_USER:-fabrik}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}
ports:
- "127.0.0.1:${POSTGRES_EXTERNAL_PORT:-5432}:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- fabrik-network
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U fabrik"]
interval: 10s
timeout: 5s
retries: 5

redis:
image: redis:8-alpine
container_name: fabrik-redis
mem_limit: 256m
env_file:
- .env
environment:
- TZ=${TZ:-UTC}
ports:
- "127.0.0.1:${REDIS_EXTERNAL_PORT:-6379}:6379"
volumes:
- redis_data:/data
networks:
- fabrik-network
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5

neo4j:
image: neo4j:5.26
container_name: fabrik-neo4j
mem_limit: 3g
environment:
- TZ=${TZ:-UTC}
- NEO4J_AUTH=neo4j/${NEO4J_PASSWORD:?NEO4J_PASSWORD is required}
- NEO4J_server_memory_pagecache_size=${NEO4J_PAGECACHE_SIZE:-512M}
- NEO4J_server_memory_heap_initial__size=1G
- NEO4J_server_memory_heap_max__size=${NEO4J_HEAP_MAX_SIZE:-2G}
- NEO4J_ACCEPT_LICENSE_AGREEMENT=yes
- NEO4J_dbms_memory_transaction_total_max=${NEO4J_TX_MEMORY_MAX:-1G}
ports:
- "127.0.0.1:${NEO4J_HTTP_PORT:-7474}:7474"
- "127.0.0.1:${NEO4J_BOLT_PORT:-7687}:7687"
restart: unless-stopped
volumes:
- neo4j_data:/data
- neo4j_logs:/logs
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost:7474 >/dev/null || exit 1"]
interval: 10s
timeout: 5s
retries: 10
start_period: 30s
networks:
- fabrik-network

backend:
image: onemli/fabrik-backend:${FABRIK_VERSION:-latest}
container_name: fabrik-backend
mem_limit: 512m
# Uses the image CMD (entrypoint.sh): migrate -> bootstrap_mim -> daphne.
volumes:
- fabrik_mim_cache:/app/mim_cache
expose:
- "8000"
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
neo4j:
condition: service_healthy
env_file:
- .env
environment:
- TZ=${TZ:-UTC}
- NEO4J_URI=${NEO4J_URI:-bolt://neo4j:7687}
- NEO4J_USER=${NEO4J_USER:-neo4j}
- NEO4J_PASSWORD=${NEO4J_PASSWORD:?NEO4J_PASSWORD is required}
- DATABASE_URL=${DATABASE_URL:?DATABASE_URL is required}
- CELERY_BROKER_URL=${CELERY_BROKER_URL:?CELERY_BROKER_URL is required}
- CELERY_RESULT_BACKEND=${CELERY_RESULT_BACKEND:?CELERY_RESULT_BACKEND is required}
- DJANGO_SECRET_KEY=${DJANGO_SECRET_KEY:?DJANGO_SECRET_KEY is required}
- ENCRYPTION_KEY=${ENCRYPTION_KEY:?ENCRYPTION_KEY is required}
- DEBUG=${DEBUG:-False}
- ALLOWED_HOSTS=${ALLOWED_HOSTS:?ALLOWED_HOSTS is required}
- DEFAULT_USER_TIMEZONE=${DEFAULT_USER_TIMEZONE:-UTC}
restart: unless-stopped
networks:
- fabrik-network
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"

celery-worker:
image: onemli/fabrik-backend:${FABRIK_VERSION:-latest}
container_name: fabrik-celery-worker
mem_limit: 2g
command: celery -A fabrik worker --loglevel=info --concurrency=${CELERY_WORKER_CONCURRENCY:-2} -Q celery,query_exec,scheduled,awx_monitor,awx_exec,maintenance,mim_import
volumes:
- fabrik_mim_cache:/app/mim_cache
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
neo4j:
condition: service_started
env_file:
- .env
environment:
- TZ=${TZ:-UTC}
- NEO4J_URI=${NEO4J_URI:-bolt://neo4j:7687}
- NEO4J_USER=${NEO4J_USER:-neo4j}
- NEO4J_PASSWORD=${NEO4J_PASSWORD:?NEO4J_PASSWORD is required}
- DATABASE_URL=${DATABASE_URL:?DATABASE_URL is required}
- CELERY_BROKER_URL=${CELERY_BROKER_URL:?CELERY_BROKER_URL is required}
- CELERY_RESULT_BACKEND=${CELERY_RESULT_BACKEND:?CELERY_RESULT_BACKEND is required}
- DJANGO_SECRET_KEY=${DJANGO_SECRET_KEY:?DJANGO_SECRET_KEY is required}
- ENCRYPTION_KEY=${ENCRYPTION_KEY:?ENCRYPTION_KEY is required}
- DEFAULT_USER_TIMEZONE=${DEFAULT_USER_TIMEZONE:-UTC}
restart: unless-stopped
networks:
- fabrik-network
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"

celery-beat:
image: onemli/fabrik-backend:${FABRIK_VERSION:-latest}
container_name: fabrik-celery-beat
mem_limit: 256m
command: celery -A fabrik beat --loglevel=info
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
env_file:
- .env
environment:
- TZ=${TZ:-UTC}
- NEO4J_URI=${NEO4J_URI:-bolt://neo4j:7687}
- NEO4J_USER=${NEO4J_USER:-neo4j}
- NEO4J_PASSWORD=${NEO4J_PASSWORD:?NEO4J_PASSWORD is required}
- DATABASE_URL=${DATABASE_URL:?DATABASE_URL is required}
- CELERY_BROKER_URL=${CELERY_BROKER_URL:?CELERY_BROKER_URL is required}
- CELERY_RESULT_BACKEND=${CELERY_RESULT_BACKEND:?CELERY_RESULT_BACKEND is required}
- DJANGO_SECRET_KEY=${DJANGO_SECRET_KEY:?DJANGO_SECRET_KEY is required}
- ENCRYPTION_KEY=${ENCRYPTION_KEY:?ENCRYPTION_KEY is required}
- DEFAULT_USER_TIMEZONE=${DEFAULT_USER_TIMEZONE:-UTC}
restart: unless-stopped
networks:
- fabrik-network
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"

frontend:
image: onemli/fabrik-frontend:${FABRIK_VERSION:-latest}
container_name: fabrik-frontend
mem_limit: 256m
# nginx serves the built SPA and proxies /api, /admin, /static, /ws to backend.
ports:
- "${FRONTEND_PORT:-80}:80"
depends_on:
- backend
environment:
- TZ=${TZ:-UTC}
restart: unless-stopped
networks:
- fabrik-network
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"

volumes:
postgres_data:
name: fabrik_postgres_data
redis_data:
name: fabrik_redis_data
neo4j_data:
name: fabrik_neo4j_data
neo4j_logs:
name: fabrik_neo4j_logs
fabrik_mim_cache:
name: fabrik_mim_cache

networks:
fabrik-network:
name: fabrik-network
driver: bridge
Loading