Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion .github/workflows/image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ jobs:
- "4/fastcgi"
- "5"
- "5/fastcgi"
- "6"
- "6/fastcgi"
steps:
- uses: actions/checkout@v7
- name: Build the image.
Expand Down Expand Up @@ -83,14 +85,34 @@ jobs:
env:
container_name: adminer_defaultserver
- name: Verify that loading plugins work.
if: ${{ ! contains(steps.build.outputs.image, 'fastcgi') }}
if: ${{ ! contains(steps.build.outputs.image, 'fastcgi') && ! startsWith(matrix.variant, '6') }}
run: |
docker run --name $container_name -d -e ADMINER_PLUGINS="tables-filter version-noverify" ${{ steps.build.outputs.image }}
docker run -i --rm --link $container_name:$container_name buildpack-deps:curl \
curl -fsSL http://$container_name:8080/ \
|grep 'verifyVersion ='
env:
container_name: adminer_plugins
- name: Verify that loading plugins work.
if: ${{ ! contains(steps.build.outputs.image, 'fastcgi') && startsWith(matrix.variant, '6') }}
run: |
# Since Adminer 6, the version-noverify plugin no longer injects a
# 'verifyVersion =' script. Instead it suppresses the version check,
# so the 'partial(verifyVersion' onload handler (present by default)
# must disappear when the plugin is loaded.
docker run --name ${container_name}_default -d ${{ steps.build.outputs.image }}
docker run -i --rm --link ${container_name}_default:${container_name}_default buildpack-deps:curl \
curl -fsSL http://${container_name}_default:8080/ \
|grep 'partial(verifyVersion'
docker run --name $container_name -d -e ADMINER_PLUGINS="tables-filter version-noverify" ${{ steps.build.outputs.image }}
docker run -i --rm --link $container_name:$container_name buildpack-deps:curl \
curl -fsSL http://$container_name:8080/ \
|grep '<span class=.version.>'
! docker run -i --rm --link $container_name:$container_name buildpack-deps:curl \
curl -fsSL http://$container_name:8080/ \
|grep 'partial(verifyVersion'
env:
container_name: adminer_plugins
- name: Show Containers and Images
run: |
printf "::group::docker ps -a\n"
Expand Down
61 changes: 61 additions & 0 deletions 6/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
FROM php:8.4-alpine

RUN echo "upload_max_filesize = 128M" >> /usr/local/etc/php/conf.d/0-upload_large_dumps.ini \
&& echo "post_max_size = 128M" >> /usr/local/etc/php/conf.d/0-upload_large_dumps.ini \
&& echo "memory_limit = 1G" >> /usr/local/etc/php/conf.d/0-upload_large_dumps.ini \
&& echo "max_execution_time = 600" >> /usr/local/etc/php/conf.d/0-upload_large_dumps.ini \
&& echo "max_input_vars = 5000" >> /usr/local/etc/php/conf.d/0-upload_large_dumps.ini

STOPSIGNAL SIGINT

RUN addgroup -S adminer \
&& adduser -S -G adminer adminer \
&& mkdir -p /var/www/html \
&& mkdir /var/www/html/plugins-enabled \
&& chown -R adminer:adminer /var/www/html

WORKDIR /var/www/html

RUN set -x \
&& apk add --no-cache --virtual .build-deps \
postgresql-dev \
sqlite-dev \
unixodbc-dev \
freetds-dev \
&& docker-php-ext-configure pdo_odbc --with-pdo-odbc=unixODBC,/usr \
&& docker-php-ext-install \
mysqli \
pdo_pgsql \
pdo_sqlite \
pdo_odbc \
pdo_dblib \
&& runDeps="$( \
scanelf --needed --nobanner --format '%n#p' --recursive /usr/local/lib/php/extensions \
| tr ',' '\n' \
| sort -u \
| awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \
)" \
&& apk add --no-cache --virtual .phpexts-rundeps $runDeps \
&& apk del --no-network .build-deps

COPY *.php /var/www/html/

ENV ADMINER_VERSION=6.0.0
ENV ADMINER_DOWNLOAD_SHA256=8181c9be10f290243724acb0e4dc930fe04440a343fb11dcc8ddb9821095e274
ENV ADMINER_SRC_DOWNLOAD_SHA256=6e81950e86317a0c199a666d0118a315e410d179cc33111be88e41a122a0f7a8

