2026-09-29 15:38:04 +00:00
2026-09-29 22:08:18 +07:00
2026-09-29 22:08:18 +07:00
2026-09-29 22:08:18 +07:00
2026-09-29 22:08:18 +07:00
2026-09-29 22:08:18 +07:00
2026-09-29 22:08:18 +07:00
2026-09-29 22:08:18 +07:00
2026-09-29 22:08:18 +07:00
2026-09-29 22:08:18 +07:00
2026-09-29 15:38:04 +00:00
2026-09-29 22:08:18 +07:00

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/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:

/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.php returns 403
  • access to /user/settings.json returns 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
S
Description
No description provided
Readme
50 KiB
0 Stars 1 Watchers 0 Forks
Languages
Dockerfile 50.1%
Shell 49.9%