nginx слушает 80 внутри контейнера, снаружи публикуется HTTP_PORT. Эгея с E2_SYNTH_URLS собирает абсолютные URL из FastCGI-параметров, поэтому HTTP_HOST и SERVER_PORT берутся из NGINX_EXTERNAL_PORT (тот же HTTP_PORT). Редиректы nginx делаются относительными. Шаблон монтируется из docker/nginx/, а не из несуществующего ./nginx/. Каталог data монтируется в nginx только для чтения, чтобы location статики отдавал pictures и файлы из user. Сервис nginx собирается из того же Dockerfile (target nginx) и ждёт здоровый php-fpm.
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:
location / {
log_not_found off;
rewrite ^(.*)$ /index.php?go=$1 last;
}
Do not replace this with:
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:
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:
/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:
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
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:
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
chmod +x scripts/*.sh
./scripts/prepare.sh
Review .env before starting.
Build
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:
EGEYA_SHA256=<sha256 of e2_distr_v4199.zip>
Start
docker compose up -d
docker compose ps
docker compose logs --tail=100 nginx php db
By default nginx listens only on:
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/userdata/picturesdata/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:
/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:
mysqldump \
--single-transaction \
--quick \
--triggers \
--default-character-set=utf8mb4 \
egeya > egeya.sql
Copy the dump to:
backup/egeya.sql
3. Copy file data
If the old blog tree is locally available:
./scripts/migrate-files.sh /var/www/blog ./data
For a remote source, an equivalent rsync is:
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
./scripts/prepare.sh
Set the target database name and user in .env before initializing MariaDB.
5. Start MariaDB and import the dump
./scripts/import-db.sh backup/egeya.sql
6. Start PHP and nginx
docker compose up -d php nginx
7. Validate
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.phpreturns 403 - access to
/user/settings.jsonreturns 403
For upload diagnostics, the application log is available at:
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:
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:
EGEYA_VERSION=<new build number>
If necessary also set EGEYA_URL and EGEYA_SHA256.
Then rebuild and recreate the application containers:
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:
docker compose config
PHP configuration:
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:
docker compose exec php sh -c 'df -T /var/www/egeya-data/tmp /var/www/egeya-data/pictures'
Check the nginx configuration:
docker compose exec nginx nginx -T
Check protected paths:
curl -i http://127.0.0.1:8080/system/core.php
curl -i http://127.0.0.1:8080/user/settings.json