From 3c24a6f214e3fdd1ea59b36a8449891fdcb02c02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milan=20Felix=20=C5=A0ulc?= Date: Mon, 28 Sep 2026 19:45:27 +0000 Subject: [PATCH 1/8] Makefile: add help target and target descriptions Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_012DSzm4XsY7riy11DAVjsaB --- Makefile | 161 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 121 insertions(+), 40 deletions(-) diff --git a/Makefile b/Makefile index 493ea19..10197ff 100644 --- a/Makefile +++ b/Makefile @@ -3,62 +3,143 @@ DOCKER_PLATFORMS?=linux/amd64 DOCKER_RUN_PORT?=8000 DOCKER_RUN_TAG?=full -build: build-all +.DEFAULT_GOAL := help -test: test-all +##@ Help -run: +.PHONY: help +help: ## Show this help + @awk 'BEGIN {FS = ":.*##"; printf "Usage: make \033[36m\033[0m\n"} /^[a-zA-Z0-9_.-]+:.*##/ { sub(/^ +/, "", $$2); printf " \033[36m%-20s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) }' $(firstword $(MAKEFILE_LIST)) + +##@ Docker + +.PHONY: build +build: build-all ## Build all variant images + +.PHONY: test +test: test-all ## Test all variant images + +.PHONY: run +run: ## Run one image on port 8000 (DOCKER_RUN_TAG=full) docker run --rm -it -p ${DOCKER_RUN_PORT}:80 ${DOCKER_IMAGE}:${DOCKER_RUN_TAG} -build-all: build-full build-dg build-editor build-mongo build-mssql build-mysql build-postgres build-oracle-11 build-oracle-12 build-oracle-19 +.PHONY: build-all +build-all: build-full build-dg build-editor build-mongo build-mssql build-mysql build-postgres build-oracle-11 build-oracle-12 build-oracle-19 ## Build all variant images + +.PHONY: test-all +test-all: test-full test-dg test-editor test-mongo test-mssql test-mysql test-postgres test-oracle-11 test-oracle-12 test-oracle-19 ## Run php --version in all variant images _docker-build-%: TAG=$* _docker-build-%: docker buildx build --platform ${DOCKER_PLATFORMS} -t ${DOCKER_IMAGE}:${TAG} -f ./adminer-${TAG}/Dockerfile . -build-full: _docker-build-full -build-dg: _docker-build-dg -build-editor: _docker-build-editor -build-mongo: _docker-build-mongo -build-mssql: _docker-build-mssql -build-mysql: _docker-build-mysql -build-postgres: _docker-build-postgres -build-oracle-11: _docker-build-oracle-11 -build-oracle-12: _docker-build-oracle-12 -build-oracle-19: _docker-build-oracle-19 - _docker-test-%: TAG=$* _docker-test-%: docker run --rm --platform ${DOCKER_PLATFORMS} ${DOCKER_IMAGE}:${TAG} php --version -test-full: _docker-test-full -test-dg: _docker-test-dg -test-editor: _docker-test-editor -test-mongo: _docker-test-mongo -test-mssql: _docker-test-mssql -test-mysql: _docker-test-mysql -test-postgres: _docker-test-postgres -test-oracle-11: _docker-test-oracle-11 -test-oracle-12: _docker-test-oracle-12 -test-oracle-19: _docker-test-oracle-19 - -test-all: test-full test-dg test-editor test-mongo test-mssql test-mysql test-postgres test-oracle-11 test-oracle-12 test-oracle-19 - _docker-run-%: TAG=$* _docker-run-%: docker run --rm -it -p ${DOCKER_RUN_PORT}:80 ${DOCKER_IMAGE}:${TAG} -run-full: _docker-run-full -run-dg: _docker-run-dg -run-editor: _docker-run-editor -run-mongo: _docker-run-mongo -run-mssql: _docker-run-mssql -run-mysql: _docker-run-mysql -run-postgres: _docker-run-postgres -run-oracle-11: _docker-run-oracle-11 -run-oracle-12: _docker-run-oracle-12 -run-oracle-19: _docker-run-oracle-19 - -update-versions: +##@ Build Variants + +.PHONY: build-full +build-full: _docker-build-full ## Build the full (MySQL, PostgreSQL, SQLite, MongoDB) image + +.PHONY: build-dg +build-dg: _docker-build-dg ## Build the adminer-custom image + +.PHONY: build-editor +build-editor: _docker-build-editor ## Build the Adminer Editor image + +.PHONY: build-mongo +build-mongo: _docker-build-mongo ## Build the MongoDB image + +.PHONY: build-mssql +build-mssql: _docker-build-mssql ## Build the MS SQL Server image + +.PHONY: build-mysql +build-mysql: _docker-build-mysql ## Build the MySQL image + +.PHONY: build-postgres +build-postgres: _docker-build-postgres ## Build the PostgreSQL image + +.PHONY: build-oracle-11 +build-oracle-11: _docker-build-oracle-11 ## Build the Oracle 11 image + +.PHONY: build-oracle-12 +build-oracle-12: _docker-build-oracle-12 ## Build the Oracle 12 image + +.PHONY: build-oracle-19 +build-oracle-19: _docker-build-oracle-19 ## Build the Oracle 19 image + +##@ Test Variants + +.PHONY: test-full +test-full: _docker-test-full ## Test the full (MySQL, PostgreSQL, SQLite, MongoDB) image + +.PHONY: test-dg +test-dg: _docker-test-dg ## Test the adminer-custom image + +.PHONY: test-editor +test-editor: _docker-test-editor ## Test the Adminer Editor image + +.PHONY: test-mongo +test-mongo: _docker-test-mongo ## Test the MongoDB image + +.PHONY: test-mssql +test-mssql: _docker-test-mssql ## Test the MS SQL Server image + +.PHONY: test-mysql +test-mysql: _docker-test-mysql ## Test the MySQL image + +.PHONY: test-postgres +test-postgres: _docker-test-postgres ## Test the PostgreSQL image + +.PHONY: test-oracle-11 +test-oracle-11: _docker-test-oracle-11 ## Test the Oracle 11 image + +.PHONY: test-oracle-12 +test-oracle-12: _docker-test-oracle-12 ## Test the Oracle 12 image + +.PHONY: test-oracle-19 +test-oracle-19: _docker-test-oracle-19 ## Test the Oracle 19 image + +##@ Run Variants + +.PHONY: run-full +run-full: _docker-run-full ## Run the full (MySQL, PostgreSQL, SQLite, MongoDB) image on port 8000 + +.PHONY: run-dg +run-dg: _docker-run-dg ## Run the adminer-custom image on port 8000 + +.PHONY: run-editor +run-editor: _docker-run-editor ## Run the Adminer Editor image on port 8000 + +.PHONY: run-mongo +run-mongo: _docker-run-mongo ## Run the MongoDB image on port 8000 + +.PHONY: run-mssql +run-mssql: _docker-run-mssql ## Run the MS SQL Server image on port 8000 + +.PHONY: run-mysql +run-mysql: _docker-run-mysql ## Run the MySQL image on port 8000 + +.PHONY: run-postgres +run-postgres: _docker-run-postgres ## Run the PostgreSQL image on port 8000 + +.PHONY: run-oracle-11 +run-oracle-11: _docker-run-oracle-11 ## Run the Oracle 11 image on port 8000 + +.PHONY: run-oracle-12 +run-oracle-12: _docker-run-oracle-12 ## Run the Oracle 12 image on port 8000 + +.PHONY: run-oracle-19 +run-oracle-19: _docker-run-oracle-19 ## Run the Oracle 19 image on port 8000 + +##@ Maintenance + +.PHONY: update-versions +update-versions: ## Set ENV ADMINER_VERSION in every Dockerfile (ADMINER_VERSION=x, BSD sed) find . -type f -name Dockerfile -exec sed -i '' 's/ENV ADMINER_VERSION=.*/ENV ADMINER_VERSION=${ADMINER_VERSION}/g' {} + find . -type f -name Dockerfile -exec sed -i '' 's/ENV ADMINER_EDITOR_VERSION=.*/ENV ADMINER_EDITOR_VERSION=${ADMINER_VERSION}/g' {} + From e04aa0ad615bb2cf6b550112e4918b7324326a46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milan=20Felix=20=C5=A0ulc?= Date: Mon, 28 Sep 2026 19:45:27 +0000 Subject: [PATCH 2/8] AI: add agents instructions Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_012DSzm4XsY7riy11DAVjsaB --- AGENTS.md | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ CLAUDE.md | 1 + 2 files changed, 81 insertions(+) create mode 100644 AGENTS.md create mode 100644 CLAUDE.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..daee9e5 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,80 @@ +# Dockette / Adminer + +Instructions for AI coding agents working in this repository. + +## Overview + +`dockette/adminer` serves the Adminer database UI with the PHP built-in web server on port `80`, one image per +database driver set. It is a service image (see IMAGES.md): upstream `adminer-{version}.php` plus our entrypoint, +three plugins in `.plugins/` and the upstream themes. It is not a database and holds no data. + +- **Image**: `dockette/adminer`, tags `full`, `editor`, `mysql`, `postgres`, `mongo`, `mssql`, `oracle-11`, + `oracle-12`, `oracle-19`, `dg`; `latest` is built from `adminer-full/` +- **Base**: official `alpine:3.23` (`alpine:3.22` for `mysql`) with PHP 8.4 from the community repository; + `dockette/debian:bookworm-slim` with PHP 8.4 from `packages.sury.org` for `mssql` and `oracle-*` +- **Adminer**: `ENV ADMINER_VERSION=6.1.0` (`ADMINER_EDITOR_VERSION` in `editor`), downloaded from GitHub releases +- **Platforms**: `linux/amd64`, `linux/arm64`; `mssql` and `oracle-*` are `linux/amd64` only +- **Layout**: one folder per variant (`adminer-full/`), each with a `Dockerfile` and an `entrypoint.sh`; shared + plugins in `.plugins/`; screenshots in `.docs/assets/` + +## Documentation + +- `DESIGN.md` describes what we change in the UI (themes, plugins, login form). Read it before changing + `.plugins/`, a theme or the theme and plugin code in `entrypoint.sh`. +- `README.md` holds the tag list, the environment variables and the theme screenshots, and is the Docker Hub + description; the `docs` job publishes it from `master`. +- `docker-compose.yml` builds `adminer-full` next to MariaDB and PostgreSQL with the server list plugin on. +- Organization rules are in [dockette/dockette specs](https://github.com/dockette/dockette/tree/master/specs). + +## Commands + +```bash +# Build and test all ten variants (build = build-all, test = test-all) +make build +make test + +# Build, test and run one variant on port 8000 +make build-mysql +make test-mysql +make run-mysql +make run DOCKER_RUN_TAG=postgres + +# Try the plugins against real databases +docker compose up --build +``` + +`make test` only runs `php --version`. CI does more: the `test` job builds each tag for `linux/amd64` with +`docker/build-push-action`, runs `php --version`, starts the container and checks that `curl` on port `80` +returns a page containing "adminer". The `build` job pushes every tag from `master` only. There is no `VERSION` +variable; use the per-variant targets. + +## Conventions + +- Build from the repository root: `-f ./adminer-{tag}/Dockerfile .`, so `.plugins/` can be copied. The Makefile + and the workflow both do this. +- A new variant is a folder `adminer-{tag}/`, `build-`, `test-` and `run-` targets plus the `build-all` and + `test-all` lists in the `Makefile`, an entry in both workflow matrices and a README row. +- Plugins are opt-in: `ADMINER_PLUGIN_{NAME}=1` copies `.plugins/adminer-{name}.php` into `/srv/adminer-plugins/`, + which Adminer loads on its own. + +## Traps + +- **Every `entrypoint.sh` is a separate copy.** They differ on purpose: only `full` copies the upstream driver + plugins, `mssql` enables `mssql-encrypt` by default and has no autologin or server list, `dg` has no plugins + and no themes. Apply a shared change to each folder that has the feature. +- **The `dg` variant is not upstream Adminer.** It downloads the `adminer-custom` release archive + (`ENV ADMINER_DG_VERION`, spelled that way) and `update-versions` does not touch it. +- **`make update-versions` needs BSD `sed`.** It runs `sed -i ''`, which fails with GNU `sed` on Linux. It sets + `ADMINER_VERSION` and `ADMINER_EDITOR_VERSION` in every `Dockerfile`. +- **`WORKERS` has no effect at runtime.** `PHP_CLI_SERVER_WORKERS=${WORKERS}` is resolved at build time, so + `-e WORKERS=4` changes nothing; `-e PHP_CLI_SERVER_WORKERS=4` does. +- **Autologin wins over the server list.** The entrypoints use `if`/`elif`, so both variables set means only + `adminer-autologin.php` is active. +- **Autologin opens the database to anyone who reaches the port.** The DSN credentials are used for every + visitor without a login form; never publish such a container. +- **Oracle Instant Client comes from outside Oracle for 11 and 12.** `oracle-11` and `oracle-12` download the zips + from `github.com/f00b4r/oracle-instantclient`; `oracle-19` downloads from `download.oracle.com`. None is + checksum-verified. +- **There is no `.dockerignore`.** The build context is the whole repository, including `.docs/`. It is safe only + because each `Dockerfile` copies named paths; keep it that way. +- Usage for image users (environment variables, plugins, themes, ports) lives in `README.md`, not here. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..43c994c --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +@AGENTS.md From 91b0bf8e6267b6a4b560dfadaa17bebb0e214a0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milan=20Felix=20=C5=A0ulc?= Date: Mon, 28 Sep 2026 19:45:27 +0000 Subject: [PATCH 3/8] Docs: add design notes Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_012DSzm4XsY7riy11DAVjsaB --- DESIGN.md | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 DESIGN.md diff --git a/DESIGN.md b/DESIGN.md new file mode 100644 index 0000000..31e11c9 --- /dev/null +++ b/DESIGN.md @@ -0,0 +1,104 @@ +# Adminer Design + +The Adminer images serve the Adminer database UI on port `80`. Developers open it in a browser to inspect and +edit databases in local and staging stacks. The UI is upstream [Adminer](https://www.adminer.org); this file +describes only what the image adds on top of it. + +## Principles + +- **Upstream UI, unmodified PHP.** The `Dockerfile` downloads the release file `adminer-{version}.php` (or + `editor-{version}.php`) to `/srv/index.php`; nothing patches it. +- **Everything is opt-in by environment.** Themes and plugins are off until a variable turns them on, so a + container started with no variables looks like upstream Adminer. The one exception is `mssql`, where + `mssql-encrypt` is on by default. +- **Credentials never reach the browser.** The server list and autologin plugins parse DSNs from the environment + on the server; the page only receives server names. +- **One entrypoint per variant.** Each `adminer-{tag}/entrypoint.sh` enables only the features its variant + supports. + +## Inventory + +- Login and database screens: upstream `adminer-{version}.php`, served as `/srv/index.php` (`ADMINER_VERSION`). +- Editor screens (`editor` tag): upstream `editor-{version}.php`, the data-only Adminer Editor. +- Server dropdown with Auto Sign-In: `.plugins/adminer-server-list.php`, enabled by `ADMINER_PLUGIN_SERVER_LIST=1`. +- Autologin, which skips the login form: `.plugins/adminer-autologin.php`, enabled by `ADMINER_PLUGIN_AUTOLOGIN=1`. +- MSSQL encryption options: `.plugins/adminer-mssql-encrypt.php`, `mssql` tag only, on unless + `ADMINER_PLUGIN_MSSQL_ENCRYPT=0`. +- Upstream driver plugins: the release `plugins/drivers/` folder, copied into `/srv/adminer-plugins/` at start, + `full` tag only. +- Themes: the release `designs/` folder, copied to `/srv/designs/` at build time (not in `dg`). +- The `dg` tag serves the separate `adminer-custom` project with its own look. None of the plugins or themes + above apply to it. +- The other variants differ in drivers, not in UI: `full`, `mysql`, `postgres`, `mongo`, `mssql`, `oracle-*`. + +## Layout + +- Upstream. The server list plugin changes the login form: the Server text field becomes a `` helper and a plain + ``, both keyboard reachable. Its button is hidden with `display: none` for servers without + credentials. + +## Dark Mode + +- Only through a theme that ships `adminer-dark.css`; how it is switched on is upstream behaviour. + +## Responsive + +- Desktop first, as upstream. Our plugins add no layout of their own and are not tested on narrow screens. + +## Screenshots + +- `.docs/assets/adminer.png` (default look), `.docs/assets/adminer-dg.png` (`dg` tag) and + `.docs/assets/themes/{name}.png`, one per theme, shown 200 px wide in the README table. +- To retake one, run `make build-full`, then `docker run --rm -p 8000:80 -e ADMINER_THEME={name} + dockette/adminer:full`, open `http://localhost:8000` and capture the login screen. +- After an Adminer version bump, retake the default screenshot and check the theme list against `designs/`. + +## Changing the UI + +- Variable names (`ADMINER_THEME`, `ADMINER_PLUGIN_*`, `ADMINER_SERVERS_*`, `ADMINER_AUTOLOGIN_SERVER`) are + public; rename them only with a deprecation note in the README. +- A new upstream major can change the plugin API (`Adminer\Plugin`, `loginFormField`, `credentials`); start + every variant and log in once. +- The server list script finds the Login button by `value="Login"`; an upstream label change hides the Auto + Sign-In button. +- Adding a theme to the README table needs its screenshot in `.docs/assets/themes/`. + +## Checklist + +- [ ] The default container (no variables) looks like upstream Adminer +- [ ] Each changed plugin tested with and without credentials, in `full` and one Debian variant +- [ ] `ADMINER_THEME` with a valid and an invalid name +- [ ] No DSN or password appears in the page source +- [ ] `mssql` still connects with `ADMINER_PLUGIN_MSSQL_ENCRYPT` unset and set to `0` +- [ ] Screenshots updated if the UI changed From d154ae17c74919d403874633166185e7603091c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milan=20Felix=20=C5=A0ulc?= Date: Mon, 28 Sep 2026 19:45:27 +0000 Subject: [PATCH 4/8] Config: add fxnorm configuration Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_012DSzm4XsY7riy11DAVjsaB --- fxnorm.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 fxnorm.yml diff --git a/fxnorm.yml b/fxnorm.yml new file mode 100644 index 0000000..5b45951 --- /dev/null +++ b/fxnorm.yml @@ -0,0 +1,12 @@ +# fxnorm configuration, written by `fxnorm init`. +# `fxnorm config` prints what runs and why; `fxnorm rules` lists every rule with its group. + +# A Dockette Docker image repository (a Dockerfile in the root or one folder below) +presets: + - dockette-image + +# groups: # add a group, or drop one with a leading minus +# - -ci + +# rules: # false, true, error, warning, or options +# common/agents-md-length: {min: 50, max: 120} From 039d87dd53c66b885de0fbb4439a953005282b0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milan=20Felix=20=C5=A0ulc?= Date: Mon, 28 Sep 2026 19:45:27 +0000 Subject: [PATCH 5/8] Readme: describe package, usage and development Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_012DSzm4XsY7riy11DAVjsaB --- README.md | 239 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 122 insertions(+), 117 deletions(-) diff --git a/README.md b/README.md index d4c799f..fbe8c19 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,5 @@

Dockette / Adminer

-

- 🎁 Tiniest boxed dockerized Adminer (MySQL, PostgreSQL, SQLite, Mongo, Oracle, MSSQL) Dockerfiles. Database management in a single PHP file. -

- -

-🕹 f3l1x.io | 💻 f3l1x | 🐦 @xf3l1x -

-

GitHub Actions Docker Hub pulls @@ -15,158 +7,140 @@ Support/Discussions

-![Adminer](.docs/assets/adminer.png) - ------- - -## Prologue - -There are few variants of this adminer image based: +

+ Adminer 6.1.0, the single-file database manager, served by the PHP 8.4 built-in web server. Each tag carries the drivers for one database (mysql, postgres, mongo, mssql, oracle-19) or for several (full), on Alpine Linux or Debian Bookworm. For developers who need a database UI next to a local or staging stack. +

-- full (mysql, pgsql, sqlite, mongo) -- mysql (only) -- pgsql (only) -- mongo (only) -- mssql (only) -- oracle-11 / oracle-12 / oracle-19 (only) -- dg (custom) +

+🕹 f3l1x.io | 💻 f3l1x | 🐦 @xf3l1x +

-**Features** +

+ Adminer login screen +

-- Alpine Linux (full, editor, dg, mongo, mysql, postgres) -- Debian Bookworm (mssql, oracle-11, oracle-12, oracle-19) -- PHP 8 (concurrency via PHP cli workers) +----- ## Usage -```sh -docker run \ - --rm - -p 8000:80 - dockette/adminer:dg -``` - -By default container is running with these settings, you can override it using environment variables. - -- `MEMORY=256M` (memory_limit) -- `UPLOAD=2048M` (upload_max_filesize, post_max_size) -- `PORT=80` (PHP server listening port) -- `WORKERS=4` (concurrency) +Run Adminer with the MySQL, PostgreSQL, SQLite and MongoDB drivers on port `8000`: ```sh -docker run \ - --rm - -p 8000:8080 - -e MEMORY=512M - -e UPLOAD=4096M - -e PORT=8080 - dockette/adminer:dg +docker run --rm -p 8000:80 dockette/adminer:full ``` -## Versions - -| Image | Technologies | Size | Docker Hub | -|------------------------------|---------------------------------------|------|---------------------------------------------------------| -| dockette/adminer | MySQL / PostgreSQL / MongoDB / Sqlite | 12mb | [link](https://hub.docker.com/r/dockette/adminer/tags/) | -| dockette/adminer:full | MySQL / PostgreSQL / MongoDB / Sqlite | 12mb | [link](https://hub.docker.com/r/dockette/adminer/tags/) | -| dockette/adminer:mysql | MySQL | 9mb | [link](https://hub.docker.com/r/dockette/adminer/tags/) | -| dockette/adminer:pgsql | PostgreSQL | 8mb | [link](https://hub.docker.com/r/dockette/adminer/tags/) | -| dockette/adminer:mongo | MongoDB | 9mb | [link](https://hub.docker.com/r/dockette/adminer/tags/) | -| dockette/adminer:mssql | MS SQL Server | - | [link](https://hub.docker.com/r/dockette/adminer/tags/) | -| dockette/adminer:dg | MySQL / PostgreSQL / MongoDB / Sqlite | 16mb | [link](https://hub.docker.com/r/dockette/adminer/tags/) | - -### `dockette/adminer:mssql` +Open `http://localhost:8000` and log in to your database server. The image is based on `alpine:3.23` and needs +no volume. It listens on port `80`, runs as root and has no `HEALTHCHECK`. -Debian-based image with Microsoft ODBC Driver 18 and PHP `sqlsrv` / `pdo_sqlsrv` extensions. +Change the PHP limits and the port: ```sh -docker run \ - --rm \ - -p 8080:80 \ - dockette/adminer:mssql +docker run --rm -p 8000:8080 \ + -e MEMORY=512M \ + -e UPLOAD=4096M \ + -e PORT=8080 \ + dockette/adminer:full ``` -By default, `TrustServerCertificate` is set to `yes` so the image works out of the box with self-signed certificates (common in development). You can control encryption behavior via environment variables: - -| Variable | Description | Default | -|---|---|---| -| `ADMINER_PLUGIN_MSSQL_ENCRYPT` | Set to `0` to disable the encryption plugin | enabled | -| `ADMINER_MSSQL_ENCRYPT` | `yes`, `no`, or `strict` | not set | -| `ADMINER_MSSQL_TRUST_CERT` | `yes` or `no` | `yes` | +> [!CAUTION] +> Adminer gives full access to every database it can reach. Don't expose the port to the internet, and never +> publish a container with the autologin plugin enabled. -### `dockette/adminer:dg` - -> Customization for the best database management tool written in PHP, Adminer - -You should take a look to the official github profile (https://github.com/dg/adminer-custom). +## Versions -![Adminer DG](.docs/assets/adminer-dg.png) +| Tag | Description | +|-----|-------------| +| `dockette/adminer:full` | MySQL, PostgreSQL, SQLite and MongoDB drivers, plus the upstream driver plugins; Alpine 3.23 | +| `dockette/adminer:latest` | Same as `full` | +| `dockette/adminer:editor` | [Adminer Editor](https://www.adminer.org/en/editor/) (data only) with MySQL, PostgreSQL and MongoDB; Alpine 3.23 | +| `dockette/adminer:mysql` | MySQL and MariaDB; Alpine 3.22 | +| `dockette/adminer:postgres` | PostgreSQL; Alpine 3.23 | +| `dockette/adminer:mongo` | MongoDB; Alpine 3.23 | +| `dockette/adminer:mssql` | MS SQL Server with Microsoft ODBC Driver 18 and `sqlsrv`, `pdo_sqlsrv`; Debian Bookworm, `linux/amd64` only | +| `dockette/adminer:oracle-19` | Oracle with Instant Client 19.30 and `oci8`; Debian Bookworm, `linux/amd64` only | +| `dockette/adminer:oracle-12` | Oracle with Instant Client 12.1 and `oci8`; Debian Bookworm, `linux/amd64` only | +| `dockette/adminer:oracle-11` | Oracle with Instant Client 11.2 and `oci8`; Debian Bookworm, `linux/amd64` only | +| `dockette/adminer:dg` | The `adminer-custom` 3.4.1 build with MySQL, PostgreSQL and MongoDB; Alpine 3.23. No plugins or themes | + +The Alpine tags are built for `linux/amd64` and `linux/arm64`; Microsoft and Oracle ship their drivers for +`amd64` only. Every tag is rebuilt every Monday. + +## Environment + +| Variable | Default | Description | +|----------|---------|-------------| +| `MEMORY` | `256M` | PHP `memory_limit` | +| `UPLOAD` | `2048M` | PHP `upload_max_filesize` and `post_max_size` | +| `PORT` | `80` | Port of the PHP built-in web server inside the container | +| `PHP_CLI_SERVER_WORKERS` | `8` | Number of PHP server workers. `WORKERS` only sets it at build time | +| `ADMINER_THEME` | (none) | Theme name from the table below | +| `ADMINER_PLUGIN_AUTOLOGIN` | (off) | `1` enables the autologin plugin | +| `ADMINER_AUTOLOGIN_SERVER` | (none) | DSN for autologin | +| `ADMINER_PLUGIN_SERVER_LIST` | (off) | `1` enables the server list plugin | +| `ADMINER_SERVERS_{Name}` | (none) | DSN of one server in the list; `{Name}` is its label | +| `ADMINER_PLUGIN_MSSQL_ENCRYPT` | (on) | `mssql` only: `0` disables the encryption plugin | +| `ADMINER_MSSQL_ENCRYPT` | (not set) | `mssql` only: `yes`, `no` or `strict` | +| `ADMINER_MSSQL_TRUST_CERT` | `yes` | `mssql` only: `TrustServerCertificate`, `yes` or `no` | +| `ADMINER_BANNER` | (on) | `0`, `false`, `no` or `off` hides the start banner | +| `ADMINER_DEBUG` | (off) | `1` traces the entrypoint with `set -x` | + +The `ADMINER_*` variables for themes and plugins work in every tag except `dg`. ## Plugins -Adminer plugins can be enabled via environment variables. All plugins are disabled by default. Available for all image variants except `dg`. +Plugins are off by default. A DSN has the form `driver://username:password@host:port/database`, where `driver` +is the Adminer driver name: `server` (MySQL and MariaDB), `pgsql`, `sqlite`, `oracle` or `mongo`. ### Autologin -Skips the login form and connects directly to a database server. - -| Variable | Description | -|---|---| -| `ADMINER_PLUGIN_AUTOLOGIN=1` | Enable the autologin plugin | -| `ADMINER_AUTOLOGIN_SERVER` | DSN connection string | - -DSN format: `driver://username:password@host:port/database` +Autologin skips the login form and connects to one server with the credentials from the DSN: ```sh -docker run \ - --rm \ - -p 8080:80 \ +docker run --rm -p 8000:80 \ -e ADMINER_PLUGIN_AUTOLOGIN=1 \ -e ADMINER_AUTOLOGIN_SERVER=server://root:secret@mysql:3306/mydb \ dockette/adminer:full ``` -Supported drivers: `server` (MySQL/MariaDB), `pgsql`, `sqlite`, `mongo`, `oracle`, `elastic`. - ### Server List -Displays a dropdown of pre-configured database servers with an **Auto Sign-In** button. Credentials are handled server-side and never exposed to the browser. - -| Variable | Description | -|---|---| -| `ADMINER_PLUGIN_SERVER_LIST=1` | Enable the server list plugin | -| `ADMINER_SERVERS_` | DSN for each server (suffix becomes the display name) | +The server list replaces the server field with a dropdown of preset servers and adds an Auto Sign-In button for +servers with stored credentials. The credentials stay on the server and never reach the browser: ```sh -docker run \ - --rm \ - -p 8080:80 \ +docker run --rm -p 8000:80 \ -e ADMINER_PLUGIN_SERVER_LIST=1 \ -e ADMINER_SERVERS_MySQL=server://root:secret@mysql:3306/mydb \ -e ADMINER_SERVERS_PostgreSQL=pgsql://postgres:pwd@pg:5432/app \ - -e ADMINER_SERVERS_DevDB=server://dev@devhost:3306 \ + -e ADMINER_SERVERS_DevDB=server://devhost:3306 \ dockette/adminer:full ``` -Servers without credentials in the DSN (e.g. `server://devhost:3306`) appear in the dropdown but require manual login. The **Auto Sign-In** button only appears for servers with stored credentials. +A server without credentials in its DSN, like `DevDB` above, is listed but needs a manual login. -> **Note:** Autologin takes precedence over Server List. If both plugins are enabled, only Autologin is activated. +> [!NOTE] +> Autologin takes precedence. When both plugins are enabled, only autologin is active. -## Themes +### MSSQL Encryption -You can apply a theme by setting the `ADMINER_THEME` environment variable: +The `mssql` tag enables its encryption plugin by default with `TrustServerCertificate=yes`, so it connects to +servers with self-signed certificates: ```sh -docker run \ - --rm - -p 8000:80 - -e ADMINER_THEME=dracula - dockette/adminer:full +docker run --rm -p 8000:80 -e ADMINER_MSSQL_ENCRYPT=strict -e ADMINER_MSSQL_TRUST_CERT=no dockette/adminer:mssql ``` -If the specified theme is not found, the container will list all available themes. +The `mssql` tag has no autologin and no server list. + +## Themes + +`ADMINER_THEME` selects one of the themes from the Adminer release: -### Available Themes +```sh +docker run --rm -p 8000:80 -e ADMINER_THEME=dracula dockette/adminer:full +``` + +When the theme is not found, the container prints the available names and starts with the default look. @@ -213,14 +187,45 @@ If the specified theme is not found, the container will list all available theme
-## Upgrade +## Adminer Custom + +The `dg` tag serves the [`adminer-custom`](https://github.com/dg/adminer-custom) project, a customised Adminer with its own plugins and look, instead of +the upstream release: + +```sh +docker run --rm -p 8000:80 dockette/adminer:dg +``` + +adminer-custom login screen + +## Compose + +The [`docker-compose.yml`](https://github.com/dockette/adminer/blob/master/docker-compose.yml) in this repository +builds the `full` image and starts it on port `8080` next to MariaDB 11 and PostgreSQL 17, with the server list +plugin enabled: + +```sh +docker compose up --build +``` + +## Development -**Upgrade Adminer and Adminer Editor versions to X.Y.Z** +Build and test all tags, or build and run one of them on port `8000`: -```bash -ADMINER_VERSION=4.8.1 make update-versions +```sh +make build +make test +make build-mysql +make run-mysql +``` + +`make test` runs `php --version` in each image. `make help` lists every target. To move all Dockerfiles to a new +Adminer release (the `sed` call needs macOS or BSD `sed`): + +```sh +ADMINER_VERSION=6.1.0 make update-versions ``` ## Maintenance -See [how to contribute](https://github.com/dockette/.github/blob/master/CONTRIBUTING.md) to this package. Consider to [support](https://github.com/sponsors/f3l1x) **f3l1x**. Thank you for using this package. +See [how to contribute](https://github.com/dockette/.github/blob/master/CONTRIBUTING.md) to this package. Consider [supporting](https://github.com/sponsors/f3l1x) **f3l1x**. Thank you for using this package. From f0b73004572b90f4177bb1680f09c4d4ffc13a85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milan=20Felix=20=C5=A0ulc?= Date: Tue, 29 Sep 2026 17:26:19 +0000 Subject: [PATCH 6/8] AI: simplify agents instructions to development essentials Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_012DSzm4XsY7riy11DAVjsaB --- AGENTS.md | 86 +++++++++++-------------------------------------------- 1 file changed, 17 insertions(+), 69 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index daee9e5..a6ba019 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,80 +1,28 @@ # Dockette / Adminer -Instructions for AI coding agents working in this repository. +Adminer database UI served by the PHP built-in web server, one image per database driver set. -## Overview +## Stack -`dockette/adminer` serves the Adminer database UI with the PHP built-in web server on port `80`, one image per -database driver set. It is a service image (see IMAGES.md): upstream `adminer-{version}.php` plus our entrypoint, -three plugins in `.plugins/` and the upstream themes. It is not a database and holds no data. +- Docker image built with `docker buildx`, base `alpine:3.23` or `dockette/debian:bookworm-slim` (MS SQL, Oracle) +- Adminer 6.1.0 on PHP 8 +- Published to Docker Hub as `dockette/adminer` for linux/amd64 and linux/arm64 by GitHub Actions -- **Image**: `dockette/adminer`, tags `full`, `editor`, `mysql`, `postgres`, `mongo`, `mssql`, `oracle-11`, - `oracle-12`, `oracle-19`, `dg`; `latest` is built from `adminer-full/` -- **Base**: official `alpine:3.23` (`alpine:3.22` for `mysql`) with PHP 8.4 from the community repository; - `dockette/debian:bookworm-slim` with PHP 8.4 from `packages.sury.org` for `mssql` and `oracle-*` -- **Adminer**: `ENV ADMINER_VERSION=6.1.0` (`ADMINER_EDITOR_VERSION` in `editor`), downloaded from GitHub releases -- **Platforms**: `linux/amd64`, `linux/arm64`; `mssql` and `oracle-*` are `linux/amd64` only -- **Layout**: one folder per variant (`adminer-full/`), each with a `Dockerfile` and an `entrypoint.sh`; shared - plugins in `.plugins/`; screenshots in `.docs/assets/` - -## Documentation - -- `DESIGN.md` describes what we change in the UI (themes, plugins, login form). Read it before changing - `.plugins/`, a theme or the theme and plugin code in `entrypoint.sh`. -- `README.md` holds the tag list, the environment variables and the theme screenshots, and is the Docker Hub - description; the `docs` job publishes it from `master`. -- `docker-compose.yml` builds `adminer-full` next to MariaDB and PostgreSQL with the server list plugin on. -- Organization rules are in [dockette/dockette specs](https://github.com/dockette/dockette/tree/master/specs). - -## Commands +## Development ```bash -# Build and test all ten variants (build = build-all, test = test-all) -make build -make test - -# Build, test and run one variant on port 8000 -make build-mysql -make test-mysql -make run-mysql -make run DOCKER_RUN_TAG=postgres - -# Try the plugins against real databases -docker compose up --build +make build # build all variant images +make test # smoke test all variant images +make run # run one image on port 8000 (DOCKER_RUN_TAG=full) +make build-full # build one variant; also test-full, run-full ``` -`make test` only runs `php --version`. CI does more: the `test` job builds each tag for `linux/amd64` with -`docker/build-push-action`, runs `php --version`, starts the container and checks that `curl` on port `80` -returns a page containing "adminer". The `build` job pushes every tag from `master` only. There is no `VERSION` -variable; use the per-variant targets. - -## Conventions - -- Build from the repository root: `-f ./adminer-{tag}/Dockerfile .`, so `.plugins/` can be copied. The Makefile - and the workflow both do this. -- A new variant is a folder `adminer-{tag}/`, `build-`, `test-` and `run-` targets plus the `build-all` and - `test-all` lists in the `Makefile`, an entry in both workflow matrices and a README row. -- Plugins are opt-in: `ADMINER_PLUGIN_{NAME}=1` copies `.plugins/adminer-{name}.php` into `/srv/adminer-plugins/`, - which Adminer loads on its own. +Run `make` to list every target. -## Traps +## Principles -- **Every `entrypoint.sh` is a separate copy.** They differ on purpose: only `full` copies the upstream driver - plugins, `mssql` enables `mssql-encrypt` by default and has no autologin or server list, `dg` has no plugins - and no themes. Apply a shared change to each folder that has the feature. -- **The `dg` variant is not upstream Adminer.** It downloads the `adminer-custom` release archive - (`ENV ADMINER_DG_VERION`, spelled that way) and `update-versions` does not touch it. -- **`make update-versions` needs BSD `sed`.** It runs `sed -i ''`, which fails with GNU `sed` on Linux. It sets - `ADMINER_VERSION` and `ADMINER_EDITOR_VERSION` in every `Dockerfile`. -- **`WORKERS` has no effect at runtime.** `PHP_CLI_SERVER_WORKERS=${WORKERS}` is resolved at build time, so - `-e WORKERS=4` changes nothing; `-e PHP_CLI_SERVER_WORKERS=4` does. -- **Autologin wins over the server list.** The entrypoints use `if`/`elif`, so both variables set means only - `adminer-autologin.php` is active. -- **Autologin opens the database to anyone who reaches the port.** The DSN credentials are used for every - visitor without a login form; never publish such a container. -- **Oracle Instant Client comes from outside Oracle for 11 and 12.** `oracle-11` and `oracle-12` download the zips - from `github.com/f00b4r/oracle-instantclient`; `oracle-19` downloads from `download.oracle.com`. None is - checksum-verified. -- **There is no `.dockerignore`.** The build context is the whole repository, including `.docs/`. It is safe only - because each `Dockerfile` copies named paths; keep it that way. -- Usage for image users (environment variables, plugins, themes, ports) lives in `README.md`, not here. +- KISS: one image does one job; no extra services or tools. +- DRY: shared steps live in the base image, not copied into every Dockerfile. +- YAGNI: add a package only when the image needs it. +- Pin versions, keep layers small, clean package caches in the same `RUN`. +- Every change is built and smoke tested with `make build test` before a commit. From 484a8a68447adf7bbf36b748ee8dc312d32115b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milan=20Felix=20=C5=A0ulc?= Date: Tue, 29 Sep 2026 20:32:39 +0000 Subject: [PATCH 7/8] AI: drop CLAUDE.md, agents read AGENTS.md directly Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_012DSzm4XsY7riy11DAVjsaB --- CLAUDE.md | 1 - 1 file changed, 1 deletion(-) delete mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index 43c994c..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1 +0,0 @@ -@AGENTS.md From 2942fc0cda232153025bf4b8350f845b60f850a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milan=20Felix=20=C5=A0ulc?= Date: Tue, 29 Sep 2026 20:42:47 +0000 Subject: [PATCH 8/8] Readme: simplify usage and development Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_012DSzm4XsY7riy11DAVjsaB --- README.md | 107 ++++++++---------------------------------------------- 1 file changed, 16 insertions(+), 91 deletions(-) diff --git a/README.md b/README.md index fbe8c19..99289fc 100644 --- a/README.md +++ b/README.md @@ -23,24 +23,15 @@ ## Usage -Run Adminer with the MySQL, PostgreSQL, SQLite and MongoDB drivers on port `8000`: +Run the image and open `http://localhost:8000`: ```sh -docker run --rm -p 8000:80 dockette/adminer:full +docker run -p 8000:80 dockette/adminer ``` -Open `http://localhost:8000` and log in to your database server. The image is based on `alpine:3.23` and needs -no volume. It listens on port `80`, runs as root and has no `HEALTHCHECK`. - -Change the PHP limits and the port: - -```sh -docker run --rm -p 8000:8080 \ - -e MEMORY=512M \ - -e UPLOAD=4096M \ - -e PORT=8080 \ - dockette/adminer:full -``` +The image adds the drivers for its tag, a set of upstream plugins and themes, and an entrypoint that sets them up +from environment variables (see [Environment](#environment)). Pick a tag for your database from the table below; +see the [Adminer documentation](https://www.adminer.org/en/plugins/) for what the plugins do. > [!CAUTION] > Adminer gives full access to every database it can reach. Don't expose the port to the internet, and never @@ -88,59 +79,15 @@ The `ADMINER_*` variables for themes and plugins work in every tag except `dg`. ## Plugins -Plugins are off by default. A DSN has the form `driver://username:password@host:port/database`, where `driver` -is the Adminer driver name: `server` (MySQL and MariaDB), `pgsql`, `sqlite`, `oracle` or `mongo`. - -### Autologin - -Autologin skips the login form and connects to one server with the credentials from the DSN: - -```sh -docker run --rm -p 8000:80 \ - -e ADMINER_PLUGIN_AUTOLOGIN=1 \ - -e ADMINER_AUTOLOGIN_SERVER=server://root:secret@mysql:3306/mydb \ - dockette/adminer:full -``` - -### Server List - -The server list replaces the server field with a dropdown of preset servers and adds an Auto Sign-In button for -servers with stored credentials. The credentials stay on the server and never reach the browser: - -```sh -docker run --rm -p 8000:80 \ - -e ADMINER_PLUGIN_SERVER_LIST=1 \ - -e ADMINER_SERVERS_MySQL=server://root:secret@mysql:3306/mydb \ - -e ADMINER_SERVERS_PostgreSQL=pgsql://postgres:pwd@pg:5432/app \ - -e ADMINER_SERVERS_DevDB=server://devhost:3306 \ - dockette/adminer:full -``` - -A server without credentials in its DSN, like `DevDB` above, is listed but needs a manual login. - -> [!NOTE] -> Autologin takes precedence. When both plugins are enabled, only autologin is active. - -### MSSQL Encryption - -The `mssql` tag enables its encryption plugin by default with `TrustServerCertificate=yes`, so it connects to -servers with self-signed certificates: - -```sh -docker run --rm -p 8000:80 -e ADMINER_MSSQL_ENCRYPT=strict -e ADMINER_MSSQL_TRUST_CERT=no dockette/adminer:mssql -``` - -The `mssql` tag has no autologin and no server list. +Plugins are off by default and are switched on with the `ADMINER_PLUGIN_*` variables. A DSN has the form +`driver://username:password@host:port/database`, where `driver` is `server` (MySQL and MariaDB), `pgsql`, +`sqlite`, `oracle` or `mongo`. The server list keeps the credentials on the server; when autologin is also on, +only autologin is active. The `mssql` tag has no autologin and no server list. ## Themes -`ADMINER_THEME` selects one of the themes from the Adminer release: - -```sh -docker run --rm -p 8000:80 -e ADMINER_THEME=dracula dockette/adminer:full -``` - -When the theme is not found, the container prints the available names and starts with the default look. +`ADMINER_THEME` selects one of the themes from the Adminer release, for example `ADMINER_THEME=dracula`. When the +theme is not found, the container prints the available names and starts with the default look. @@ -190,41 +137,19 @@ When the theme is not found, the container prints the available names and starts ## Adminer Custom The `dg` tag serves the [`adminer-custom`](https://github.com/dg/adminer-custom) project, a customised Adminer with its own plugins and look, instead of -the upstream release: - -```sh -docker run --rm -p 8000:80 dockette/adminer:dg -``` +the upstream release. adminer-custom login screen -## Compose - -The [`docker-compose.yml`](https://github.com/dockette/adminer/blob/master/docker-compose.yml) in this repository -builds the `full` image and starts it on port `8080` next to MariaDB 11 and PostgreSQL 17, with the server list -plugin enabled: - -```sh -docker compose up --build -``` - ## Development -Build and test all tags, or build and run one of them on port `8000`: - ```sh -make build -make test -make build-mysql -make run-mysql +make build # build every tag +make test # smoke test every tag +make run # run the full tag on port 8000 ``` -`make test` runs `php --version` in each image. `make help` lists every target. To move all Dockerfiles to a new -Adminer release (the `sed` call needs macOS or BSD `sed`): - -```sh -ADMINER_VERSION=6.1.0 make update-versions -``` +Run `make` to list every target. ## Maintenance