From 05f5f17b16e7b6cb01a488cedfc02e279f3d33c1 Mon Sep 17 00:00:00 2001 From: DariusIII Date: Thu, 5 Mar 2026 15:14:04 +0100 Subject: [PATCH] Update docker management --- .dockerignore | 28 ++++- .env.example | 39 +++++++ DOCKER.md | 173 +++++++++++++++++++++++++++++++ Dockerfile | 6 +- Makefile | 182 +++++++++++++++++++++++++++++++++ docker-compose.yml.dist | 132 ------------------------ docker-compose.yml.prod-dist | 193 +++++++++++++++++++---------------- docker/8.4/Dockerfile | 66 ------------ docker/8.4/README.md | 91 ----------------- docker/8.4/nginx.conf | 50 --------- docker/8.4/php.ini | 12 --- docker/8.4/scheduler | 1 - docker/8.4/start-container | 22 ---- docker/8.4/supervisord.conf | 45 -------- docker/8.5/php.ini | 2 - docker/8.5/supervisord.conf | 4 +- 16 files changed, 527 insertions(+), 519 deletions(-) create mode 100644 DOCKER.md create mode 100644 Makefile delete mode 100644 docker-compose.yml.dist delete mode 100644 docker/8.4/Dockerfile delete mode 100644 docker/8.4/README.md delete mode 100644 docker/8.4/nginx.conf delete mode 100644 docker/8.4/php.ini delete mode 100644 docker/8.4/scheduler delete mode 100644 docker/8.4/start-container delete mode 100644 docker/8.4/supervisord.conf diff --git a/.dockerignore b/.dockerignore index c67b45e78..a27262eb5 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,7 +1,25 @@ vendor/ -docker/mariadb-data -docker/redis-data -docker/manticore-data +node_modules/ +.git/ +tests/ +docker/ +__pycache__/ +.idea/ +.vscode/ + +storage/logs/ +storage/nzb/ +storage/covers/ + +public/build/ + .env -storage/nzb -storage/covers +.env.* +*.log +phpstan* +.phpunit* + +AGENTS.md +CONTRIBUTING.md +DOCKER.md +CAPTCHA_CONFIGURATION.md diff --git a/.env.example b/.env.example index 2657685c4..e590d2aca 100644 --- a/.env.example +++ b/.env.example @@ -235,3 +235,42 @@ TMUX_USE_POWERLINE=true TMUX_USE_NERD_FONTS=true TMUX_TERMINAL=tmux-256color +# ────────────────────────────────────────────────────────────── +# Docker / Sail +# ────────────────────────────────────────────────────────────── +# These are only used when running via Docker (./sail or make). +# For native installs, leave them commented out. + +# Which Compose profiles to activate (comma-separated). +# Use "manticore" or "elasticsearch" to match SEARCH_DRIVER above. +COMPOSE_PROFILES=manticore + +# Sail service name (should match docker-compose.yml) +APP_SERVICE=laravel.test + +# Port mapping: host → container +APP_PORT=80 +VITE_PORT=5173 +FORWARD_DB_PORT=3306 +FORWARD_REDIS_PORT=6379 +FORWARD_MAILPIT_PORT=1025 +FORWARD_MAILPIT_DASHBOARD_PORT=8025 + +# Host UID/GID — avoids file-permission issues with bind mounts. +# On Linux/WSL run: id -u and id -g +WWWUSER=1000 +WWWGROUP=1000 + +# Xdebug (off | debug | develop | coverage | profile) +SAIL_XDEBUG_MODE=off + +# ── Docker service hostnames ───────────────────────────────── +# Uncomment these when running inside Docker so the app resolves +# to the correct container names instead of localhost / 127.0.0.1. +#DB_HOST=mariadb +#REDIS_HOST=redis +#MANTICORESEARCH_HOST=manticore +#ELASTICSEARCH_HOST=elasticsearch +#MAIL_HOST=mailpit +#MAIL_PORT=1025 + diff --git a/DOCKER.md b/DOCKER.md new file mode 100644 index 000000000..88d4c3721 --- /dev/null +++ b/DOCKER.md @@ -0,0 +1,173 @@ +# Docker Development Environment + +> Docker / Sail setup for NNTmux — a Laravel 12 Usenet indexer. + +## Prerequisites + +- Docker & Docker Compose v2+ +- A GitHub (scopeless) token for Composer private packages +- [Laravel Sail](https://laravel.com/docs/12.x/sail) (included as a dev dependency) + +## Quick Start + +```bash +# 1. Copy and configure your environment +cp .env.example .env +# Edit .env — set DB credentials, COMPOSER_AUTH, and uncomment the +# "Docker service hostnames" block at the bottom. + +# 2. Build and start +make build +make up + +# 3. Install NNTmux (first run only) +make artisan cmd="nntmux:install" + +# 4. Build frontend assets +make npm-build +``` + +## Environment Configuration + +When running via Docker, uncomment the **Docker service hostnames** block +at the bottom of `.env` so the app resolves container names: + +```dotenv +DB_HOST=mariadb +REDIS_HOST=redis +MANTICORESEARCH_HOST=manticore +ELASTICSEARCH_HOST=elasticsearch +MAIL_HOST=mailpit +MAIL_PORT=1025 +``` + +### Search Engine Selection + +Set `COMPOSE_PROFILES` in `.env` to match your `SEARCH_DRIVER`: + +| `SEARCH_DRIVER` | `COMPOSE_PROFILES` | +|------------------|--------------------| +| `manticore` | `manticore` | +| `elasticsearch` | `elasticsearch` | + +Only the selected search service container will start. The other remains +dormant and consumes no resources. + +## Make Targets + +Run `make` or `make help` to see all targets: + +| Target | Description | +|---------------------|-------------------------------------------------------| +| `make up` | Start all services (detached) | +| `make down` | Stop all services | +| `make restart` | Restart all services | +| `make build` | Build the app image | +| `make rebuild` | Build from scratch (no cache) | +| `make pull` | Pull latest base images | +| `make update` | Pull + rebuild + restart | +| `make fresh` | **Destroy volumes**, rebuild, start clean (DATA LOSS) | +| `make shell` | Bash shell in the app container | +| `make root-shell` | Root bash shell in the app container | +| `make artisan cmd=` | Run any artisan command | +| `make tmux-start` | Start the NNTmux tmux processing engine | +| `make tmux-stop` | Stop the tmux processing engine | +| `make tmux-attach` | Attach to the running tmux session | +| `make horizon` | Show Horizon queue status | +| `make test` | Run PHPUnit tests (`filter=Name` optional) | +| `make pint` | Pint formatter on dirty files | +| `make npm-build` | `npm install` + `npm run build` | +| `make npm-dev` | Start Vite dev server | +| `make db` | MariaDB CLI session | +| `make redis-cli` | Redis CLI session | +| `make logs` | Tail all container logs | +| `make status` | Show container status | +| `make clean` | Prune stopped containers / dangling images | +| `make nuke` | **Remove ALL** project containers, images, volumes | + +You can also use `./sail` directly for anything not covered above — +unknown commands are passed through to `docker compose`. + +## Networking + +Sail creates a Docker network called `sail` with these default port mappings: + +| Service | Container Port | Host Port (default) | +|----------------|----------------|------------------------------------------| +| HTTP (nginx) | 80 | `APP_PORT` (80) | +| Vite | 5173 | `VITE_PORT` (5173) | +| MariaDB | 3306 | `FORWARD_DB_PORT` (3306) | +| Redis | 6379 | `FORWARD_REDIS_PORT` (6379) | +| Manticore SQL | 9306 | 9306 | +| Manticore HTTP | 9308 | 9308 | +| Elasticsearch | 9200 | 9200 | +| Mailpit SMTP | 1025 | `FORWARD_MAILPIT_PORT` (1025) | +| Mailpit Web | 8025 | `FORWARD_MAILPIT_DASHBOARD_PORT` (8025) | + +If a port is already in use on your host, change the corresponding +`FORWARD_*` / `APP_PORT` variable in `.env`. + +## Database + +On first run MariaDB creates a user/database from your `.env`: + +```dotenv +DB_USERNAME= +DB_PASSWORD= +DB_DATABASE=nntmux +``` + +Import an existing SQL dump or run `make artisan cmd="nntmux:install"` for +a fresh installation. + +## Backups + +Add this optional service to `docker-compose.yml` for automated MariaDB backups: + +```yaml + backup: + image: fradelg/mysql-cron-backup + depends_on: + - mariadb + restart: always + volumes: + - ./docker/backups:/backup + environment: + - MYSQL_USER=${DB_USERNAME} + - MYSQL_PASS=${DB_PASSWORD} + - MYSQL_DB=${DB_DATABASE} + - CRON_TIME=0 3 * * * + - MYSQL_HOST=mariadb + - MYSQL_PORT=3306 + - TIMEOUT=10s + - GZIP_LEVEL=9 + - MAX_BACKUPS=5 + - INIT_BACKUP=0 + - EXIT_BACKUP=1 + networks: + - sail +``` + +## Production + +For production deployments use `docker-compose.yml.prod-dist` as a starting +point. It includes separate `webapp`, `worker`, and `scheduler` services +and uses the root `Dockerfile` (FrankenPHP-based). + +```bash +cp docker-compose.yml.prod-dist docker-compose.yml +# Edit .env for production settings +docker compose up -d +``` + +## Troubleshooting + +| Problem | Solution | +|---------------------------------|-----------------------------------------------------------------------| +| Permission errors on storage/ | `make root-shell` then `chown -R sail:sail storage bootstrap/cache` | +| Port already in use | Change `APP_PORT`, `FORWARD_DB_PORT`, etc. in `.env` | +| Containers won't start | `make logs` to inspect, or `make rebuild` to start fresh | +| Stale images after upgrade | `make update` (pulls + rebuilds + restarts) | +| Need a completely clean slate | `make fresh` (destroys all volumes!) | +| supervisorctl not connecting | `make root-shell` then `supervisorctl status` to verify socket path | + diff --git a/Dockerfile b/Dockerfile index 13bb62ea6..ad67e42db 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ FROM composer:latest AS composer-base -FROM dunglas/frankenphp:1-php8.3 +FROM dunglas/frankenphp:1-php8.4 LABEL maintainer="PyRowMan" ENV SERVER_NAME=:${APP_PORT:-80} ARG MYSQL_CLIENT="mariadb-client" @@ -8,7 +8,7 @@ ARG MYSQL_CLIENT="mariadb-client" WORKDIR /app -COPY --from=node:21 /usr/local/ /usr/local/ +COPY --from=node:22 /usr/local/ /usr/local/ COPY --from=composer-base --link /usr/bin/composer /usr/bin/composer RUN apt update \ @@ -37,7 +37,7 @@ RUN docker-php-ext-install \ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" -COPY ./docker/8.3/php.ini "$PHP_INI_DIR/conf.d/custom-conf.ini" +COPY ./docker/8.5/php.ini "$PHP_INI_DIR/conf.d/custom-conf.ini" COPY --chmod=755 ./docker-entrypoint.sh /usr/local/bin/docker-entrypoint diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..fcd062d81 --- /dev/null +++ b/Makefile @@ -0,0 +1,182 @@ +# ────────────────────────────────────────────────────────────── +# NNTmux – Docker / Sail convenience targets +# ────────────────────────────────────────────────────────────── +# +# Run `make` or `make help` to see all available targets. +# See DOCKER.md for full documentation. +# ────────────────────────────────────────────────────────────── + +.DEFAULT_GOAL := help + +# Source SEARCH_DRIVER from .env and export as COMPOSE_PROFILES +# so the correct search engine container starts automatically. +-include .env +export COMPOSE_PROFILES ?= $(SEARCH_DRIVER) + +SAIL := ./sail +DOCKER_COMPOSE := docker compose + +# Colors +CYAN := \033[36m +GREEN := \033[32m +YELLOW := \033[33m +RESET := \033[0m + +# ── Lifecycle ──────────────────────────────────────────────── + +.PHONY: up +up: ## Start all services in the background + @$(SAIL) up -d + +.PHONY: down +down: ## Stop all services + @$(SAIL) down + +.PHONY: stop +stop: down ## Alias for 'down' + +.PHONY: restart +restart: ## Restart all services + @$(SAIL) restart + +.PHONY: build +build: ## Build the app image + @$(SAIL) build + +.PHONY: rebuild +rebuild: ## Build the app image from scratch (no cache) + @$(SAIL) build --no-cache + +.PHONY: pull +pull: ## Pull the latest versions of all base images + @$(DOCKER_COMPOSE) pull + +.PHONY: update +update: pull rebuild ## Pull latest images, rebuild, and restart + @$(SAIL) up -d + +.PHONY: fresh +fresh: ## Destroy ALL volumes, rebuild, and start clean (DATA LOSS!) + @echo "$(YELLOW)⚠ This will destroy all Docker volumes (database, redis, search index).$(RESET)" + @read -p "Are you sure? [y/N] " confirm && [ "$$confirm" = "y" ] || exit 1 + @$(SAIL) down -v + @$(SAIL) build --no-cache + @$(SAIL) up -d + @echo "$(GREEN)✔ Fresh environment is up. Run 'make artisan cmd=nntmux:install' to initialise.$(RESET)" + +# ── Shell Access ───────────────────────────────────────────── + +.PHONY: shell +shell: ## Open a bash shell in the app container + @$(SAIL) shell + +.PHONY: root-shell +root-shell: ## Open a root bash shell in the app container + @$(SAIL) root-shell + +.PHONY: tinker +tinker: ## Open a Laravel Tinker session + @$(SAIL) tinker + +# ── Artisan / PHP ──────────────────────────────────────────── + +.PHONY: artisan +artisan: ## Run an artisan command (usage: make artisan cmd="migrate") + @$(SAIL) artisan $(cmd) + +.PHONY: tmux-start +tmux-start: ## Start the NNTmux tmux processing engine + @$(SAIL) artisan tmux:start + +.PHONY: tmux-stop +tmux-stop: ## Stop the NNTmux tmux processing engine + @$(SAIL) artisan tmux:stop + +.PHONY: tmux-attach +tmux-attach: ## Attach to the running tmux session + @$(SAIL) artisan tmux:attach + +.PHONY: horizon +horizon: ## Show Horizon status + @$(SAIL) artisan horizon:status + +# ── Testing & Quality ──────────────────────────────────────── + +.PHONY: test +test: ## Run the PHPUnit test suite (usage: make test filter=TestName) + @$(SAIL) test $(if $(filter),--filter=$(filter),) + +.PHONY: pint +pint: ## Run Laravel Pint code formatter on dirty files + @$(SAIL) pint --dirty + +.PHONY: pint-all +pint-all: ## Run Laravel Pint on all files + @$(SAIL) pint + +# ── Frontend ───────────────────────────────────────────────── + +.PHONY: npm-build +npm-build: ## Run npm install and build inside the container + @$(SAIL) npm install + @$(SAIL) npm run build + +.PHONY: npm-dev +npm-dev: ## Start Vite dev server inside the container + @$(SAIL) npm run dev + +# ── Dependencies ───────────────────────────────────────────── + +.PHONY: composer-install +composer-install: ## Run composer install inside the container + @$(SAIL) composer install + +.PHONY: composer-update +composer-update: ## Run composer update inside the container + @$(SAIL) composer update + +# ── Database / Services ────────────────────────────────────── + +.PHONY: db +db: ## Open a MariaDB CLI session + @$(SAIL) mariadb + +.PHONY: redis-cli +redis-cli: ## Open a Redis CLI session + @$(SAIL) redis + +# ── Logs & Status ──────────────────────────────────────────── + +.PHONY: logs +logs: ## Tail logs from all containers + @$(DOCKER_COMPOSE) logs -f --tail=100 + +.PHONY: status +status: ## Show running containers and their status + @$(DOCKER_COMPOSE) ps + +# ── Cleanup ────────────────────────────────────────────────── + +.PHONY: clean +clean: ## Remove stopped containers and dangling images + @docker system prune -f + @echo "$(GREEN)✔ Cleaned up dangling resources.$(RESET)" + +.PHONY: nuke +nuke: ## Remove ALL project containers, images, and volumes (DATA LOSS!) + @echo "$(YELLOW)⚠ This will remove ALL project containers, images, and volumes.$(RESET)" + @read -p "Are you sure? [y/N] " confirm && [ "$$confirm" = "y" ] || exit 1 + @$(SAIL) down -v --rmi all + @echo "$(GREEN)✔ All project Docker resources removed.$(RESET)" + +# ── Help ───────────────────────────────────────────────────── + +.PHONY: help +help: ## Show this help message + @echo "" + @echo "$(CYAN)NNTmux Docker / Sail Commands$(RESET)" + @echo "$(CYAN)─────────────────────────────$(RESET)" + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \ + awk 'BEGIN {FS = ":.*?## "}; {printf " $(GREEN)%-20s$(RESET) %s\n", $$1, $$2}' + @echo "" + diff --git a/docker-compose.yml.dist b/docker-compose.yml.dist deleted file mode 100644 index 207f29792..000000000 --- a/docker-compose.yml.dist +++ /dev/null @@ -1,132 +0,0 @@ -services: - laravel.test: - build: - context: ./docker/8.3 - dockerfile: Dockerfile - args: - WWWGROUP: '${WWWGROUP}' - image: sail-8.3/app - extra_hosts: - - 'host.docker.internal:host-gateway' - ports: - - '${APP_PORT:-80}:80' - - '${VITE_PORT:-5173}:${VITE_PORT:-5173}' - environment: - TZ: ${APP_TIMEZONE} - COMPOSER_AUTH: ${COMPOSER_AUTH} - WWWUSER: '${WWWUSER}' - LARAVEL_SAIL: 1 - XDEBUG_MODE: '${SAIL_XDEBUG_MODE:-off}' - XDEBUG_CONFIG: '${SAIL_XDEBUG_CONFIG:-client_host=host.docker.internal}' - IGNITION_LOCAL_SITES_PATH: '${PWD}' - volumes: - - '.:/var/www/html' - - './docker/8.3/nginx.conf:/etc/nginx/sites-available/default' - networks: - - sail - depends_on: - - mariadb - - redis - - manticore - - mailpit - mariadb: - image: 'mariadb:11' - ports: - - '${FORWARD_DB_PORT:-3306}:3306' - environment: - TZ: ${APP_TIMEZONE} - MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}' - MYSQL_ROOT_HOST: '%' - MYSQL_DATABASE: '${DB_DATABASE}' - MYSQL_USER: '${DB_USERNAME}' - MYSQL_PASSWORD: '${DB_PASSWORD}' - MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' - command: - --max_allowed_packet=128M - --group_concat_max_len=16384 - --max_connections=200 - volumes: - - 'sail-mariadb:/var/lib/mysql' - - './vendor/laravel/sail/database/mysql/create-testing-database.sh:/docker-entrypoint-initdb.d/10-create-testing-database.sh' - networks: - - sail - healthcheck: - test: - - CMD - - mysqladmin - - ping - - '-p${DB_PASSWORD}' - retries: 3 - timeout: 5s - redis: - image: 'redis:alpine' - ports: - - '${FORWARD_REDIS_PORT:-6379}:6379' - environment: - TZ: ${APP_TIMEZONE} - volumes: - - 'sail-redis:/data' - networks: - - sail - healthcheck: - test: - - CMD - - redis-cli - - ping - retries: 3 - timeout: 5s - mailpit: - image: 'axllent/mailpit:latest' - ports: - - '${FORWARD_MAILPIT_PORT:-1025}:1025' - - '${FORWARD_MAILPIT_DASHBOARD_PORT:-8025}:8025' - networks: - - sail - manticore: - image: manticoresearch/manticore - environment: - TZ: ${APP_TIMEZONE} - EXTRA: 1 # Activates extra features - restart: always - ports: - - 9306:9306 - - 9308:9308 - ulimits: - nproc: 65535 - nofile: - soft: 65535 - hard: 65535 - memlock: - soft: -1 - hard: -1 - volumes: - - 'sail-manticore:/var/lib/manticore' - - ./config/manticore.conf:/etc/manticoresearch/manticore.conf - networks: - - sail - elasticsearch: - image: docker.elastic.co/elasticsearch/elasticsearch:8.6.2 - environment: - - TZ=${APP_TIMEZONE} - - discovery.type=single-node - - xpack.security.enabled=false - - "ES_JAVA_OPTS=-Xms512m -Xmx512m" - ports: - - 9200:9200 - - 9300:9300 - volumes: - - sail-elasticsearch:/usr/share/elasticsearch/data - networks: - - sail -networks: - sail: - driver: bridge -volumes: - sail-mariadb: - driver: local - sail-redis: - driver: local - sail-manticore: - driver: local - sail-elasticsearch: - driver: local diff --git a/docker-compose.yml.prod-dist b/docker-compose.yml.prod-dist index cd7467394..fb7d044ee 100644 --- a/docker-compose.yml.prod-dist +++ b/docker-compose.yml.prod-dist @@ -11,62 +11,61 @@ services: environment: TZ: ${APP_TIMEZONE} healthcheck: - test: [ "CMD", "curl", "-f", "http://localhost:${APP_PORT:-80}" ] - interval: 10s - timeout: 5s - retries: 5 + test: ["CMD", "curl", "-f", "http://localhost:${APP_PORT:-80}"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 30s env_file: - - .env + - .env volumes: - - 'install:/app/_install' - - 'storage:/app/storage' -# - 'resources:/var/www/html/resources' + - 'install:/app/_install' + - 'storage:/app/storage' networks: - nntmux depends_on: - - mariadb - - redis - - mailpit - - elasticsearch - - manticore + mariadb: + condition: service_healthy + redis: + condition: service_healthy worker: - command: > - sh -c "php artisan tmux-ui:start & php artisan horizon" - image: pyrowman/nntmux - extra_hosts: - - 'host.docker.internal:host-gateway' - tty: true - environment: - TZ: ${APP_TIMEZONE} - env_file: - - .env - volumes: - - 'install:/app/_install' - - 'storage:/app/storage' - networks: - - nntmux - depends_on: - webapp: - condition: service_healthy + command: > + sh -c "php artisan tmux-ui:start & php artisan horizon" + image: pyrowman/nntmux + extra_hosts: + - 'host.docker.internal:host-gateway' + tty: true + environment: + TZ: ${APP_TIMEZONE} + env_file: + - .env + volumes: + - 'install:/app/_install' + - 'storage:/app/storage' + networks: + - nntmux + depends_on: + webapp: + condition: service_healthy scheduler: - image: pyrowman/nntmux - extra_hosts: - - 'host.docker.internal:host-gateway' - tty: true - env_file: - - .env - environment: - TZ: ${APP_TIMEZONE} - volumes: - - 'install:/app/_install' - - 'storage:/app/storage' - networks: - - nntmux - depends_on: - webapp: - condition: service_healthy - command: > - sh -c "while [ true ]; do php artisan schedule:run; sleep 60;done" + image: pyrowman/nntmux + extra_hosts: + - 'host.docker.internal:host-gateway' + tty: true + env_file: + - .env + environment: + TZ: ${APP_TIMEZONE} + volumes: + - 'install:/app/_install' + - 'storage:/app/storage' + networks: + - nntmux + depends_on: + webapp: + condition: service_healthy + command: > + sh -c "while [ true ]; do php artisan schedule:run; sleep 60; done" mariadb: image: 'mariadb:11' ports: @@ -89,13 +88,11 @@ services: networks: - nntmux healthcheck: - test: - - CMD - - mysqladmin - - ping - - '-p${DB_PASSWORD}' + test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"] + interval: 10s retries: 3 timeout: 5s + start_period: 15s redis: image: 'redis:alpine' ports: @@ -108,33 +105,45 @@ services: - nntmux healthcheck: test: - - CMD - - redis-cli - - ping + - CMD + - redis-cli + - ping retries: 3 timeout: 5s manticore: - image: manticoresearch/manticore - environment: - TZ: ${APP_TIMEZONE} - EXTRA: 1 # Activates extra features - restart: always - ports: - - 9306:9306 - - 9308:9308 - ulimits: - nproc: 65535 - nofile: - soft: 65535 - hard: 65535 - memlock: - soft: -1 - hard: -1 - volumes: - - 'manticore:/var/lib/manticore' - - ./config/manticore.conf:/etc/manticoresearch/manticore.conf - networks: - - nntmux + image: manticoresearch/manticore:7.4.6 + profiles: + - manticore + environment: + TZ: ${APP_TIMEZONE} + EXTRA: 1 + restart: always + ports: + - 9306:9306 + - 9308:9308 + ulimits: + nproc: 65535 + nofile: + soft: 65535 + hard: 65535 + memlock: + soft: -1 + hard: -1 + volumes: + - 'manticore:/var/lib/manticore' + - ./config/manticore.conf:/etc/manticoresearch/manticore.conf + networks: + - nntmux + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-P", "9306"] + interval: 15s + timeout: 5s + retries: 3 + start_period: 15s + deploy: + resources: + limits: + memory: 1g mailpit: image: 'axllent/mailpit:latest' ports: @@ -144,6 +153,8 @@ services: - nntmux elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:8.17.0 + profiles: + - elasticsearch environment: - TZ=${APP_TIMEZONE} - discovery.type=single-node @@ -156,18 +167,24 @@ services: - elasticsearch:/usr/share/elasticsearch/data networks: - nntmux + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:9200/_cluster/health"] + interval: 15s + timeout: 5s + retries: 3 + start_period: 30s deploy: - resources: - limits: - memory: 1g + resources: + limits: + memory: 1g networks: nntmux: driver: bridge volumes: - mariadb: - redis: - elasticsearch: - manticore: - storage: - resources: - install: + mariadb: + redis: + elasticsearch: + manticore: + storage: + resources: + install: diff --git a/docker/8.4/Dockerfile b/docker/8.4/Dockerfile deleted file mode 100644 index 970680fbf..000000000 --- a/docker/8.4/Dockerfile +++ /dev/null @@ -1,66 +0,0 @@ -FROM ubuntu:24.04 - -LABEL maintainer="Fossil01" - -ARG WWWGROUP -ARG NODE_VERSION=22 -ARG POSTGRES_VERSION=17 -ARG MYSQL_CLIENT="mariadb-client" - -WORKDIR /var/www/html - -ENV DEBIAN_FRONTEND noninteractive - -RUN apt-get update \ - && apt-get install -y gnupg gosu curl ca-certificates zip unzip unrar lame git supervisor sqlite3 libcap2-bin libpng-dev python3 dnsutils \ - && curl -sS 'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x14aa40ec0831756756d7f66c4f4ea0aae5267a6c' | gpg --dearmor | tee /etc/apt/keyrings/ppa_ondrej_php.gpg > /dev/null \ - && echo "deb [signed-by=/etc/apt/keyrings/ppa_ondrej_php.gpg] https://ppa.launchpadcontent.net/ondrej/php/ubuntu noble main" > /etc/apt/sources.list.d/ppa_ondrej_php.list \ - && echo "deb [signed-by=/etc/apt/keyrings/ppa_ondrej_php.gpg] https://ppa.launchpadcontent.net/ondrej/nginx/ubuntu noble main" > /etc/apt/sources.list.d/ppa_ondrej_nginx.list \ - && curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor | tee /etc/apt/keyrings/yarn.gpg >/dev/null \ - && echo "deb [signed-by=/etc/apt/keyrings/yarn.gpg] https://dl.yarnpkg.com/debian/ stable main" > /etc/apt/sources.list.d/yarn.list \ - && curl -sS https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor | tee /etc/apt/keyrings/pgdg.gpg >/dev/null \ - && echo "deb [signed-by=/etc/apt/keyrings/pgdg.gpg] http://apt.postgresql.org/pub/repos/apt noble-pgdg main" > /etc/apt/sources.list.d/pgdg.list \ - && apt-get update \ - && apt-get install -y php8.4 php8.4-cli php8.4-common php8.4-mysql php8.4-xdebug php8.4-dev \ - php8.4-amqp php8.4-bcmath php8.4-bz2 php8.4-curl php8.4-gd php8.4-gmp php8.4-gnupg \ - php8.4-http php8.4-igbinary php8.4-imagick php8.4-intl php8.4-mbstring php8.4-msgpack \ - php8.4-oauth php8.4-opcache php8.4-raphf php8.4-readline php8.4-redis php8.4-soap php8.4-sqlite3 \ - php8.4-swoole php8.4-tidy php8.4-uploadprogress php8.4-uuid php8.4-xml php8.4-xmlrpc php8.4-xsl \ - php8.4-yaml php8.4-zip php8.4-zstd php8.4-pgsql php8.4-sockets php8.4-imap php8.4-ldap php8.4-memcached php8.4-pcov \ - tmux iputils-ping net-tools ffmpeg \ - sudo jq htop fonts-powerline nano bash-completion time wget cron \ - nginx php8.4-fpm \ - jpegoptim webp optipng pngquant libavif-bin \ - && wget https://mediaarea.net/repo/deb/repo-mediaarea_1.0-25_all.deb \ - && dpkg -i repo-mediaarea_1.0-25_all.deb \ - && apt-get update \ - && apt-get install -y libmediainfo0v5 mediainfo libzen0v5 \ - && curl -sLS https://getcomposer.org/installer | php -- --install-dir=/usr/bin/ --filename=composer \ - && curl -sLS https://deb.nodesource.com/setup_$NODE_VERSION.x | bash - \ - && apt-get install -y nodejs \ - && npm install -g npm bun pnpm \ - && apt-get install -y yarn $MYSQL_CLIENT postgresql-client-$POSTGRES_VERSION \ - && apt-get -y autoremove \ - && apt-get clean \ - && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* - - -RUN groupadd --force -g $WWWGROUP sail -RUN useradd -ms /bin/bash --no-user-group -g $WWWGROUP -u 1337 sail -RUN echo "alias artisan=\"php artisan\"" >> /home/sail/.bashrc - -COPY scheduler /etc/cron.d/scheduler -RUN chmod 0644 /etc/cron.d/scheduler \ - && crontab /etc/cron.d/scheduler - -COPY start-container /usr/local/bin/start-container -COPY nginx.conf /etc/nginx/sites-available/default -COPY supervisord.conf /etc/supervisor/supervisord.conf -COPY php.ini /etc/php/8.4/cli/conf.d/99-sail.ini - -RUN chmod +x /usr/local/bin/start-container - -EXPOSE 80 - -#ENTRYPOINT ["tail", "-f", "/dev/null"] # Use only for debugging -ENTRYPOINT ["start-container"] diff --git a/docker/8.4/README.md b/docker/8.4/README.md deleted file mode 100644 index 407d7b73b..000000000 --- a/docker/8.4/README.md +++ /dev/null @@ -1,91 +0,0 @@ -# NNTmux Docker Dev Environment - -**Author:** [Fossil01](https://github.com/Fossil01) - -### Caution: This setup is intended solely for development use. For production deployments, it is recommended to construct your own Docker containers. - -This development environment is composed of several key containers: App, MariaDB, Redis, Manticore, and Mailpit. The App container hosts nginx and PHP-FPM, and includes a bind mount that links to the root directory of this project. Supervisord is utilized to manage these services in the background. - -For search capabilities, Manticore is the default setup, but you can easily switch to Elasticsearch by modifying the corresponding lines in the docker-compose.yml file. Note that Elasticsearch is configured with security features disabled by default. - -This container also houses several tools to run the indexing backend: tmux, ffmpeg, mediainfo, unrar etc. It also has MariaDB & Postgres clients, NodeJS & Yarn. - -nginx runs on port 80 and is mapped to port 80 on the host machine too. If you're already using port 80 then change the `docker-compose.yml` file accordingly. - -Mailpit is used as a fake mailserver which catches all e-mails in one inbox. You can acess this via [this link](http://localhost:8025). Mailpit's SMTP server runs on port `1025`. - -> This project currently uses PHP 8.4 and MariaDB 11.x - -## Prerequisites - -- Docker & Docker Compose (Duh) -- Github (scopeless) Token -- [Laravel Sail](https://laravel.com/docs/10.x/sail) - -## Setup - -- Edit your projects `.env` file and add a `COMPOSER_AUTH` entry. - - Get a Github token: https://github.com/settings/tokens/new?scopes=&description=NNTMux+Docker and set the expiration to **No expiration** - - Example: `COMPOSER_AUTH='{"github-oauth": {"github.com": "ghp_xxxxxxxx"}}'` -- `sail build --no-cache` -- `sail up -d` - -### You might have to edit your Laravel `.env` file: - -``` -DB_HOST=mariadb - -MAIL_MAILER=smtp -MAIL_DRIVER=smtp -MAIL_HOST=mailpit -MAIL_PORT=1025 - -MANTICORESEARCH_HOST=manticore -ELASTICSEARCH_HOST=elasticsearch -``` - -## Database -On first run MariaDB will create a user and password based on your projects .env file: - -``` -DB_USERNAME= -DB_PASSWORD= -``` - -You will need to manually import a SQL dump or run `sail artisan nntmux:install` if this is a new installation. - -## Networking -Sail will create a Docker network called `sail` with these ports mapped to your host: -- HTTP: `80` -- Vite: `5173` -- Manticore: `9306`(SQL) & `9308`(HTTP) -- Mailpit: `1025`(SMTP) & `8025`(WebUI) - -## Backups - -Optionally you can add this config to `docker-compose.yml` to have automated MariaDB backups. Just replace `DATABASE_NAME` with your own NNTmux database name. - -```yaml - backup: - image: fradelg/mysql-cron-backup - depends_on: - - mariadb - restart: always - volumes: - - ./docker/mariadb/backups:/backup - environment: - - MYSQL_USER=${DB_USERNAME} - - MYSQL_PASS=${DB_PASSWORD} - - MYSQL_DB=${DB_DATABASE} - - MYSQLDUMP_OPTS=--ignore-table=DATABASE_NAME.telescope_entries --ignore-table=DATABASE_NAME.telescope_entries_tags - - CRON_TIME=0 0 31 2 * # (To never run with cron use Feb 31st: 0 0 31 2 *) - - MYSQL_HOST=mariadb - - MYSQL_PORT=3306 - - TIMEOUT=10s - - GZIP_LEVEL=9 - - MAX_BACKUPS=5 # The number of backups to keep. When reaching the limit, the old backup will be discarded. - - INIT_BACKUP=0 - - EXIT_BACKUP=1 # Make a backup whenever this container is gracefully stopped. - networks: - - sail -``` diff --git a/docker/8.4/nginx.conf b/docker/8.4/nginx.conf deleted file mode 100644 index 2ab7301ad..000000000 --- a/docker/8.4/nginx.conf +++ /dev/null @@ -1,50 +0,0 @@ -server { - listen 80; - root "/var/www/html/public"; - index index.html index.htm index.php; - charset utf-8; - - gzip on; - gzip_types text/plain text/xml text/css application/x-javascript text/javascript application/javascript application/xml application/xml+rss application/atom+xml image/x-icon font/opentype application/json; - gzip_min_length 256; - gzip_vary on; - gzip_disable "MSIE [1-6]\.(?!.*SV1)"; - gzip_proxied any; - gzip_comp_level 6; - - # Brotli compression (requires libnginx-mod-http-brotli-filter and libnginx-mod-http-brotli-static) - # Uncomment these lines after installing the brotli module - #brotli on; - #brotli_comp_level 6; - #brotli_static on; - #brotli_types application/atom+xml application/javascript application/json application/rss+xml - #application/vnd.ms-fontobject application/x-font-opentype application/x-font-truetype - #application/x-font-ttf application/x-javascript application/xhtml+xml application/xml - #font/eot font/opentype font/otf font/truetype image/svg+xml image/vnd.microsoft.icon - #image/x-icon image/x-win-bitmap text/css text/javascript text/plain text/xml text/html; - - location / { - try_files $uri $uri/ /index.php?$query_string; - } - location ^~ /covers/ { - root /var/www/html/storage; - } - - access_log /dev/stdout; - error_log stderr error; - - sendfile off; - - client_max_body_size 100m; - - location ~ \.php$ { - include /etc/nginx/fastcgi_params; - fastcgi_pass unix:/run/php/php8.4-fpm.sock; - fastcgi_index index.php; - fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; - } - - location ~ /\.ht { - deny all; - } -} diff --git a/docker/8.4/php.ini b/docker/8.4/php.ini deleted file mode 100644 index d0cd1cd72..000000000 --- a/docker/8.4/php.ini +++ /dev/null @@ -1,12 +0,0 @@ -[PHP] -post_max_size = 100M -upload_max_filesize = 100M -variables_order = EGPCS -max_execution_time = 300 -memory_limit = 2048M -error_reporting = E_ALL -log_errors = On -error_log = php-errors.log - -[Date] -date.timezone = Europe/Amsterdam diff --git a/docker/8.4/scheduler b/docker/8.4/scheduler deleted file mode 100644 index 69e95f100..000000000 --- a/docker/8.4/scheduler +++ /dev/null @@ -1 +0,0 @@ -* * * * * root cd /var/www/html && php artisan schedule:run >> /dev/null 2>&1 diff --git a/docker/8.4/start-container b/docker/8.4/start-container deleted file mode 100644 index ef73da83b..000000000 --- a/docker/8.4/start-container +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash - -if [ ! -z "$WWWUSER" ]; then - usermod -u $WWWUSER sail -fi - -if [ ! -d /.composer ]; then - mkdir /.composer -fi - -chmod -R ugo+rw /.composer -addgroup supervisor > /dev/null 2>&1 -usermod -a -G supervisor sail > /dev/null 2>&1 - -# Set timezone -ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone - -if [ $# -gt 0 ]; then - exec gosu $WWWUSER "$@" -else - exec /usr/bin/supervisord --nodaemon -c /etc/supervisor/supervisord.conf -fi diff --git a/docker/8.4/supervisord.conf b/docker/8.4/supervisord.conf deleted file mode 100644 index bee93d2c2..000000000 --- a/docker/8.4/supervisord.conf +++ /dev/null @@ -1,45 +0,0 @@ -[unix_http_server] -file=/opt/supervisor.sock ; the path to the socket file -chmod=0700 ; socket file mode (default 0700) -chown=root:supervisor ; socket file uid:gid owner - -[supervisord] -user=root -logfile=/var/log/supervisor/supervisord.log ; (main log file;default $CWD/supervisord.log) -pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid) -childlogdir=/var/log/supervisor ; ('AUTO' child log dir, default $TEMP) - -[supervisorctl] -serverurl=unix:////var/run/supervisor.sock - -[rpcinterface:supervisor] -supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface - -[program:php-fpm] -command=/usr/sbin/php-fpm8.4 --nodaemonize -c /etc/php/8.4/fpm/php-fpm.conf -autostart=true -autorestart=true -redirect_stderr=true - -[program:nginx] -command=/usr/sbin/nginx -g "daemon off;" -autostart=true -autorestart=true -startretries=5 -numprocs=1 -startsecs=0 -redirect_stderr=true - -[program:horizon] -process_name=%(program_name)s -command=php /var/www/html/artisan horizon -autostart=true -autorestart=true -redirect_stderr=true -stdout_logfile=/var/www/html/storage/logs/horizon.log - -[program:cron] -command=/usr/sbin/cron -f -l 8 -autostart=true -stdout_logfile=/var/log/cron.out.log -redirect_stderr=true diff --git a/docker/8.5/php.ini b/docker/8.5/php.ini index d0cd1cd72..4a6d30d97 100644 --- a/docker/8.5/php.ini +++ b/docker/8.5/php.ini @@ -8,5 +8,3 @@ error_reporting = E_ALL log_errors = On error_log = php-errors.log -[Date] -date.timezone = Europe/Amsterdam diff --git a/docker/8.5/supervisord.conf b/docker/8.5/supervisord.conf index a92b91dcc..709380eb6 100644 --- a/docker/8.5/supervisord.conf +++ b/docker/8.5/supervisord.conf @@ -1,5 +1,5 @@ [unix_http_server] -file=/opt/supervisor.sock ; the path to the socket file +file=/var/run/supervisor.sock ; the path to the socket file chmod=0700 ; socket file mode (default 0700) chown=root:supervisor ; socket file uid:gid owner @@ -10,7 +10,7 @@ pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid) childlogdir=/var/log/supervisor ; ('AUTO' child log dir, default $TEMP) [supervisorctl] -serverurl=unix:////var/run/supervisor.sock +serverurl=unix:///var/run/supervisor.sock [rpcinterface:supervisor] supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface