This repository contains the Docker configuration for running Pinakes, a web-based library management system. It provides a simple, multi-container environment using Docker Compose to run the application, a web server, and a database.
The setup consists of three main services orchestrated by docker-compose.yml:
pinakes: The PHP application itself, running on PHP 8.2-FPM. A pre-built image is published to the GitHub Container Registry (ghcr.io/jbenamy/pinakes-docker) on every push tomainand on tagged releases. You can also build the image locally from the includedDockerfile.nginx: A lightweight Nginx web server built fromDockerfile.nginx, which bakesnginx.confdirectly into the image (ghcr.io/jbenamy/pinakes-docker-nginx). This makesdocker-compose.ymlfully self-contained with no host file dependencies.mariadb: A MariaDB 11 database server for storing the application's data.
- Dockerized Environment: Run Pinakes without installing PHP, Nginx, or MariaDB on your local machine.
- Simple Setup: Get started with a single
docker-composecommand. - Automated Installation: The entrypoint script detects if the database is empty and guides you to the web installer.
- Production-Ready: The configuration is based on production best practices, including a production
php.iniand security headers in Nginx. - Customizable: Easily change the application version, database credentials, and other settings through environment variables.
- Backend: PHP 8.2
- Web Server: Nginx
- Database: MariaDB 11
- Containerization: Docker, Docker Compose
These instructions will get you a copy of the project up and running on your local machine for development and testing purposes.
- Docker
- Docker Compose (usually included with Docker Desktop)
-
Clone this repository:
git clone https://github.com/jbenamy/pinakes-docker.git cd pinakes-docker -
Start the services:
docker-compose up -d
This pulls the pre-built
pinakesimage fromghcr.io, downloads the other required images, and starts all containers in the background.To build the image locally instead (e.g. to test local changes), replace
image:withbuild: .in thepinakesservice and run:docker-compose up -d --build
-
Complete the web installation: Open your web browser and navigate to
http://localhost:8080/installer/. You will be guided through the final setup steps by the Pinakes web installer.The entrypoint script automatically checks if the database is empty. If it is, the installer is available. Once installation is complete, Pinakes creates a
.installedlock file that causes the installer to block re-execution on subsequent visits. (Note: the upstream.htaccess-based redirect is Apache-only and has no effect on Nginx; protection here relies on the PHP-level gate ininstaller/index.php.) -
Access the application: Once the installation is complete, you can access Pinakes at
http://localhost:8080.
The application is configured using environment variables set in the docker-compose.yml file. These variables are used by docker-entrypoint.sh to generate a .env file inside the pinakes container at startup if one does not already exist.
The following variables can be set in the environment section of the pinakes service in docker-compose.yml:
| Variable | Description | Default |
|---|---|---|
DB_HOST |
The hostname of the database server. | mariadb |
DB_USER |
The username for the database connection. | pinakes |
DB_PASS |
The password for the database connection. | pinakes |
DB_NAME |
The name of the database. | pinakes |
DB_PORT |
The port of the database server. | 3306 |
APP_ENV |
Application environment (production, development). |
production |
APP_DEBUG |
Enable debug mode. | false |
APP_LOCALE |
Application locale. | en_US |
APP_CANONICAL_URL |
The canonical URL of the application. | (empty) |
SESSION_LIFETIME |
Session lifetime in seconds. | 3600 |
PLUGIN_ENCRYPTION_KEY |
Encryption key for plugins. Auto-generated if not set. | (random) |
The mariadb service uses MARIADB_ROOT_PASSWORD (default: pinakes-root) along with MARIADB_DATABASE, MARIADB_USER, and MARIADB_PASSWORD to initialize the database. These should be changed for any non-local deployment.
The pinakes image accepts one build argument, passed with --build-arg:
| Argument | Description | Default |
|---|---|---|
PINAKES_REF |
The branch or tag of the Pinakes repository to build. | main |
Example: docker-compose build --build-arg PINAKES_REF=v1.2.3
The nginx image automatically forwards X-Forwarded-Proto, X-Forwarded-For, and X-Real-IP headers to PHP-FPM, so PHP correctly detects HTTPS when SSL is terminated upstream. You must also set APP_CANONICAL_URL to your public URL in docker-compose.yml:
APP_CANONICAL_URL: https://library.example.comIf using Nginx Proxy Manager, disable Block Common Exploits on the proxy host. NPM sets the same security headers (X-Frame-Options, X-Content-Type-Options, etc.) that the nginx image already sets, and duplicate headers can cause browser errors.
All persistent data is stored in a ./data/ directory next to docker-compose.yml on the host:
| Host path | Container path | Contents |
|---|---|---|
./data/db/ |
/var/lib/mysql |
MariaDB data files |
./data/uploads/ |
/var/www/pinakes/public/uploads |
Book cover images |
./data/backups/ |
/var/www/pinakes/storage/backups |
Database backups |
./data/logs/ |
/var/www/pinakes/storage/logs |
Application logs |
./data/plugins/ |
/var/www/pinakes/storage/plugins |
Plugins (bundled + user-installed) |
On first run, if ./data/plugins/ is empty the entrypoint automatically seeds it with the bundled plugins from the image (open-library, z39-server, etc.). On subsequent starts the directory is left as-is, so user-installed plugins persist.
The entrypoint skips auto-generating .env if the file already exists in the container. You can supply your own by adding a bind mount to the pinakes service in docker-compose.yml:
volumes:
- ./my.env:/var/www/pinakes/.env:rodocker-compose.yml: The main Docker Compose file that defines the services.Dockerfile: Builds thepinakesPHP-FPM image.Dockerfile.nginx: Builds thenginximage with the config baked in.docker-entrypoint.sh: The entrypoint script for thepinakescontainer.nginx.conf: The Nginx configuration file (baked into the nginx image at build time).php-custom.ini: Custom PHP settings.php-fpm-www.conf: PHP-FPM pool configuration..dockerignore: Specifies files to ignore when building the Docker images..github/workflows/docker-publish.yml: GitHub Actions workflow that builds and pushes both thepinakesandnginximages toghcr.ioon every push tomainand onv*tags.
Contributions are welcome! If you have suggestions for improving this Docker setup, please feel free to open an issue or submit a pull request.
This project is open-source and available under the MIT License.