RUN set -x \
&& curl -fsSL https://github.com/vrana/adminer/releases/download/v$ADMINER_VERSION/adminer-$ADMINER_VERSION.php -o adminer.php \
&& echo "$ADMINER_DOWNLOAD_SHA256 adminer.php" |sha256sum -c - \
&& curl -fsSL https://github.com/vrana/adminer/archive/v$ADMINER_VERSION.tar.gz -o source.tar.gz \
&& echo "$ADMINER_SRC_DOWNLOAD_SHA256 source.tar.gz" |sha256sum -c - \
&& tar xzf source.tar.gz --strip-components=1 "adminer-$ADMINER_VERSION/designs/" "adminer-$ADMINER_VERSION/plugins/" \
&& rm source.tar.gz

COPY entrypoint.sh /usr/local/bin/
ENTRYPOINT [ "entrypoint.sh", "docker-php-entrypoint" ]

USER adminer
CMD [ "php", "-S", "[::]:8080", "-t", "/var/www/html" ]

EXPOSE 8080
20 changes: 20 additions & 0 deletions 6/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/bin/sh
set -e

if [ -n "$ADMINER_DESIGN" ]; then
# Only create link on initial start, to ensure that explicit changes to
# adminer.css after the container was started once are preserved.
if [ ! -e .adminer-init ]; then
ln -sf "designs/$ADMINER_DESIGN/adminer.css" .
fi
fi

number=1
for PLUGIN in $ADMINER_PLUGINS; do
php plugin-loader.php "$PLUGIN" > plugins-enabled/$(printf "%03d" $number)-$PLUGIN.php
number=$(($number+1))
done

touch .adminer-init || true

exec "$@"
55 changes: 55 additions & 0 deletions 6/fastcgi/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
FROM php:8.4-fpm-alpine

RUN echo "upload_max_filesize = 128M" >> /usr/local/etc/php/conf.d/0-upload_large_dumps.ini \
&& echo "post_max_size = 128M" >> /usr/local/etc/php/conf.d/0-upload_large_dumps.ini \
&& echo "memory_limit = 1G" >> /usr/local/etc/php/conf.d/0-upload_large_dumps.ini \
&& echo "max_execution_time = 600" >> /usr/local/etc/php/conf.d/0-upload_large_dumps.ini \
&& echo "max_input_vars = 5000" >> /usr/local/etc/php/conf.d/0-upload_large_dumps.ini

RUN addgroup -S adminer \
&& adduser -S -G adminer adminer \
&& mkdir -p /var/www/html \
&& mkdir /var/www/html/plugins-enabled \
&& chown -R adminer:adminer /var/www/html

RUN set -x \
&& apk add --no-cache --virtual .build-deps \
postgresql-dev \
sqlite-dev \
unixodbc-dev \
freetds-dev \
&& docker-php-ext-configure pdo_odbc --with-pdo-odbc=unixODBC,/usr \
&& docker-php-ext-install \
mysqli \
pdo_pgsql \
pdo_sqlite \
pdo_odbc \
pdo_dblib \
&& runDeps="$( \
scanelf --needed --nobanner --format '%n#p' --recursive /usr/local/lib/php/extensions \
| tr ',' '\n' \
| sort -u \
| awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \
)" \
&& apk add --no-cache --virtual .phpexts-rundeps $runDeps \
&& apk del --no-network .build-deps

COPY *.php /var/www/html/

ENV ADMINER_VERSION=6.0.0
ENV ADMINER_DOWNLOAD_SHA256=8181c9be10f290243724acb0e4dc930fe04440a343fb11dcc8ddb9821095e274
ENV ADMINER_SRC_DOWNLOAD_SHA256=6e81950e86317a0c199a666d0118a315e410d179cc33111be88e41a122a0f7a8

RUN set -x \
&& curl -fsSL https://github.com/vrana/adminer/releases/download/v$ADMINER_VERSION/adminer-$ADMINER_VERSION.php -o adminer.php \
&& echo "$ADMINER_DOWNLOAD_SHA256 adminer.php" |sha256sum -c - \
&& curl -fsSL https://github.com/vrana/adminer/archive/v$ADMINER_VERSION.tar.gz -o source.tar.gz \
&& echo "$ADMINER_SRC_DOWNLOAD_SHA256 source.tar.gz" |sha256sum -c - \
&& tar xzf source.tar.gz --strip-components=1 "adminer-$ADMINER_VERSION/designs/" "adminer-$ADMINER_VERSION/plugins/" \
&& rm source.tar.gz

COPY entrypoint.sh /usr/local/bin/
ENTRYPOINT [ "entrypoint.sh", "docker-php-entrypoint" ]

USER adminer
CMD [ "php-fpm" ]
20 changes: 20 additions & 0 deletions 6/fastcgi/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/bin/sh
set -e

if [ -n "$ADMINER_DESIGN" ]; then
# Only create link on initial start, to ensure that explicit changes to
# adminer.css after the container was started once are preserved.
if [ ! -e .adminer-init ]; then
ln -sf "designs/$ADMINER_DESIGN/adminer.css" .
fi
fi

