Docker Implementation

This commit is contained in:
Hosteroid
2025-10-23 00:56:29 +03:00
parent fa0167bf71
commit 75f0ae35fb
7 changed files with 444 additions and 0 deletions

View File

@@ -0,0 +1,24 @@
# Latest stable PHP + Apache
FROM php:apache
# Build deps for requested PHP extensions
RUN apt-get update && apt-get install -y --no-install-recommends \
libicu-dev libzip-dev libpng-dev libjpeg62-turbo-dev libfreetype6-dev \
libxml2-dev libcurl4-openssl-dev libonig-dev pkg-config unzip git tzdata \
&& docker-php-ext-configure gd --with-jpeg --with-freetype \
&& docker-php-ext-install -j"$(nproc)" \
pdo pdo_mysql mysqli intl zip gd bcmath mbstring curl xml \
&& a2enmod rewrite headers \
&& rm -rf /var/lib/apt/lists/*
# Set Apache DocumentRoot to /var/www/html/public
ARG APACHE_DOCUMENT_ROOT=/var/www/html/public
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/000-default.conf
# Apache timeout only (no proxy needed)
RUN set -eux; \
echo "Timeout 300" > /etc/apache2/conf-available/timeouts.conf; \
a2enconf timeouts
WORKDIR /var/www/html

View File

@@ -0,0 +1,20 @@
; ---- PHP limits (as requested) ----
max_execution_time = 0
max_input_time = -1
max_input_vars = 3000
memory_limit = 512M
post_max_size = 32M
upload_max_filesize = 16M
default_socket_timeout = 120
; Recommended defaults
date.timezone = UTC
display_errors = On
error_reporting = E_ALL
; Opcache (safe defaults)
opcache.enable=1
opcache.enable_cli=1
opcache.validate_timestamps=1
opcache.revalidate_freq=2

50
domain-monitor-docker/.gitignore vendored Normal file
View File

@@ -0,0 +1,50 @@
===
.env
.env.docker
*.env.bak*
*.env.backup*
app/.env
# === LOGS ===
app/logs/
*.log
# === COMPOSER ===
app/vendor/
app/composer.lock
# === DOCKER / BUILD ARTIFACTS ===
dbdata/
.docker/*.pid
.docker/*.sock
.docker/.cache/
*.pid
*.sock
# === TEMPORARY FILES ===
*.tmp
*.swp
*.bak
*.orig
# === OS / EDITOR ===
.DS_Store
Thumbs.db
.idea/
.vscode/
*.code-workspace
# === BACKUPS ===
*.bak.*
*.tar
*.zip
# === GIT IGNORES REPO CLONED APP (OPTIONAL) ===
# If you keep domain-monitor-docker in its own Git repo and want to ignore app/
# uncomment this line:
# app/
# === SYSTEM / MISC ===
node_modules/
coverage/

View File

@@ -0,0 +1,157 @@
# Domain Monitor Docker Setup
This directory contains Docker configuration for running Domain Monitor in a containerized environment.
## Quick Start
1. **Configure your environment:**
- Copy `env.docker.example` to `.env.docker`
- Edit `.env.docker` and change the default passwords:
```bash
cp env.docker.example .env.docker
# Edit .env.docker with your real passwords
```
2. **Run the bootstrap script:**
```bash
chmod +x bootstrap.sh
./bootstrap.sh
```
## What the bootstrap script does
The `bootstrap.sh` script will:
- **Clone the Domain Monitor repository** from GitHub into the `app/` folder (only if `app/` doesn't exist or is empty)
- **Set up the application environment** by creating `.env` file with database configuration
- **Install PHP dependencies** using Composer
- **Configure proper file permissions** for the web server
- **Load environment variables** from `.env.docker` into the shell
- **Start the Docker stack** (web server, database, and phpMyAdmin)
### Running bootstrap multiple times
The bootstrap script is **safe to run multiple times**:
- If `app/` folder exists and has content, it skips the git clone
- It will reinstall Composer dependencies (ensures they're up to date)
- It will restart the Docker containers with `--build` flag
- Your database data is preserved (stored in Docker volumes)
## Environment Configuration
The bootstrap script loads environment variables from `.env.docker` into the shell environment, which Docker Compose then uses for variable substitution. This approach ensures that all services get the correct database credentials.
## Services
After running the bootstrap script, you'll have:
- **Domain Monitor App**: http://localhost:8080
- **phpMyAdmin**: http://localhost:8081 (Server: `domain-monitor-mariadb`)
## Managing the Docker Stack
### Starting the stack
```bash
# First time setup (clones repo, installs dependencies, starts containers)
./bootstrap.sh
# Or if you just want to start existing containers
docker compose up -d
```
### Stopping the stack
```bash
# Stop all containers
docker compose down
# Stop and remove volumes (WARNING: This will delete your database data!)
docker compose down -v
```
### Restarting the stack
```bash
# Restart containers (keeps data)
docker compose restart
# Rebuild and restart (if you made changes to Docker config)
docker compose up -d --build
# Full restart (stops, rebuilds, starts)
docker compose down && docker compose up -d --build
```
### Viewing logs
```bash
# View logs for all services
docker compose logs
# View logs for specific service
docker compose logs web
docker compose logs db
docker compose logs pma
# Follow logs in real-time
docker compose logs -f
```
## Environment Configuration
You need to create a `.env.docker` file with your database credentials. The script will copy `env.docker.example` to `.env.docker` if it doesn't exist, but you **must edit it** with real passwords before the script will work.
Required variables in `.env.docker`:
- `DB_DATABASE` - Database name
- `DB_USERNAME` - Database user
- `DB_PASSWORD` - Database password
- `DB_ROOT_PASSWORD` - Database root password
- `TZ` - Timezone (optional, defaults to UTC)
## Requirements
- Docker and Docker Compose
- Git
- Internet connection (to clone the repository)
## Troubleshooting
- Make sure you're running the script from the `domain-monitor-docker` directory
- Ensure Docker is running and you have permission to use it
- Check that you've edited `.env.docker` with real passwords (not the example values)
## Quick Reference
### Common scenarios
**First time setup:**
```bash
cp env.docker.example .env.docker
# Edit .env.docker with real passwords
./bootstrap.sh
```
**Daily usage:**
```bash
# Start (if stopped)
docker compose up -d
# Stop
docker compose down
```
**After making changes to the app:**
```bash
# Restart to pick up changes
docker compose restart web
```
**After making changes to Docker config:**
```bash
# Rebuild containers
docker compose up -d --build
```
**Complete reset (WARNING: deletes all data):**
```bash
docker compose down -v
rm -rf app/
./bootstrap.sh
```

View File

@@ -0,0 +1,131 @@
#!/usr/bin/env bash
set -euo pipefail
### --- CONFIG ---
GIT_URL="${GIT_URL:-https://github.com/Hosteroid/domain-monitor.git}"
APP_ENV_DEFAULT="${APP_ENV:-production}"
# Always treat the CURRENT directory as project root
PROJECT_ROOT="$(pwd)"
APP_DIR="$PROJECT_ROOT/app"
DOCKER_ENV_FILE="$PROJECT_ROOT/.env.docker"
ENV_TMPL="$APP_DIR/env.example.txt"
ENV_FILE="$APP_DIR/.env"
# Numeric IDs for php:apache (Debian) www-data
WWW_UID=33
WWW_GID=33
ROOT_UID=0
dc() {
if command -v docker &>/dev/null && docker compose version &>/dev/null; then
docker compose "$@"
elif command -v docker-compose &>/dev/null; then
docker-compose "$@"
else
echo "Error: docker compose not found." >&2
exit 1
fi
}
fail() { echo "Error: $*" >&2; exit 1; }
upsert_kv() {
local file="$1" key="$2" val="$3"
if grep -qE "^${key}=" "$file" 2>/dev/null; then
sed -i "s#^${key}=.*#${key}=${val}#g" "$file"
else
printf "%s=%s\n" "$key" "$val" >> "$file"
fi
}
echo "==> Domain Monitor bootstrap"
[[ -f "$PROJECT_ROOT/docker-compose.yml" ]] || fail "Run this from the domain-monitor-docker folder."
# Ensure .env.docker exists (or copy example then exit)
if [[ ! -f "$DOCKER_ENV_FILE" ]]; then
if [[ -f "$PROJECT_ROOT/env.docker.example" ]]; then
echo "==> .env.docker not found. Creating from example..."
cp "$PROJECT_ROOT/env.docker.example" "$DOCKER_ENV_FILE"
echo " Edit $DOCKER_ENV_FILE with real passwords, then re-run."
exit 1
else
fail ".env.docker not found (and no example to copy)."
fi
fi
# Load Docker env
set -a
# shellcheck disable=SC1090
. "$DOCKER_ENV_FILE"
set +a
: "${DB_DATABASE:?Missing DB_DATABASE in .env.docker}"
: "${DB_USERNAME:?Missing DB_USERNAME in .env.docker}"
: "${DB_PASSWORD:?Missing DB_PASSWORD in .env.docker}"
: "${DB_ROOT_PASSWORD:?Missing DB_ROOT_PASSWORD in .env.docker}"
TZ="${TZ:-UTC}"
# Clone repo if needed
if [[ ! -d "$APP_DIR" || -z "$(ls -A "$APP_DIR" 2>/dev/null || true)" ]]; then
echo "==> Cloning $GIT_URL into app/"
git clone "$GIT_URL" "$APP_DIR"
else
echo "==> app/ exists; skipping clone"
fi
# Create/merge app .env
if [[ -f "$ENV_FILE" ]]; then
cp -a "$ENV_FILE" "$ENV_FILE.bak.$(date +%s)"
echo " - Existing .env backed up."
elif [[ -f "$ENV_TMPL" ]]; then
cp "$ENV_TMPL" "$ENV_FILE"
echo " - Created .env from env.example.txt"
else
touch "$ENV_FILE"
echo " - Created empty .env (env.example.txt not found)"
fi
# Write DB + env for container network
upsert_kv "$ENV_FILE" "DB_HOST" "db"
upsert_kv "$ENV_FILE" "DB_PORT" "3306"
upsert_kv "$ENV_FILE" "DB_DATABASE" "$DB_DATABASE"
upsert_kv "$ENV_FILE" "DB_USERNAME" "$DB_USERNAME"
upsert_kv "$ENV_FILE" "DB_PASSWORD" "$DB_PASSWORD"
upsert_kv "$ENV_FILE" "APP_ENV" "${APP_ENV_DEFAULT}"
# --- PERMISSIONS using numeric IDs (works across host/container) ---
echo "==> Applying permissions with numeric IDs (root:${WWW_GID} for code; ${WWW_UID}:${WWW_GID} for writable dirs)"
mkdir -p "$APP_DIR/logs"
# Code owned by root, group = www-data (33)
chown -R ${ROOT_UID}:${WWW_GID} "$APP_DIR" || true
# Dirs 755, files 644
find "$APP_DIR" -type d -print0 | xargs -0 chmod 755
find "$APP_DIR" -type f -print0 | xargs -0 chmod 644
# Writable dirs for the app at runtime
for d in logs storage cache tmp runtime; do
if [ -d "$APP_DIR/$d" ]; then
echo " - Making $d writable by ${WWW_UID}:${WWW_GID}"
chown -R ${WWW_UID}:${WWW_GID} "$APP_DIR/$d"
chmod -R 775 "$APP_DIR/$d"
fi
done
# .env readable by root & group only
chmod 640 "$APP_DIR/.env" || true
# Install vendors via Composer container
echo "==> Installing Composer vendors (composer:2) ..."
docker run --rm -v "$APP_DIR":/app -w /app composer:2 install --no-interaction --prefer-dist
# Bring stack up (build/rebuild)
echo "==> Starting stack ..."
dc up -d --build
echo "==> Done."
echo " App URL: http://<SERVER_IP>:8080"
echo " phpMyAdmin: http://<SERVER_IP>:8081 (Server: domain-monitor-mariadb)"
echo " Note: On the host, UID 33 may display as 'tape'; inside the container it's www-data. This is normal."

View File

@@ -0,0 +1,50 @@
services:
web:
build:
context: .
dockerfile: .docker/Dockerfile
container_name: domain-monitor-web
ports:
- "8080:80"
volumes:
- ./app:/var/www/html:Z
- ./.docker/php.ini:/usr/local/etc/php/conf.d/custom.ini:ro,Z
environment:
APACHE_DOCUMENT_ROOT: /var/www/html/public
TZ: ${TZ:-UTC}
depends_on:
- db
db:
image: mariadb:latest
container_name: domain-monitor-mariadb
restart: unless-stopped
environment:
MARIADB_DATABASE: ${DB_DATABASE}
MARIADB_USER: ${DB_USERNAME}
MARIADB_PASSWORD: ${DB_PASSWORD}
MARIADB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
TZ: ${TZ:-UTC}
command: [
"--character-set-server=utf8mb4",
"--collation-server=utf8mb4_unicode_ci"
]
volumes:
- dbdata:/var/lib/mysql
pma:
image: phpmyadmin:latest
container_name: domain-monitor-pma
restart: unless-stopped
environment:
PMA_HOST: domain-monitor-mariadb
UPLOAD_LIMIT: 256M
TZ: ${TZ:-UTC}
ports:
- "8081:80"
depends_on:
- db
volumes:
dbdata:

View File

@@ -0,0 +1,12 @@
# Example Docker environment file
# Copy this file to .env.docker and update your credentials
# === Database Configuration ===
DB_DATABASE=domain_monitor
DB_USERNAME=user_example
DB_PASSWORD=example_password
DB_ROOT_PASSWORD=example_root_password
# === Timezone (for PHP, MariaDB, phpMyAdmin) ===
TZ=UTC