Taiga: refactor service naming & resource limits

Add CPU/memory/pids limits for taiga, async, front, gateway, events, async-rabbitmq, events-rabbitmq, manager, and protected. Align manager service usage (was taiga-manage) in admin tasks and inits compose. Switch to variable-driven service names (TAIGA_* vars), add container_name patterns, normalize volume mappings via TAIGA_VOLUME_STATIC/MEDIA, fix depends_on to use TAIGA_* vars, and set RabbitMQ hostnames from vars. Remove obsolete Development.md.

Conversation reference: https://chatgpt.com/share/68da83b7-0cb4-800f-9702-d8a2d4ebea71  (replace with this chat’s share link)
This commit is contained in:
2025-09-29 15:04:12 +02:00
parent 55f2d15e93
commit 27b89d8fb6
6 changed files with 128 additions and 93 deletions

View File

@@ -1,37 +0,0 @@
# Development Notes
## Build front container
```bash
docker compose up -d --force-recreate taiga-front
```
## Debug
Verify front configuration:
```bash
docker compose exec -it taiga-front cat /usr/share/nginx/html/conf.json
```
Verify the backend configuration:
```bash
docker compose exec -it taiga-back cat /taiga-back/settings/local.py
```
## Additional Configuration for plugin
```bash
# ENABLE_OPENID Plugin
ENABLE_OPENID = os.getenv('ENABLE_OPENID', 'False') == 'True'
if ENABLE_OPENID:
INSTALLED_APPS += [
"taiga_contrib_openid_auth"
]
OPENID_USER_URL = os.getenv('OPENID_USER_URL')
OPENID_TOKEN_URL = os.getenv('OPENID_TOKEN_URL')
OPENID_CLIENT_ID = os.getenv('OPENID_CLIENT_ID')
OPENID_CLIENT_SECRET = os.getenv('OPENID_CLIENT_SECRET')
OPENID_SCOPE = os.getenv('OPENID_SCOPE')
OPENID_FILTER = os.getenv('OPENID_FILTER')
OPENID_FILTER_FIELD = os.getenv('OPENID_FILTER_FIELD')
```

View File

@@ -19,6 +19,50 @@ docker:
enabled: true enabled: true
taiga: taiga:
version: "latest" version: "latest"
cpus: "1.0"
mem_reservation: "1g"
mem_limit: "1.5g"
pids_limit: 512
async:
cpus: "1.0"
mem_reservation: "1g"
mem_limit: "1.5g"
pids_limit: 512
front:
cpus: "0.3"
mem_reservation: "256m"
mem_limit: "512m"
pids_limit: 256
gateway:
cpus: "0.3"
mem_reservation: "256m"
mem_limit: "512m"
pids_limit: 256
events:
cpus: "0.3"
mem_reservation: "256m"
mem_limit: "512m"
pids_limit: 256
async-rabbitmq:
cpus: "1.0"
mem_reservation: "1g"
mem_limit: "1.5g"
pids_limit: 512
events-rabbitmq:
cpus: "0.5"
mem_reservation: "512m"
mem_limit: "1g"
pids_limit: 512
manager:
cpus: "0.5"
mem_reservation: "512m"
mem_limit: "1g"
pids_limit: 256
protected:
cpus: "0.2"
mem_reservation: "128m"
mem_limit: "256m"
pids_limit: 128
server: server:
csp: csp:
flags: flags:

View File

@@ -3,7 +3,7 @@
docker compose docker compose
-f {{ TAIGA_DOCKER_COMPOSE_PATH }} -f {{ TAIGA_DOCKER_COMPOSE_PATH }}
-f {{ TAIGA_DOCKER_COMPOSE_INIT_PATH }} -f {{ TAIGA_DOCKER_COMPOSE_INIT_PATH }}
run --rm taiga-manage run --rm {{ TAIGA_MANAGER_SERVICE }}
createsuperuser --noinput createsuperuser --noinput
--username {{ TAIGA_SUPERUSER_NAME }} --username {{ TAIGA_SUPERUSER_NAME }}
--email {{ TAIGA_SUPERUSER_EMAIL }} --email {{ TAIGA_SUPERUSER_EMAIL }}
@@ -25,7 +25,7 @@
-f {{ TAIGA_DOCKER_COMPOSE_INIT_PATH }} -f {{ TAIGA_DOCKER_COMPOSE_INIT_PATH }}
run --rm run --rm
-e DJANGO_SUPERUSER_PASSWORD={{ TAIGA_SUPERUSER_PASSWORD | quote }} -e DJANGO_SUPERUSER_PASSWORD={{ TAIGA_SUPERUSER_PASSWORD | quote }}
taiga-manage {{ TAIGA_MANAGER_SERVICE }}
shell -c shell -c
"from django.contrib.auth import get_user_model; import os; U=get_user_model(); u,created=U.objects.get_or_create(username='{{ TAIGA_SUPERUSER_NAME }}'); changed=bool(created); old=(u.email,u.is_staff,u.is_superuser,u.is_active); u.email='{{ TAIGA_SUPERUSER_EMAIL }}'; u.is_staff=True; u.is_superuser=True; u.is_active=True; changed = changed or old!=(u.email,u.is_staff,u.is_superuser,u.is_active); pwd=os.environ.get('DJANGO_SUPERUSER_PASSWORD'); assert pwd, 'Missing DJANGO_SUPERUSER_PASSWORD'; need_pwd = not u.check_password(pwd); changed = changed or need_pwd; need_pwd and u.set_password(pwd); u.save(); print('CHANGED=1' if changed else 'CHANGED=0')" "from django.contrib.auth import get_user_model; import os; U=get_user_model(); u,created=U.objects.get_or_create(username='{{ TAIGA_SUPERUSER_NAME }}'); changed=bool(created); old=(u.email,u.is_staff,u.is_superuser,u.is_active); u.email='{{ TAIGA_SUPERUSER_EMAIL }}'; u.is_staff=True; u.is_superuser=True; u.is_active=True; changed = changed or old!=(u.email,u.is_staff,u.is_superuser,u.is_active); pwd=os.environ.get('DJANGO_SUPERUSER_PASSWORD'); assert pwd, 'Missing DJANGO_SUPERUSER_PASSWORD'; need_pwd = not u.check_password(pwd); changed = changed or need_pwd; need_pwd and u.set_password(pwd); u.save(); print('CHANGED=1' if changed else 'CHANGED=0')"
args: args:

View File

@@ -1,5 +1,7 @@
{% include 'roles/docker-compose/templates/base.yml.j2' %} {% include 'roles/docker-compose/templates/base.yml.j2' %}
taiga-manage: {% set service_name = TAIGA_MANAGER_SERVICE %}
{{ service_name }}:
container_name: {{ TAIGA_CONTAINER }}-{{ service_name }}
{% include 'roles/docker-container/templates/base.yml.j2' %} {% include 'roles/docker-container/templates/base.yml.j2' %}
image: taigaio/taiga-back:latest image: taigaio/taiga-back:latest
environment: environment:
@@ -8,8 +10,8 @@
{% include 'roles/docker-container/templates/networks.yml.j2' %} {% include 'roles/docker-container/templates/networks.yml.j2' %}
entrypoint: "python manage.py" entrypoint: "python manage.py"
volumes: volumes:
- static-data:/taiga-back/static - static-data:{{ TAIGA_VOLUME_STATIC }}
- media-data:/taiga-back/media - media-data:{{ TAIGA_VOLUME_MEDIA }}
# - ./config.py:/taiga-back/settings/config.py # - ./config.py:/taiga-back/settings/config.py
{% include 'roles/docker-compose/templates/networks.yml.j2' %} {% include 'roles/docker-compose/templates/networks.yml.j2' %}
taiga: taiga:

View File

@@ -1,81 +1,76 @@
{% include 'roles/docker-compose/templates/base.yml.j2' %} {% include 'roles/docker-compose/templates/base.yml.j2' %}
taiga-back: {% set service_name = TAIGA_SERVICE %}
{{ service_name }}:
container_name: {{ TAIGA_CONTAINER }}
{% include 'roles/docker-container/templates/base.yml.j2' %} {% include 'roles/docker-container/templates/base.yml.j2' %}
image: "{{ TAIGA_DOCKER_IMAGE_BACKEND }}:{{ TAIGA_VERSION }}" image: "{{ TAIGA_DOCKER_IMAGE_BACKEND }}:{{ TAIGA_VERSION }}"
volumes: volumes:
# These volumens will be used by taiga-back and taiga-async. # These volumens will be used by taiga-back and taiga-async.
- static-data:/taiga-back/static - static-data:{{ TAIGA_VOLUME_STATIC }}
- media-data:/taiga-back/media - media-data:{{ TAIGA_VOLUME_MEDIA }}
# - ./config.py:/taiga-back/settings/config.py # - ./config.py:/taiga-back/settings/config.py
{% if TAIGA_TAIGAIO_ENABLED | bool %}
{% if TAIGA_TAIGAIO_ENABLED %}
- {{ docker_compose.directories.config }}taiga-local.py:/taiga-back/settings/local.py:ro - {{ docker_compose.directories.config }}taiga-local.py:/taiga-back/settings/local.py:ro
{% endif %} {% endif %}
{% include 'roles/docker-container/templates/networks.yml.j2' %} {% include 'roles/docker-container/templates/networks.yml.j2' %}
taiga: taiga:
{% include 'roles/docker-container/templates/depends_on/dmbs_incl.yml.j2' %} {% include 'roles/docker-container/templates/depends_on/dmbs_incl.yml.j2' %}
taiga-events-rabbitmq: {{ TAIGA_EVENTS_RABBITMQ_SERVICE }}:
condition: service_started condition: service_started
taiga-async-rabbitmq: {{ TAIGA_ASYNC_RABBITMQ_SERVICE }}:
condition: service_started condition: service_started
{% if TAIGA_TAIGAIO_ENABLED %} {% if TAIGA_TAIGAIO_ENABLED | bool %}
command: > command: >
/bin/sh -c " /bin/sh -c "
pip install taiga-contrib-oidc-auth && pip install taiga-contrib-oidc-auth &&
/taiga-back/docker/entrypoint.sh" /taiga-back/docker/entrypoint.sh"
{% endif %} {% endif %}
{% set service_name = TAIGA_ASYNC_SERVICE %}
taiga-async: {{ service_name }}:
container_name: {{ TAIGA_CONTAINER }}-{{ service_name }}
{% include 'roles/docker-container/templates/base.yml.j2' %} {% include 'roles/docker-container/templates/base.yml.j2' %}
image: "{{ TAIGA_DOCKER_IMAGE_BACKEND }}:{{ TAIGA_VERSION }}" image: "{{ TAIGA_DOCKER_IMAGE_BACKEND }}:{{ TAIGA_VERSION }}"
entrypoint: ["/taiga-back/docker/async_entrypoint.sh"] entrypoint: ["/taiga-back/docker/async_entrypoint.sh"]
volumes: volumes:
# These volumens will be used by taiga-back and taiga-async. # These volumens will be used by backend and async service
- static-data:/taiga-back/static - static-data:{{ TAIGA_VOLUME_STATIC }}
- media-data:/taiga-back/media - media-data:{{ TAIGA_VOLUME_MEDIA }}
# - ./config.py:/taiga-back/settings/config.py # - ./config.py:/taiga-back/settings/config.py
{% if TAIGA_TAIGAIO_ENABLED | bool %}
{% if TAIGA_TAIGAIO_ENABLED %}
{% for item in TAIGA_SETTING_FILES %} {% for item in TAIGA_SETTING_FILES %}
- {{ docker_compose.directories.config }}taiga-{{ item }}.py:/taiga-back/settings/{{ item }}.py:ro - {{ docker_compose.directories.config }}taiga-{{ item }}.py:/taiga-back/settings/{{ item }}.py:ro
{% endfor %} {% endfor %}
{% endif %} {% endif %}
{% include 'roles/docker-container/templates/networks.yml.j2' %} {% include 'roles/docker-container/templates/networks.yml.j2' %}
taiga: taiga:
{% include 'roles/docker-container/templates/depends_on/dmbs_incl.yml.j2' %} {% include 'roles/docker-container/templates/depends_on/dmbs_incl.yml.j2' %}
taiga-events-rabbitmq: {{ TAIGA_EVENTS_RABBITMQ_SERVICE }}:
condition: service_started condition: service_started
taiga-async-rabbitmq: {{ TAIGA_ASYNC_RABBITMQ_SERVICE }}:
condition: service_started condition: service_started
{% if TAIGA_TAIGAIO_ENABLED %} {% if TAIGA_TAIGAIO_ENABLED | bool %}
command: > command: >
/bin/sh -c " /bin/sh -c "
pip install taiga-contrib-oidc-auth && pip install taiga-contrib-oidc-auth &&
/taiga-back/docker/entrypoint.sh" /taiga-back/docker/entrypoint.sh"
{% endif %} {% endif %}
taiga-async-rabbitmq: {% set service_name = TAIGA_ASYNC_RABBITMQ_SERVICE %}
{{ service_name }}:
container_name: {{ TAIGA_CONTAINER }}-{{ service_name }}
image: rabbitmq:3.8-management-alpine image: rabbitmq:3.8-management-alpine
hostname: "taiga-async-rabbitmq" hostname: "{{ TAIGA_ASYNC_RABBITMQ_SERVICE }}"
volumes: volumes:
- async-rabbitmq-data:/var/lib/rabbitmq - async-rabbitmq-data:/var/lib/rabbitmq
{% include 'roles/docker-container/templates/base.yml.j2' %} {% include 'roles/docker-container/templates/base.yml.j2' %}
{% include 'roles/docker-container/templates/networks.yml.j2' %} {% include 'roles/docker-container/templates/networks.yml.j2' %}
taiga: taiga:
taiga-front: {% set service_name = TAIGA_FRONT_SERVICE %}
{{ service_name }}:
container_name: {{ TAIGA_CONTAINER }}-{{ service_name }}
image: "{{TAIGA_DOCKER_IMAGE_FRONTEND}}:{{ TAIGA_VERSION }}" image: "{{TAIGA_DOCKER_IMAGE_FRONTEND}}:{{ TAIGA_VERSION }}"
{% include 'roles/docker-container/templates/base.yml.j2' %} {% include 'roles/docker-container/templates/base.yml.j2' %}
{% include 'roles/docker-container/templates/networks.yml.j2' %} {% include 'roles/docker-container/templates/networks.yml.j2' %}
@@ -83,18 +78,22 @@
# volumes: # volumes:
# - {{ TAIGA_FRONTEND_CONF_PATH }}:/usr/share/nginx/html/conf.json:ro # - {{ TAIGA_FRONTEND_CONF_PATH }}:/usr/share/nginx/html/conf.json:ro
taiga-events: {% set service_name = TAIGA_EVENTS_SERVICE %}
{{ service_name }}:
container_name: {{ TAIGA_CONTAINER }}-{{ service_name }}
image: taigaio/taiga-events:latest image: taigaio/taiga-events:latest
{% include 'roles/docker-container/templates/base.yml.j2' %} {% include 'roles/docker-container/templates/base.yml.j2' %}
{% include 'roles/docker-container/templates/networks.yml.j2' %} {% include 'roles/docker-container/templates/networks.yml.j2' %}
taiga: taiga:
depends_on: depends_on:
taiga-events-rabbitmq: {{ TAIGA_EVENTS_RABBITMQ_SERVICE }}:
condition: service_started condition: service_started
taiga-events-rabbitmq: {% set service_name = TAIGA_EVENTS_RABBITMQ_SERVICE %}
{{ service_name }}:
container_name: {{ TAIGA_CONTAINER }}-{{ service_name }}
image: rabbitmq:3.8-management-alpine image: rabbitmq:3.8-management-alpine
hostname: "events-rabbitmq" hostname: {{ service_name }}
volumes: volumes:
- events-rabbitmq-data:/var/lib/rabbitmq - events-rabbitmq-data:/var/lib/rabbitmq
{% include 'roles/docker-container/templates/base.yml.j2' %} {% include 'roles/docker-container/templates/base.yml.j2' %}
@@ -102,14 +101,18 @@
{% include 'roles/docker-container/templates/networks.yml.j2' %} {% include 'roles/docker-container/templates/networks.yml.j2' %}
taiga: taiga:
taiga-protected: {% set service_name = 'protected' %}
{{ service_name }}:
container_name: {{ TAIGA_CONTAINER }}-{{ service_name }}
image: taigaio/taiga-protected:latest image: taigaio/taiga-protected:latest
{% include 'roles/docker-container/templates/base.yml.j2' %} {% include 'roles/docker-container/templates/base.yml.j2' %}
{% include 'roles/docker-container/templates/networks.yml.j2' %} {% include 'roles/docker-container/templates/networks.yml.j2' %}
taiga: taiga:
taiga-gateway: {% set service_name = 'gateway' %}
{{ service_name }}:
container_name: {{ TAIGA_CONTAINER }}-{{ service_name }}
image: nginx:alpine image: nginx:alpine
ports: ports:
- "127.0.0.1:{{ ports.localhost.http[application_id] }}:80" - "127.0.0.1:{{ ports.localhost.http[application_id] }}:80"
@@ -122,10 +125,9 @@
{% include 'roles/docker-container/templates/networks.yml.j2' %} {% include 'roles/docker-container/templates/networks.yml.j2' %}
taiga: taiga:
depends_on: depends_on:
- taiga-front - {{ TAIGA_FRONT_SERVICE }}
- taiga-back - {{ TAIGA_SERVICE }}
- taiga-events - {{ TAIGA_EVENTS_SERVICE }}
{% include 'roles/docker-compose/templates/volumes.yml.j2' %} {% include 'roles/docker-compose/templates/volumes.yml.j2' %}
static-data: static-data:
media-data: media-data:

View File

@@ -1,27 +1,51 @@
# General # General
application_id: "web-app-taiga" application_id: "web-app-taiga"
database_type: "postgres" database_type: "postgres"
js_application_name: "Taiga" js_application_name: "Taiga"
entity_name: "{{ application_id | get_entity_name }}"
# Docker # Docker
docker_repository_address: "https://github.com/taigaio/taiga-docker" docker_repository_address: "https://github.com/taigaio/taiga-docker"
docker_pull_git_repository: true docker_pull_git_repository: true
# Taiga # Taiga
## General
TAIGA_EMAIL_BACKEND: "{{ 'smtp' if SYSTEM_EMAIL.SMTP else 'console' }}" ## use an SMTP server or display the emails in the console (either "smtp" or "console")
## User
TAIGA_SUPERUSER_NAME: "{{ users.administrator.username }}"
TAIGA_SUPERUSER_PASSWORD: "{{ users.administrator.password }}"
TAIGA_SUPERUSER_EMAIL: "{{ users.administrator.email }}"
## OIDC
TAIGA_OIDC_ENABLED: "{{ applications | get_app_conf(application_id, 'features.oidc') }}" TAIGA_OIDC_ENABLED: "{{ applications | get_app_conf(application_id, 'features.oidc') }}"
TAIGA_OIDC_FLAVOR: "{{ applications | get_app_conf(application_id, 'oidc.flavor') }}" TAIGA_OIDC_FLAVOR: "{{ applications | get_app_conf(application_id, 'oidc.flavor') }}"
TAIGA_FLAVOR_ROBROTHERAM: "{{ TAIGA_OIDC_FLAVOR == 'robrotheram' }}" TAIGA_FLAVOR_ROBROTHERAM: "{{ TAIGA_OIDC_FLAVOR == 'robrotheram' }}"
TAIGA_ROBROTHERAM_ENABLED: "{{ TAIGA_OIDC_ENABLED and TAIGA_FLAVOR_ROBROTHERAM }}" TAIGA_ROBROTHERAM_ENABLED: "{{ TAIGA_OIDC_ENABLED and TAIGA_FLAVOR_ROBROTHERAM }}"
TAIGA_FLAVOR_TAIGAIO: "{{ TAIGA_OIDC_FLAVOR == 'taigaio' }}" TAIGA_FLAVOR_TAIGAIO: "{{ TAIGA_OIDC_FLAVOR == 'taigaio' }}"
TAIGA_TAIGAIO_ENABLED: "{{ TAIGA_OIDC_ENABLED and TAIGA_FLAVOR_TAIGAIO }}" TAIGA_TAIGAIO_ENABLED: "{{ TAIGA_OIDC_ENABLED and TAIGA_FLAVOR_TAIGAIO }}"
TAIGA_EMAIL_BACKEND: "{{ 'smtp' if SYSTEM_EMAIL.SMTP else 'console' }}" ## use an SMTP server or display the emails in the console (either "smtp" or "console")
## Docker
TAIGA_DOCKER_COMPOSE_INIT_PATH: "{{ [ docker_compose.directories.instance,'docker-compose-inits.yml' ] | path_join }}" TAIGA_DOCKER_COMPOSE_INIT_PATH: "{{ [ docker_compose.directories.instance,'docker-compose-inits.yml' ] | path_join }}"
TAIGA_DOCKER_COMPOSE_PATH: "{{ [ docker_compose.directories.instance,'docker-compose.yml' ] | path_join }}" TAIGA_DOCKER_COMPOSE_PATH: "{{ [ docker_compose.directories.instance,'docker-compose.yml' ] | path_join }}"
TAIGA_DOCKER_IMAGE_BACKEND: "{{ 'robrotheram/taiga-back-openid' if TAIGA_ROBROTHERAM_ENABLED else 'taigaio/taiga-back' }}" TAIGA_DOCKER_IMAGE_BACKEND: "{{ 'robrotheram/taiga-back-openid' if TAIGA_ROBROTHERAM_ENABLED else 'taigaio/taiga-back' }}"
TAIGA_DOCKER_IMAGE_FRONTEND: "{{ 'robrotheram/taiga-front-openid' if TAIGA_ROBROTHERAM_ENABLED else 'taigaio/taiga-front' }}" TAIGA_DOCKER_IMAGE_FRONTEND: "{{ 'robrotheram/taiga-front-openid' if TAIGA_ROBROTHERAM_ENABLED else 'taigaio/taiga-front' }}"
TAIGA_FRONTEND_CONF_PATH: "{{ [ docker_compose.directories.config,'conf.json' ] | path_join }}" TAIGA_FRONTEND_CONF_PATH: "{{ [ docker_compose.directories.config,'conf.json' ] | path_join }}"
TAIGA_VERSION: "{{ applications | get_app_conf(application_id, 'docker.services.taiga.version') }}" TAIGA_VERSION: "{{ applications | get_app_conf(application_id, 'docker.services.taiga.version') }}"
TAIGA_SUPERUSER_NAME: "{{ users.administrator.username }}"
TAIGA_SUPERUSER_PASSWORD: "{{ users.administrator.password }}" ### Backend
TAIGA_SUPERUSER_EMAIL: "{{ users.administrator.email }}" TAIGA_SERVICE: "{{ entity_name }}"
TAIGA_CONTAINER: "{{ entity_name }}"
TAIGA_VOLUME_MEDIA: "/taiga-back/media"
TAIGA_VOLUME_STATIC: "/taiga-back/static"
## Services
TAIGA_MANAGER_SERVICE: "manager"
TAIGA_ASYNC_SERVICE: "async"
TAIGA_ASYNC_RABBITMQ_SERVICE: "async-rabbitmq"
TAIGA_EVENTS_RABBITMQ_SERVICE: "events-rabbitmq"
TAIGA_FRONT_SERVICE: "front"
TAIGA_EVENTS_SERVICE: "events"
TAIGA_SETTING_FILES: ['urls','local'] TAIGA_SETTING_FILES: ['urls','local']