number=1
for PLUGIN in $ADMINER_PLUGINS; do
php plugin-loader.php "$PLUGIN" > plugins-enabled/$(printf "%03d" $number)-$PLUGIN.php
number=$(($number+1))
done

touch .adminer-init || true

exec "$@"
63 changes: 63 additions & 0 deletions 6/fastcgi/index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php
namespace docker {
function adminer_object() {
/**
* Prefills the “Server” field with the ADMINER_DEFAULT_SERVER environment variable.
*/
final class DefaultServerPlugin extends \Adminer\Plugin {
public function __construct(
private \Adminer\Adminer $adminer
) { }

public function loginFormField(...$args): string {
return (function (...$args): string {
$field = $this->loginFormField(...$args);

return \preg_replace_callback(
"/name='auth\[server\]' value='' title='(?:[^']+)'/",
static function (array $matches): string {
return \str_replace(
"value=''",
\sprintf("value='%s'", ($_ENV['ADMINER_DEFAULT_SERVER'] ?: 'db')),
$matches[0],
);
},
$field,
);
})->call($this->adminer, ...$args);
}
}

$plugins = [];
foreach (glob('plugins-enabled/*.php') as $plugin) {
$plugins[] = require($plugin);
}

$adminer = new \Adminer\Plugins($plugins);

(function () {
$last = &$this->hooks['loginFormField'][\array_key_last($this->hooks['loginFormField'])];
if ($last instanceof \Adminer\Adminer) {
$defaultServerPlugin = new DefaultServerPlugin($last);
$this->plugins[] = $defaultServerPlugin;
$last = $defaultServerPlugin;
}
})->call($adminer);

return $adminer;
}
}

namespace {
if (basename($_SERVER['DOCUMENT_URI'] ?? $_SERVER['REQUEST_URI']) === 'adminer.css' && is_readable('adminer.css')) {
header('Content-Type: text/css');
readfile('adminer.css');
exit;
}

function adminer_object() {
return \docker\adminer_object();
}

require('adminer.php');
}
78 changes: 78 additions & 0 deletions 6/fastcgi/plugin-loader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php

if (PHP_SAPI !== 'cli') exit;
if ($_SERVER['argc'] !== 2) exit;

$name = $_SERVER['argv'][1];
// Sanity checks.
if (basename($name) !== $name) {
fwrite(STDERR, 'Refusing to load plugin file "'.$name.'" for security reasons.'."\n");
exit(1);
}
if (!is_readable('plugins/'.$name.'.php')) {
fwrite(STDERR, 'Unable to find plugin file "'.$name.'".'."\n");
exit(1);
}

// Try to find class.
$file = 'plugins/'.$name.'.php';
$code = file_get_contents('plugins/'.$name.'.php');
$tokens = token_get_all($code);

$classFound = false;
$classes = [];
for ($i = 0, $max = count($tokens); $i < $max; $i++) {
if ($tokens[$i][0] === T_CLASS) $classFound = true;
if ($classFound && $tokens[$i][0] === T_STRING) {
$classes[] = $tokens[$i][1];
$classFound = false;
}
}

// Sanity checks.
if (count($classes) == 0) {
fwrite(STDERR, 'Unable to load plugin file "'.$name.'", because it does not define any classes.'."\n");
exit(1);
}

if (count($classes) > 1) {
fwrite(STDERR, 'Unable to load plugin file "'.$name.'", because it defines multiple classes.'."\n");
exit(1);
}

if (!class_exists(\Adminer\Plugin::class)) {
class_alias(stdClass::class, \Adminer\Plugin::class);
}

// Check constructor.
$class = $classes[0];
require($file);

$constructor = (new \ReflectionClass($class))->getConstructor();

if ($constructor && $constructor->getNumberOfRequiredParameters() > 0) {
$requiredParameters = array_slice($constructor->getParameters(), 0, $constructor->getNumberOfRequiredParameters());

fwrite(STDERR, 'Unable to load plugin file "'.$name.'", because it has required parameters: '.implode(', ', array_map(function ($item) {
return $item->getName();
}, $requiredParameters))."\n".
'Create a file "'.getcwd().'/plugins-enabled/'.$name.'.php" with the following contents to load the plugin:'."\n\n".
'<?php
require_once('.var_export($file, true).');

'.$constructor->getDocComment().'
return new '.$class.'(
'.implode(",\n\t", array_map(function ($item) {
return '$'.$item->getName()." = ".($item->isOptional() ? var_export($item->getDefaultValue(), true) : '???');
}, $constructor->getParameters())).'
);
');
exit(1);
}

echo '<?php
require_once('.var_export($file, true).');

return new '.$class.'();
';
exit(0);
Loading