Update docker management

This commit is contained in:
DariusIII
2026-03-05 15:14:04 +01:00
parent 5707bdd015
commit 05f5f17b16
16 changed files with 527 additions and 519 deletions
+23 -5
View File
@@ -1,7 +1,25 @@
vendor/ vendor/
docker/mariadb-data node_modules/
docker/redis-data .git/
docker/manticore-data tests/
docker/
__pycache__/
.idea/
.vscode/
storage/logs/
storage/nzb/
storage/covers/
public/build/
.env .env
storage/nzb .env.*
storage/covers *.log
phpstan*
.phpunit*
AGENTS.md
CONTRIBUTING.md
DOCKER.md
CAPTCHA_CONFIGURATION.md
+39
View File
@@ -235,3 +235,42 @@ TMUX_USE_POWERLINE=true
TMUX_USE_NERD_FONTS=true TMUX_USE_NERD_FONTS=true
TMUX_TERMINAL=tmux-256color 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
+173
View File
@@ -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 |
+3 -3
View File
@@ -1,6 +1,6 @@
FROM composer:latest AS composer-base FROM composer:latest AS composer-base
FROM dunglas/frankenphp:1-php8.3 FROM dunglas/frankenphp:1-php8.4
LABEL maintainer="PyRowMan" LABEL maintainer="PyRowMan"
ENV SERVER_NAME=:${APP_PORT:-80} ENV SERVER_NAME=:${APP_PORT:-80}
ARG MYSQL_CLIENT="mariadb-client" ARG MYSQL_CLIENT="mariadb-client"
@@ -8,7 +8,7 @@ ARG MYSQL_CLIENT="mariadb-client"
WORKDIR /app 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 COPY --from=composer-base --link /usr/bin/composer /usr/bin/composer
RUN apt update \ RUN apt update \
@@ -37,7 +37,7 @@ RUN docker-php-ext-install \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" 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 COPY --chmod=755 ./docker-entrypoint.sh /usr/local/bin/docker-entrypoint
+182
View File
@@ -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 ""
-132
View File
@@ -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
+32 -15
View File
@@ -11,24 +11,23 @@ services:
environment: environment:
TZ: ${APP_TIMEZONE} TZ: ${APP_TIMEZONE}
healthcheck: healthcheck:
test: [ "CMD", "curl", "-f", "http://localhost:${APP_PORT:-80}" ] test: ["CMD", "curl", "-f", "http://localhost:${APP_PORT:-80}"]
interval: 10s interval: 10s
timeout: 5s timeout: 5s
retries: 5 retries: 5
start_period: 30s
env_file: env_file:
- .env - .env
volumes: volumes:
- 'install:/app/_install' - 'install:/app/_install'
- 'storage:/app/storage' - 'storage:/app/storage'
# - 'resources:/var/www/html/resources'
networks: networks:
- nntmux - nntmux
depends_on: depends_on:
- mariadb mariadb:
- redis condition: service_healthy
- mailpit redis:
- elasticsearch condition: service_healthy
- manticore
worker: worker:
command: > command: >
sh -c "php artisan tmux-ui:start & php artisan horizon" sh -c "php artisan tmux-ui:start & php artisan horizon"
@@ -66,7 +65,7 @@ services:
webapp: webapp:
condition: service_healthy condition: service_healthy
command: > command: >
sh -c "while [ true ]; do php artisan schedule:run; sleep 60;done" sh -c "while [ true ]; do php artisan schedule:run; sleep 60; done"
mariadb: mariadb:
image: 'mariadb:11' image: 'mariadb:11'
ports: ports:
@@ -89,13 +88,11 @@ services:
networks: networks:
- nntmux - nntmux
healthcheck: healthcheck:
test: test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
- CMD interval: 10s
- mysqladmin
- ping
- '-p${DB_PASSWORD}'
retries: 3 retries: 3
timeout: 5s timeout: 5s
start_period: 15s
redis: redis:
image: 'redis:alpine' image: 'redis:alpine'
ports: ports:
@@ -114,10 +111,12 @@ services:
retries: 3 retries: 3
timeout: 5s timeout: 5s
manticore: manticore:
image: manticoresearch/manticore image: manticoresearch/manticore:7.4.6
profiles:
- manticore
environment: environment:
TZ: ${APP_TIMEZONE} TZ: ${APP_TIMEZONE}
EXTRA: 1 # Activates extra features EXTRA: 1
restart: always restart: always
ports: ports:
- 9306:9306 - 9306:9306
@@ -135,6 +134,16 @@ services:
- ./config/manticore.conf:/etc/manticoresearch/manticore.conf - ./config/manticore.conf:/etc/manticoresearch/manticore.conf
networks: networks:
- nntmux - 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: mailpit:
image: 'axllent/mailpit:latest' image: 'axllent/mailpit:latest'
ports: ports:
@@ -144,6 +153,8 @@ services:
- nntmux - nntmux
elasticsearch: elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.17.0 image: docker.elastic.co/elasticsearch/elasticsearch:8.17.0
profiles:
- elasticsearch
environment: environment:
- TZ=${APP_TIMEZONE} - TZ=${APP_TIMEZONE}
- discovery.type=single-node - discovery.type=single-node
@@ -156,6 +167,12 @@ services:
- elasticsearch:/usr/share/elasticsearch/data - elasticsearch:/usr/share/elasticsearch/data
networks: networks:
- nntmux - nntmux
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9200/_cluster/health"]
interval: 15s
timeout: 5s
retries: 3
start_period: 30s
deploy: deploy:
resources: resources:
limits: limits:
-66
View File
@@ -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"]
-91
View File
@@ -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
```
-50
View File
@@ -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;
}
}
-12
View File
@@ -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
-1
View File
@@ -1 +0,0 @@
* * * * * root cd /var/www/html && php artisan schedule:run >> /dev/null 2>&1
-22
View File
@@ -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
-45
View File
@@ -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
-2
View File
@@ -8,5 +8,3 @@ error_reporting = E_ALL
log_errors = On log_errors = On
error_log = php-errors.log error_log = php-errors.log
[Date]
date.timezone = Europe/Amsterdam
+2 -2
View File
@@ -1,5 +1,5 @@
[unix_http_server] [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) chmod=0700 ; socket file mode (default 0700)
chown=root:supervisor ; socket file uid:gid owner 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) childlogdir=/var/log/supervisor ; ('AUTO' child log dir, default $TEMP)
[supervisorctl] [supervisorctl]
serverurl=unix:////var/run/supervisor.sock serverurl=unix:///var/run/supervisor.sock
[rpcinterface:supervisor] [rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface