Files
2026-09-29 22:08:18 +07:00

317 lines
6.5 KiB
Markdown

# Egeya 11.5 v4199 in Docker
Stack:
- nginx
- PHP-FPM 8.2
- MariaDB 10.11
- Egeya v4199
The layout intentionally follows a tested nginx + PHP-FPM deployment rather than the older Apache-based Docker example.
## Why nginx + PHP-FPM
Egeya 11 supports PHP up to 8.2. The nginx configuration uses synthetic URLs through:
```nginx
location / {
log_not_found off;
rewrite ^(.*)$ /index.php?go=$1 last;
}
```
Do not replace this with:
```nginx
try_files $uri $uri/ /index.php?go=$uri;
```
The rewrite form preserves the original query string used by Egeya upload requests, including fields such as `entity` and `entity-id`.
The PHP location also passes:
```nginx
fastcgi_param E2_SYNTH_URLS true;
```
Direct access to PHP files under `/system` and `/user`, `user/settings.json`, `*.psa`, and `.ht*` is blocked.
## Upload temporary directory
The `data` directory is mounted once at `/var/www/egeya-data`.
Persistent paths are:
```text
/var/www/egeya-data/user
/var/www/egeya-data/pictures
/var/www/egeya-data/tmp
```
Inside both application images, `/var/www/html/user` and `/var/www/html/pictures` are symbolic links into this single mount.
PHP is configured with:
```ini
upload_tmp_dir = /var/www/egeya-data/tmp
sys_temp_dir = /var/www/egeya-data/tmp
```
This is deliberate. A standard container `/tmp` is on the container filesystem, while `pictures` is on a bind mount. Moving an uploaded file between them may cross mount boundaries and fail with `EXDEV`. Keeping the upload temporary directory and `pictures` under the same mount avoids that class of failure.
## Project structure
```text
Dockerfile
compose.yaml
.env.example
.dockerignore
.gitignore
docker/nginx/egeya.conf.template
docker/php/egeya-entrypoint.sh
docker/php/www-egeya.conf
scripts/prepare.sh
scripts/migrate-files.sh
scripts/import-db.sh
data/user
data/pictures
data/tmp
backup
secrets
```
Create the structure manually if required:
```bash
mkdir -p docker/nginx docker/php scripts data/user data/pictures data/tmp backup secrets
touch Dockerfile compose.yaml .env.example .dockerignore .gitignore \
docker/nginx/egeya.conf.template \
docker/php/egeya-entrypoint.sh docker/php/www-egeya.conf \
scripts/prepare.sh scripts/migrate-files.sh scripts/import-db.sh \
data/user/.gitkeep data/pictures/.gitkeep data/tmp/.gitkeep \
backup/.gitkeep secrets/.gitkeep
```
## Prepare
```bash
chmod +x scripts/*.sh
./scripts/prepare.sh
```
Review `.env` before starting.
## Build
```bash
docker compose build --pull
```
Both `nginx` and `php` targets are built from the same Egeya source stage, so the static files seen by nginx and the PHP code executed by PHP-FPM are from the same Egeya release.
Optional source integrity check:
```text
EGEYA_SHA256=<sha256 of e2_distr_v4199.zip>
```
## Start
```bash
docker compose up -d
docker compose ps
docker compose logs --tail=100 nginx php db
```
By default nginx listens only on:
```text
127.0.0.1:8080
```
This is suitable when another reverse proxy terminates HTTPS on the Docker host.
## Data model
The application code is immutable and comes from the Docker images.
Persistent data is limited to:
- `data/user`
- `data/pictures`
- `data/tmp`
- MariaDB named volume `db_data`
Do not copy an old `/system` directory into the container. Updating the image updates `/system` and the bundled application files.
Custom additions stored below `user`, including `user/extras`, migrate together with the user data.
## Migration from a bare-metal installation
Assume the current installation is:
```text
/var/www/blog
```
### 1. Stop writes on the old installation
Stop the web application or otherwise prevent writes for the final synchronization.
### 2. Create a database dump
Example:
```bash
mysqldump \
--single-transaction \
--quick \
--triggers \
--default-character-set=utf8mb4 \
egeya > egeya.sql
```
Copy the dump to:
```text
backup/egeya.sql
```
### 3. Copy file data
If the old blog tree is locally available:
```bash
./scripts/migrate-files.sh /var/www/blog ./data
```
For a remote source, an equivalent rsync is:
```bash
rsync -aHAX old-host:/var/www/blog/user/ ./data/user/
rsync -aHAX old-host:/var/www/blog/pictures/ ./data/pictures/
```
Do not copy `/system`.
Do not copy the old nginx configuration into the application image. Use `docker/nginx/egeya.conf.template`.
### 4. Prepare secrets and configuration
```bash
./scripts/prepare.sh
```
Set the target database name and user in `.env` before initializing MariaDB.
### 5. Start MariaDB and import the dump
```bash
./scripts/import-db.sh backup/egeya.sql
```
### 6. Start PHP and nginx
```bash
docker compose up -d php nginx
```
### 7. Validate
```bash
docker compose ps
docker compose logs --tail=200 php nginx
```
Check at least:
- public pages
- author login
- note editor
- image upload
- audio/video upload if used
- editing an existing note
- built-in security check
- access to `/system/core.php` returns 403
- access to `/user/settings.json` returns 403
For upload diagnostics, the application log is available at:
```text
data/user/logs/main.log
```
It is created by the PHP container entrypoint if absent.
## Database credentials
Egeya receives database settings through its supported environment variables:
```text
E2_DB_SERVER
E2_DB_USER_NAME
E2_DB_PASSW
E2_DB_NAME
```
The Compose file does not place the password directly in its environment section. It mounts a Docker secret and the PHP entrypoint exports its contents as `E2_DB_PASSW` immediately before starting PHP-FPM.
PHP-FPM is explicitly configured with `clear_env = no` so the Egeya process can see these variables.
## Updating Egeya
Change:
```text
EGEYA_VERSION=<new build number>
```
If necessary also set `EGEYA_URL` and `EGEYA_SHA256`.
Then rebuild and recreate the application containers:
```bash
docker compose build --pull php nginx
docker compose up -d --no-deps --force-recreate php nginx
```
The persistent `user`, `pictures`, and database data are not replaced.
Before an update, make a database dump and a copy of `data`.
## Useful commands
Validate Compose rendering:
```bash
docker compose config
```
PHP configuration:
```bash
docker compose exec php php -i | grep -E 'upload_tmp_dir|sys_temp_dir|upload_max_filesize|post_max_size'
```
Verify that temp and pictures resolve to the same mounted filesystem:
```bash
docker compose exec php sh -c 'df -T /var/www/egeya-data/tmp /var/www/egeya-data/pictures'
```
Check the nginx configuration:
```bash
docker compose exec nginx nginx -T
```
Check protected paths:
```bash
curl -i http://127.0.0.1:8080/system/core.php
curl -i http://127.0.0.1:8080/user/settings.json
```