diff --git a/.gitignore b/.gitignore index 37f4e251..13fc46fe 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,5 @@ api/tacticalrmm/accounts/management/commands/random_data.py versioninfo.go resource.syso htmlcov/ +docker-compose.override.yml +docker-compose.dev.yml \ No newline at end of file diff --git a/docker/api/dockerfile b/docker/api/dockerfile deleted file mode 100644 index bf96dbfc..00000000 --- a/docker/api/dockerfile +++ /dev/null @@ -1,46 +0,0 @@ -FROM tiangolo/uwsgi-nginx:python3.8 - -WORKDIR /app - -ARG DJANGO_SEKRET -ARG DJANGO_DEBUG -ARG POSTGRES_USER -ARG POSTGRES_PASS -ARG POSTGRES_HOST -ARG SALT_HOST -ARG SALT_USER -ARG SALT_PASS -ARG REDIS_HOST -ARG MESH_USER -ARG MESH_HOST -ARG MESH_TOKEN_KEY -ARG APP_HOST -ARG API_HOST -ARG ADMIN_URL - -EXPOSE 80 - -RUN apt-get update && apt-get install -y gettext-base wget ca-certificates -COPY ./api/tacticalrmm/requirements.txt . -RUN pip install --upgrade pip -RUN pip install --no-cache-dir setuptools==49.6.0 wheel==0.35.1 -RUN pip install --no-cache-dir -r requirements.txt -RUN wget https://golang.org/dl/go1.15.linux-amd64.tar.gz -P /tmp -COPY ./api/tacticalrmm/ . -COPY ./scripts/ /scripts -COPY ./docker/api/prestart.sh . -COPY ./docker/api/uwsgi.ini . -COPY ./docker/api/api.conf /app/api.conf.tmp -COPY ./api/tacticalrmm/core/goinstaller/bin/goversioninfo /usr/local/bin/goversioninfo -RUN envsubst '\$APP_HOST, \$API_HOST' < /app/api.conf.tmp > /app/nginx.conf && \ - rm /app/api.conf.tmp -COPY ./docker/api/local_settings.py.keep ./tacticalrmm/local_settings.py.tmp -RUN envsubst < /app/tacticalrmm/local_settings.py.tmp > /app/tacticalrmm/local_settings.py && rm /app/tacticalrmm/local_settings.py.tmp - -RUN tar -xzf /tmp/go1.15.linux-amd64.tar.gz -C /tmp && \ - mkdir /usr/local/rmmgo && \ - mv /tmp/go /usr/local/rmmgo/ && \ - rm -rf /tmp/go - -RUN /usr/local/rmmgo/go/bin/go get github.com/josephspurrier/goversioninfo/cmd/goversioninfo && \ - chmod +x /usr/local/bin/goversioninfo diff --git a/docker/api/local_settings.py.keep b/docker/api/local_settings.py.keep deleted file mode 100644 index 98d06f86..00000000 --- a/docker/api/local_settings.py.keep +++ /dev/null @@ -1,47 +0,0 @@ -SECRET_KEY = '${DJANGO_SEKRET}' - -ALLOWED_HOSTS = ['${API_HOST}'] - -ADMIN_URL = "${ADMIN_URL}" - -CORS_ORIGIN_WHITELIST = ["https://${APP_HOST}",] - -DEBUG = ${DJANGO_DEBUG} - -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.postgresql', - 'NAME': 'tacticalrmm', - 'USER': '${POSTGRES_USER}', - 'PASSWORD': '${POSTGRES_PASS}', - 'HOST': '${POSTGRES_HOST}', - 'PORT': '5432', - } -} - -REST_FRAMEWORK = { - 'DATETIME_FORMAT': "%b-%d-%Y - %H:%M", - - 'DEFAULT_PERMISSION_CLASSES': ( - 'rest_framework.permissions.IsAuthenticated', - ), - 'DEFAULT_AUTHENTICATION_CLASSES': ( - 'knox.auth.TokenAuthentication', - ), -} - -if not DEBUG: - REST_FRAMEWORK.update({ - 'DEFAULT_RENDERER_CLASSES': ( - 'rest_framework.renderers.JSONRenderer', - ) - }) - -SALT_USERNAME = "${SALT_USER}" -SALT_PASSWORD = "${SALT_PASS}" -MESH_USERNAME = "${MESH_USER}" -MESH_SITE = "https://${MESH_HOST}" -MESH_WS_URL="ws://meshcentral:443" -MESH_TOKEN_KEY = "${MESH_TOKEN_KEY}" -REDIS_HOST = "${REDIS_HOST}" -SALT_HOST = "${SALT_HOST}" \ No newline at end of file diff --git a/docker/api/prestart.sh b/docker/api/prestart.sh deleted file mode 100644 index c15a3146..00000000 --- a/docker/api/prestart.sh +++ /dev/null @@ -1,10 +0,0 @@ -#! /usr/bin/env bash - -sleep 10 -python manage.py migrate --no-input -python manage.py collectstatic --no-input -python manage.py initial_db_setup -python manage.py initial_mesh_setup -python manage.py load_chocos -python manage.py fix_salt_key -python manage.py load_community_scripts diff --git a/docker/api/uwsgi.ini b/docker/api/uwsgi.ini deleted file mode 100644 index e9e26e1b..00000000 --- a/docker/api/uwsgi.ini +++ /dev/null @@ -1,14 +0,0 @@ -[uwsgi] - -logto = /app/tacticalrmm/private/log/uwsgi.log -chdir = /app -wsgi-file = tacticalrmm/wsgi.py -master = true -processes = 4 -threads = 2 -socket = /app/tacticalrmm.sock -# clear environment on exit -vacuum = true -die-on-term = true -max-requests = 500 -max-requests-delta = 1000 diff --git a/docker/nginx-proxy/api.conf b/docker/containers/frontend-proxy/api.conf similarity index 100% rename from docker/nginx-proxy/api.conf rename to docker/containers/frontend-proxy/api.conf diff --git a/docker/nginx-proxy/app.conf b/docker/containers/frontend-proxy/app.conf similarity index 100% rename from docker/nginx-proxy/app.conf rename to docker/containers/frontend-proxy/app.conf diff --git a/docker/nginx-proxy/cert/.gitkeep b/docker/containers/frontend-proxy/cert/.gitkeep similarity index 100% rename from docker/nginx-proxy/cert/.gitkeep rename to docker/containers/frontend-proxy/cert/.gitkeep diff --git a/docker/nginx-proxy/dockerfile b/docker/containers/frontend-proxy/dockerfile similarity index 100% rename from docker/nginx-proxy/dockerfile rename to docker/containers/frontend-proxy/dockerfile diff --git a/docker/nginx-proxy/mesh.conf b/docker/containers/frontend-proxy/mesh.conf similarity index 100% rename from docker/nginx-proxy/mesh.conf rename to docker/containers/frontend-proxy/mesh.conf diff --git a/docker/app/.env.keep b/docker/containers/frontend/.env.keep similarity index 100% rename from docker/app/.env.keep rename to docker/containers/frontend/.env.keep diff --git a/docker/app/app.conf b/docker/containers/frontend/app.conf similarity index 100% rename from docker/app/app.conf rename to docker/containers/frontend/app.conf diff --git a/docker/app/dockerfile b/docker/containers/frontend/dockerfile similarity index 100% rename from docker/app/dockerfile rename to docker/containers/frontend/dockerfile diff --git a/docker/meshcentral/config.json b/docker/containers/meshcentral/config.json similarity index 100% rename from docker/meshcentral/config.json rename to docker/containers/meshcentral/config.json diff --git a/docker/meshcentral/dockerfile b/docker/containers/meshcentral/dockerfile similarity index 100% rename from docker/meshcentral/dockerfile rename to docker/containers/meshcentral/dockerfile diff --git a/docker/meshcentral/entry.sh b/docker/containers/meshcentral/entry.sh similarity index 100% rename from docker/meshcentral/entry.sh rename to docker/containers/meshcentral/entry.sh diff --git a/docker/salt/api.conf b/docker/containers/salt/api.conf similarity index 100% rename from docker/salt/api.conf rename to docker/containers/salt/api.conf diff --git a/docker/salt/dockerfile b/docker/containers/salt/dockerfile similarity index 100% rename from docker/salt/dockerfile rename to docker/containers/salt/dockerfile diff --git a/docker/salt/supervisor.conf b/docker/containers/salt/supervisor.conf similarity index 100% rename from docker/salt/supervisor.conf rename to docker/containers/salt/supervisor.conf diff --git a/docker/api/api.conf b/docker/containers/tactical/api.conf similarity index 100% rename from docker/api/api.conf rename to docker/containers/tactical/api.conf diff --git a/docker/containers/tactical/dockerfile b/docker/containers/tactical/dockerfile new file mode 100644 index 00000000..7beb9cd8 --- /dev/null +++ b/docker/containers/tactical/dockerfile @@ -0,0 +1,46 @@ +FROM python:3.8-slim AS builder + +ARG DEBIAN_FRONTEND=noninteractive +ARG BUILD_DATE + +ENV TACTICAL_DIR /opt/tactical/ +ENV TACTICAL_TMP_DIR /tmp/tacticalrmm/ +ENV TACTICAL_READY_FILE ${TACTICAL_DIR}/tmp/tactical.ready +ENV TACTICAL_USER tactical + +SHELL ["/bin/bash", "-e", "-o", "pipefail", "-c"] + +# install tactical +COPY docker/containers/tactical/setup.sh /tmp +COPY api/tacticalrmm/requirements.txt ${TACTICAL_TMP_DIR} +RUN chmod +x /tmp/setup.sh && \ + /tmp/setup.sh install + +FROM python:3.8-slim + +ARG DEBIAN_FRONTEND=noninteractive +ARG BUILD_DATE + +ENV TACTICAL_DIR /opt/tactical/ +ENV TACTICAL_TMP_DIR /tmp/tacticalrmm/ +ENV TACTICAL_SCRIPTS_DIR ${TACTICAL_DIR}/scripts/ +ENV TACTICAL_GO_DIR /usr/local/rmmgo/ +ENV TACTICAL_READY_FILE ${TACTICAL_DIR}/tmp/tactical.ready +ENV TACTICAL_USER tactical + +COPY docker/containers/tactical/setup.sh /tmp +RUN chmod +x /tmp/setup.sh; \ + /tmp/setup.sh run + +COPY from=builder /tmp/go ${TACTICAL_GO_DIR} +COPY from=builder ${TACTICAL_TMP_DIR}/env ${TACTICAL_DIR} +COPY api/tacticalrmm/ ${TACTICAL_DIR} +COPY scripts/ ${TACTICAL_SCRIPTS_DIR} +COPY api/tacticalrmm/core/goinstaller/bin/goversioninfo /usr/local/bin/goversioninfo + +# docker init +COPY containers/backend/docker-entrypoint.sh / +RUN chmod +x /docker-entrypoint.sh +ENTRYPOINT ["/docker-entrypoint.sh"] + +WORKDIR ${TACTICAL_DIR} diff --git a/docker/containers/tactical/entrypoint.sh b/docker/containers/tactical/entrypoint.sh new file mode 100644 index 00000000..af4b2a39 --- /dev/null +++ b/docker/containers/tactical/entrypoint.sh @@ -0,0 +1,142 @@ +#!/usr/bin/env bash + +set -e + +: "${POSTGRES_HOST:=tactical-postgres}" +: "${POSTGRESQL_PORT:=5432}" +: "${POSTGRES_USER:=tactical}" +: "${POSTGRES_PASS:=tactical}" +: "${POSTGRES_DB:=tactical}" +: "${SALT_HOST:=tactical-salt}" +: "${SALT_USER:=saltapi}" +: "${MESH_CONTAINER:=tactical-meshcentral}" +: "${MESH_USER:=meshcentral}" +: "${MESH_PASS:=meshcentralpass}" +: "${MESH_HOST:=tactical-meshcentral}" +: "${API_HOST:=tactical-backend}" +: "${APP_HOST:=tactical-frontend}" +: "${REDIS_HOST:=tactical-redis}" + + +function check_tactical_ready { + sleep 15 + until [ -f "${TACTICAL_READY_FILE}" ]; do + echo "waiting for init container to finish install or update..." + sleep 10 + done +} + +# tactical-init +if [ "$1" = 'tactical-init' ]; then + test -f "${TACTICAL_READY_FILE}" && rm "${TACTICAL_READY_FILE}" + + until (echo > /dev/tcp/"${POSTGRES_HOST}"/"${POSTGRES_PORT}") &> /dev/null; do + echo "waiting for postgresql server to be ready..." + sleep 5 + done + + cd "${TACTICAL_DIR}" + + # configure django settings + DJANGO_SEKRET=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 80 | head -n 1) + SALT_PASS=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 20 | head -n 1) + ADMINURL=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 70 | head -n 1) + + localvars="$(cat << EOF +SECRET_KEY = '${DJANGO_SEKRET}' + +DEBUG = False + +ALLOWED_HOSTS = ['${API_HOST}'] + +ADMIN_URL = '${ADMINURL}/' + +CORS_ORIGIN_WHITELIST = [ + 'https://${APP_HOST}' +] + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.postgresql', + 'NAME': '${POSTGRES_DB}', + 'USER': '${POSTGRES_USER}', + 'PASSWORD': '${POSTGRES_PASS}', + 'HOST': '${POSTGRES_HOST}', + 'PORT': '${POSTGRES_PORT}', + } +} + +REST_FRAMEWORK = { + 'DATETIME_FORMAT': '%b-%d-%Y - %H:%M', + + 'DEFAULT_PERMISSION_CLASSES': ( + 'rest_framework.permissions.IsAuthenticated', + ), + 'DEFAULT_AUTHENTICATION_CLASSES': ( + 'knox.auth.TokenAuthentication', + ), +} + +if not DEBUG: + REST_FRAMEWORK.update({ + 'DEFAULT_RENDERER_CLASSES': ( + 'rest_framework.renderers.JSONRenderer', + ) + }) + +SALT_USERNAME = '${SALT_USER}' +SALT_PASSWORD = '${SALT_PASS}' +SALT_HOST = '${SALT_HOST}' +MESH_USERNAME = '${MESH_USER}' +MESH_SITE = 'https://${MESH_HOST}' +REDIS_HOST = '${REDIS_HOST}' +MESH_WS_URL = 'ws://${MESH_CONTAINER}:443' +EOF +)" + + echo "${localvars}" > ${TACTICAL_DIR}/tacticalrmm/local_settings.py + + # check mesh setup and wait for mesh token + if [ ! test -f "${TACTICAL_DIR}/mesh_token" ]; then + until (test -f "${TACTICAL_DIR}/mesh_token") do + echo "waiting for mesh token to be generated..." + sleep 5 + done + + # run migrations and init scripts + python manage.py migrate --no-input + python manage.py collectstatic --no-input + python manage.py initial_db_setup + python manage.py initial_mesh_setup + python manage.py load_chocos + python manage.py load_community_scripts + + # chown everything to tactical user + chown -R "${TACTICAL_USER}":"${TACTICAL_USER}" "${TACTICAL_DIR}" + + # create install ready file + su -c "echo 'tactical-init' > ${TACTICAL_READY_FILE}" "${TACTICAL_USER}" + +fi + +# backend container +if [ "$1" = 'tactical-backend' ]; then + check_tactical_ready + +# Prepare log files and start outputting logs to stdout +touch ${TACTICAL_DIR}/tacticalrmm/logs/gunicorn.log +touch ${TACTICAL_DIR}/tacticalrmm/logs/gunicorn-access.log +tail -n 0 -f ${TACTICAL_DIR}/tacticalrmm/logs/gunicorn*.log & + +export DJANGO_SETTINGS_MODULE=tactical.settings + +exec gunicorn tacticalrmm.wsgi:application \ + --name tactical-backend \ + --bind 0.0.0.0:80 \ + --workers 5 \ + --log-level=info \ + --log-file=${TACTICAL_DIR}/tacticalrmm/logs/gunicorn.log \ + --access-logfile=${TACTICAL_DIR}/tacticalrmm/logs/gunicorn-access.log \ +"$@" + +fi \ No newline at end of file diff --git a/docker/containers/tactical/setup.sh b/docker/containers/tactical/setup.sh new file mode 100644 index 00000000..e0154da1 --- /dev/null +++ b/docker/containers/tactical/setup.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +set -e + +# install tactical +groupadd -g 1000 "${TACTICAL_USER}" +useradd -M -d "${TACTICAL_DIR}" -s /bin/bash -u 1000 -g 1000 "${TACTICAL_USER}" + +if [ "$1" = 'install' ]; then + apt-get update + apt-get upgrade -y + apt-get install -y --no-install-recommends wget ca-certificates gcc libc6-dev + rm -rf /var/lib/apt/lists/* + pip install --upgrade pip + pip install --no-cache-dir virtualenv && python -m virtualenv ${TACTICAL_TMP_DIR}/env + ${TACTICAL_TMP_DIR}/env/bin/pip install --no-cache-dir setuptools wheel gunicorn + ${TACTICAL_TMP_DIR}/env/bin/pip install --no-cache-dir -r ${TACTICAL_TMP_DIR}/requirements.txt + wget https://golang.org/dl/go1.15.linux-amd64.tar.gz -P /tmp + tar -xzf /tmp/go1.15.linux-amd64.tar.gz -C /tmp +fi + +if [ "$1" = 'run' ]; then + mkdir /usr/local/rmmgo + +fi diff --git a/docker/docker-compose.override.yml b/docker/docker-compose.override.yml deleted file mode 100644 index cdbbd327..00000000 --- a/docker/docker-compose.override.yml +++ /dev/null @@ -1,143 +0,0 @@ -# FOR PROD -version: "3.7" - -volumes: - # Gives access to the debug log for celery tasks - debug_log: - -services: - # Container that hosts Vue frontend - app: - build: - context: .. - args: - - APP_HOST=${APP_HOST} - - API_HOST=${API_HOST} - dockerfile: "./docker/app/dockerfile" - networks: - - proxy - - # Container for Django backend - api: - build: - context: .. - dockerfile: "./docker/api/dockerfile" - args: - - DJANGO_SEKRET=${DJANGO_SEKRET} - - DJANGO_DEBUG=${DJANGO_DEBUG} - - POSTGRES_USER=${POSTGRES_USER} - - POSTGRES_PASS=${POSTGRES_PASS} - - POSTGRES_HOST=${POSTGRES_HOST} - - SALT_PASS=${SALT_PASS} - - SALT_USER=${SALT_USER} - - SALT_HOST=${SALT_HOST} - - REDIS_HOST=${REDIS_HOST} - - MESH_USER=${MESH_USER} - - MESH_HOST=${MESH_HOST} - - APP_HOST=${APP_HOST} - - API_HOST=${API_HOST} - - ADMIN_URL=${ADMIN_URL} - networks: - - proxy - - database - - redis - volumes: - - scripts:/srv - - mesh_token:/token - - debug_log:/app/tacticalrmm/private/log - depends_on: - - db - - meshcentral - - # Container for Celery worker service - celery-service: - build: - context: .. - dockerfile: "./docker/api/dockerfile" - args: - - DJANGO_SEKRET=${DJANGO_SEKRET} - - DJANGO_DEBUG=${DJANGO_DEBUG} - - POSTGRES_USER=${POSTGRES_USER} - - POSTGRES_PASS=${POSTGRES_PASS} - - POSTGRES_HOST=${POSTGRES_HOST} - - SALT_PASS=${SALT_PASS} - - SALT_USER=${SALT_USER} - - SALT_HOST=${SALT_HOST} - - REDIS_HOST=${REDIS_HOST} - - MESH_USER=${MESH_USER} - - MESH_HOST=${MESH_HOST} - - APP_HOST=${APP_HOST} - - API_HOST=${API_HOST} - - ADMIN_URL=${ADMIN_URL} - command: celery -A tacticalrmm worker -l debug - networks: - - redis - - proxy - - database - volumes: - - debug_log:/app/tacticalrmm/private/log - depends_on: - - db - - redis - - # Container for Celery beat service - celery-beat: - build: - context: .. - dockerfile: "./docker/api/dockerfile" - args: - - DJANGO_SEKRET=${DJANGO_SEKRET} - - DJANGO_DEBUG=${DJANGO_DEBUG} - - POSTGRES_USER=${POSTGRES_USER} - - POSTGRES_PASS=${POSTGRES_PASS} - - POSTGRES_HOST=${POSTGRES_HOST} - - SALT_PASS=${SALT_PASS} - - SALT_USER=${SALT_USER} - - SALT_HOST=${SALT_HOST} - - REDIS_HOST=${REDIS_HOST} - - MESH_USER=${MESH_USER} - - MESH_HOST=${MESH_HOST} - - APP_HOST=${APP_HOST} - - API_HOST=${API_HOST} - - ADMIN_URL=${ADMIN_URL} - command: celery -A tacticalrmm beat -l debug - networks: - - redis - - proxy - - database - volumes: - - debug_log:/app/tacticalrmm/private/log - depends_on: - - db - - redis - - # Container for Celery Winupdate tasks - celery-winupdate: - build: - context: .. - dockerfile: "./docker/api/dockerfile" - args: - - DJANGO_SEKRET=${DJANGO_SEKRET} - - DJANGO_DEBUG=${DJANGO_DEBUG} - - POSTGRES_USER=${POSTGRES_USER} - - POSTGRES_PASS=${POSTGRES_PASS} - - POSTGRES_HOST=${POSTGRES_HOST} - - SALT_PASS=${SALT_PASS} - - SALT_USER=${SALT_USER} - - SALT_HOST=${SALT_HOST} - - REDIS_HOST=${REDIS_HOST} - - MESH_USER=${MESH_USER} - - MESH_HOST=${MESH_HOST} - - APP_HOST=${APP_HOST} - - API_HOST=${API_HOST} - - ADMIN_URL=${ADMIN_URL} - command: celery -A tacticalrmm worker -Q wupdate -l debug - networks: - - redis - - proxy - - database - volumes: - - debug_log:/app/tacticalrmm/private/log - depends_on: - - db - - redis diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index c1518099..a2b12741 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -1,6 +1,6 @@ version: "3.7" -# Userdefined Networks +# networks networks: proxy: driver: bridge @@ -8,102 +8,187 @@ networks: driver: default config: - subnet: 172.20.0.0/24 - database: + api-db: redis: - mesh-mongodb: + mesh-db: -# Docker managed persistent volumes +# docker managed persistent volumes volumes: - # Volume for userdefined scripts - scripts: - # Volume for mesh token initial setup - mesh_token: - # Used to make the salt data persistent + tactical_data: salt_data: - # Makes Postgres data persistent - postgres_data13: - # Makes mesh central data persistent + postgres_data: mongo_data: services: - # Postgres Database for API service - db: + # postgres database for api service + tactical-postgres: image: postgres:13 environment: POSTGRES_DB: tacticalrmm POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASS} volumes: - - postgres_data13:/var/lib/postgresql/data + - postgres_data:/var/lib/postgresql/data networks: - - database + - api-db - # Redis Container for Celery tasks - redis: + # redis container for celery tasks + tactical-redis: image: redis networks: - redis - # Salt Master and API - salt: - build: - context: .. - dockerfile: ./docker/salt/dockerfile - args: - - SALT_USER=${SALT_USER} - - SALT_PASS=${SALT_PASS} + tactical-init: + image: ${IMAGE_REPO}:tactical-${VERSION} + restart: on-failure + command: ["tactical-init"] + environment: + POSTGRES_DB: tacticalrmm + POSTGRES_USER: ${POSTGRES_USER} + POSTGRES_PASSWORD: ${POSTGRES_PASS} + APP_HOST: ${APP_HOST} + API_HOST: ${API_HOST} + MESH_HOST: ${MESH_HOST} + depends_on: + - tactical-postgres + - tactical-meshcentral + networks: + - api-db + - proxy + volumes: + - tacticalrmm:/opt/tactical + + # salt master and api + tactical-salt: + image: {IMAGE_REPO}:tactical-salt-${VERSION} + restart: always ports: - "4505:4505" - "4506:4506" volumes: - - scripts:/srv + - tacticalrmm:/opt/tactical - salt_data:/etc/salt networks: - proxy # MeshCentral Container - meshcentral: - build: - context: ./meshcentral - args: - - MESH_HOST=${MESH_HOST} - - MESH_USER=${MESH_USER} - - MESH_PASS=${MESH_PASS} - - EMAIL_USER=${EMAIL_USER} - - MONGODB_USER=${MONGODB_USER} - - MONGODB_PASSWORD=${MONGODB_PASSWORD} + tactical-meshcentral: + image: ${IMAGE_REPO}:tactical-meshcentral-${VERSION} + restart: always networks: - proxy - - mesh-mongodb + - mesh-db volumes: - - mesh_token:/token + - tacticalrmm:/opt/tactical depends_on: - - mesh-mongodb - - nginx-proxy + - tactical-mongodb # MongoDB Container for MeshCentral - mesh-mongodb: + tactical-mongodb: image: mongo environment: MONGO_INITDB_ROOT_USERNAME: ${MONGODB_USER} MONGO_INITDB_ROOT_PASSWORD: ${MONGODB_PASSWORD} MONGO_INITDB_DATABASE: meshcentral networks: - - mesh-mongodb + - mesh-db volumes: - mongo_data:/data - # Nginx Container Reverse Proxy that handles all http/https traffic - nginx-proxy: - build: - context: ./nginx-proxy - args: - - APP_HOST=${APP_HOST} - - API_HOST=${API_HOST} - - MESH_HOST=${MESH_HOST} + # Container that hosts Vue frontend + tactical-frontend: + image: ${IMAGE_REPO}:tactical-frontend-${VERSION} + command: exec /usr/sbin/nginx -g 'daemon off;' + restart: always + environment: + - APP_HOST=${APP_HOST} + - API_HOST=${API_HOST} + volumes: + - tactical_data:/opt/tactical ports: - "80:80" - "443:443" networks: proxy: ipv4_address: 172.20.0.20 + + # Container for Django backend + tactical-backend: + image: ${IMAGE_REPO}:tactical-${VERSION} + command: ["tactical-backend"] + restart: always + environment: + - APP_HOST=${APP_HOST} + - API_HOST=${API_HOST} + - MESH_HOST=${MESH_HOST} + networks: + - proxy + - api-db + - redis + volumes: + - tactical_data:/opt/tactical + depends_on: + - tactical-postgres + - tactical-meshcentral + + tactical-nginx: + # Container for tactical proxy + image: ${IMAGE_REPO}:tactical-${VERSION} + command: ["tactical-nginx"] + restart: always + environment: + - APP_HOST=${APP_HOST} + - API_HOST=${API_HOST} + - MESH_HOST=${MESH_HOST} + networks: + - proxy + volumes: + - tactical_data:/opt/tactical + depends_on: + - tactical-postgres + - tactical-meshcentral + + # container for celery worker service + tactical-celery: + image: ${IMAGE_REPO}:tactical-${VERSION} + command: ["tactical-celery"] + restart: always + networks: + - redis + - proxy + - api-db + volumes: + - tactical_data:/opt/tactical + depends_on: + - tactical-postgres + - tactical-redis + + # container for celery beat service + tactical-celerybeat: + image: ${IMAGE_REPO}:tactical-${VERSION} + command: ["tactical-celerybeat"] + restart: always + networks: + - redis + - api-db + - database + volumes: + - tactical_data:/opt/tactical + depends_on: + - tactical-postgres + - tactical-redis + + # container for celery winupdate tasks + tactical-celerywinupdate: + image: ${IMAGE_REPO}:tactical-${VERSION} + command: ["tactical-celerywinupdate"] + restart: always + networks: + - redis + - proxy + - api-db + volumes: + - tactical_data:/opt/tactical + depends_on: + - tactical-postgres + - tactical-redis