Making lighter Docker images on Laravel Sail project

I’ve been trying to make some modifications to the default ‘docker-compose.yml’ and Dockerfiles autogenerated by Laravel Sail after it’s installed into my Laravel project. I’ve been attempting this because those images are, by default, based on either Ubuntu or Debian, so I tried to rebuild them based on an Alpine Linux image to improve their performance and gain more experience with Docker.

After a lot of work, I managed to reduce the main image of the project from over 900 MB to almost 300 MB, which is about three times smaller. I also easily replaced the default ‘mariadb’ image set by Laravel Sail, which is based on Debian, with a ‘mariadb’ image based on Alpine, also with similar results.

However, I’m finding it difficult to achieve the same with my ‘phpMyAdmin’ image, as I haven’t been able to find an existing Alpine-based image that works the same as the Debian-based one.
So then, I’ve been trying to create it by myself, by writing my own Dockerfile from the Alpine base Docker image.

Here’s my ‘docker-compose.yml’ (at root project path):

version: "1.0"
services:
    laravel.test:
        build:
            context: ./
            dockerfile: ./docker/8.3/Dockerfile
            args:
                WWWGROUP: '${WWWGROUP}'
        image: sail-8.3/app
        #command: sh -c "npm install && npm run build"
        extra_hosts:
            - 'host.docker.internal:host-gateway'
        ports:
            - '${APP_PORT:-80}:80'
            - '${VITE_PORT:-5173}:${VITE_PORT:-5173}'
        environment:
            WWWUSER: '${WWWUSER}'
            LARAVEL_SAIL: 1
            XDEBUG_MODE: '${SAIL_XDEBUG_MODE:-off}'
            XDEBUG_CONFIG: '${SAIL_XDEBUG_CONFIG:-client_host=host.docker.internal}'
            IGNITION_LOCAL_SITES_PATH: '${PWD}'
        volumes:
            - '.:/var/www/html'
            #- './docker/init.sh:/init.sh'
            #- './docker/8.3/start-container:start-container'
#            - './docker/8.3/install-deps.sh:/usr/local/bin/install-deps.sh'

        networks:
            - sail
        depends_on:
            - mariadb
            - phpmyadmin
    mariadb:
        #image: 'mariadb:10'
        image: yobasystems/alpine-mariadb:10
        ports:
            - '${FORWARD_DB_PORT:-3306}:3306'
        environment:
            MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}'
            MYSQL_ROOT_HOST: '%'
            MYSQL_DATABASE: '${DB_DATABASE}'
            MYSQL_USER: '${DB_USERNAME}'
            MYSQL_PASSWORD: '${DB_PASSWORD}'
            MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
        volumes:
            - 'sail-mariadb:/var/lib/mysql'
            - './docker/mysql/create-testing-database.sh:/docker-entrypoint-initdb.d/10-create-testing-database.sh'
        networks:
            - sail
        healthcheck:
            test:
                - CMD
                - mysqladmin
                - ping
                - '-p${DB_PASSWORD}'
            retries: 3
            timeout: 5s

    phpmyadmin:
      image: 'phpmyadmin:latest'
      #image: jackgruber/phpmyadmin
      #image: 'phpmyadmin:fpm-alpine'

      ports:
          - 8081:80
      networks:
          - sail
      environment:
          - PMA_ARBITRARY=1
networks:
    sail:
        driver: bridge
volumes:
    sail-mariadb:
        driver: local

Then, in my ‘/docker/8.3’ path I have:

‘Dockerfile’:

FROM alpine:latest AS fswatch

RUN apk add --no-cache autoconf alpine-sdk

RUN rm /usr/include/sys/inotify.h
RUN wget https://github.com/emcrisostomo/fswatch/releases/download/1.17.1/fswatch-1.17.1.tar.gz \
    && tar -xzvf fswatch-1.17.1.tar.gz \
    && cd fswatch-1.17.1 \
    && ./configure \
    && make \
    && make install \
    && rm -rf /fswatch-1.17.1


FROM alpine:latest
COPY --from=fswatch /usr/local/bin/fswatch /usr/local/bin/fswatch
COPY --from=fswatch /usr/local/lib/libfswatch.so* /usr/local/lib/

LABEL maintainer="Taylor Otwell"

ARG WWWGROUP
ARG NODE_VERSION=20

WORKDIR /var/www/html

ENV TZ=UTC
ENV SUPERVISOR_PHP_COMMAND="/usr/bin/php -d variables_order=EGPCS /var/www/html/artisan serve --host=0.0.0.0 --port=80"
ENV SUPERVISOR_PHP_USER="sail"

# Instalar dependencias
RUN apk update && \
    apk add --no-cache \
        gnupg \
        curl \
        ca-certificates \
        zip \
        unzip \
        git \
        supervisor \
        libpng-dev \
        libjpeg \
        librsvg \
        nano \
        php83 \
        php83-cli \
        php83-dev \
        php83-pdo_pgsql \
        php83-gd \
        php83-curl \
        php83-xml \
        php83-mbstring \
        php83-openssl \
        php83-json \
        php83-dom \
        php83-ctype \
        php83-tokenizer \
        php83-session \
        php83-fileinfo \
        php83-xmlwriter \
        php83-simplexml \
        php83-tokenizer \
        php83-pdo_mysql \
        nodejs \
        npm \
        mysql-client \
    && rm -rf /var/cache/apk/*

RUN apk add --no-cache php83-phar
RUN set -eux; \
    apk add --no-cache --virtual .gosu-deps \
        dpkg \
        gnupg \
        openssl \
    && dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \
    curl -fsSL "https://github.com/tianon/gosu/releases/download/1.14/gosu-$dpkgArch.asc" -o /usr/local/bin/gosu.asc \
    && curl -fsSL "https://github.com/tianon/gosu/releases/download/1.14/gosu-$dpkgArch" -o /usr/local/bin/gosu \
    && chmod +x /usr/local/bin/gosu \
    && gosu --version \
    && rm /usr/local/bin/gosu.asc \
    && apk del .gosu-deps

# ToDo: Configurar zona horaria
#RUN cp /usr/share/zoneinfo/$TZ /etc/localtime && \
#   echo $TZ > /etc/timezone

RUN apk add --no-cache libcap
# Configurar capacidades para PHP
RUN cp /usr/bin/php83 /usr/bin/php
RUN setcap "cap_net_bind_service=+ep" /usr/bin/php
RUN curl -sLS https://getcomposer.org/installer | php -- --install-dir=/usr/bin/ --filename=composer

# Definir el identificador del grupo y del usuario
ARG WWWGROUP=1000
ARG USER_ID=1337

# Crear el grupo y el usuario con los identificadores especificados
RUN addgroup -g $WWWGROUP sail && \
    adduser -D -s /bin/sh -G sail -u $USER_ID sail


RUN apk add --no-cache \
      shadow \
      supervisor

# Crear directorios necesarios
RUN mkdir -p /var/log/supervisor

# Copiar scripts y configuraciones
COPY ./docker/8.3/start-container /usr/local/bin/start-container
COPY ./docker/8.3/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
COPY ./docker/8.3/php.ini /etc/php83/cli/conf.d/99-sail.ini

# Establecer permisos
RUN chmod +x /usr/local/bin/start-container

# Exponer puerto
EXPOSE 8000

# Punto de entrada
ENTRYPOINT ["start-container"]

‘install-deps.sh’:

#!/usr/bin/env sh
npm install

‘php.ini’:

[PHP]
post_max_size = 100M
upload_max_filesize = 100M
variables_order = EGPCS
pcov.directory = .

‘start-container’:

#!/usr/bin/env sh

if [ "$SUPERVISOR_PHP_USER" != "root" ] && [ "$SUPERVISOR_PHP_USER" != "sail" ]; then
    echo "You should set SUPERVISOR_PHP_USER to either 'sail' or 'root'."
    exit 1
fi

if [ ! -z "$WWWUSER" ]; then
    usermod -u $WWWUSER sail
fi


#if [ ! -d /var/www/html/node_modules ]; then
#    cd /var/www/html
#    npm install
#    chmod 777 ./node_modules -R
#    npm run build
#fi

if [ ! -d /.composer ]; then
    mkdir /.composer
fi

chmod -R ugo+rw /.composer

if [ $# -gt 0 ]; then
    if [ "$SUPERVISOR_PHP_USER" = "root" ]; then
        exec "$@"
    else
        exec gosu $WWWUSER "$@"
    fi
else
    exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf
fi

‘supervisord.conf’:

[supervisord]
nodaemon=true
user=root
logfile=/var/log/supervisor/supervisord.log
pidfile=/var/run/supervisord.pid

[program:php]
command=%(ENV_SUPERVISOR_PHP_COMMAND)s
user=%(ENV_SUPERVISOR_PHP_USER)s
environment=LARAVEL_SAIL="1"
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0

The app works fine, and also the phpMyadmin service, showing a login page like this:

enter image description here

However, when trying to build my own ‘phpmyadmin’ image, based on Alpine, I can’t achieve that the login page show the ‘Server’ field, like the one I have working in my app.

Here’s my ‘Dockerfile’ (located in a separate folder):

FROM alpine

ENV SUPERVISOR_PHP_USER="sail"

RUN apk update
RUN apk add apache2
RUN echo "ServerName localhost" >> /etc/apache2/httpd.conf
RUN apk add openrc
RUN rc-update add apache2 && openrc default

RUN apk add --no-cache \
        gnupg \
        curl \
        ca-certificates \
        zip \
        unzip \
        git \
        supervisor \
        libpng-dev \
        libjpeg \
        librsvg \
        nano \
        php83 \
        php83-cli \
        php83-dev \
        php83-pdo_pgsql \
        php83-gd \
        php83-curl \
        php83-xml \
        php83-mbstring \
        php83-openssl \
        php83-json \
        php83-dom \
        php83-ctype \
        php83-tokenizer \
        php83-session \
        php83-fileinfo \
        php83-xmlwriter \
        php83-simplexml \
        php83-tokenizer \
        php83-pdo_mysql \
        php83-mysqli \
        php83-phar \
        mysql-client \
    && rm -rf /var/cache/apk/*

RUN set -eux; \
    apk add --no-cache --virtual \
    dpkg \
    gnupg \
    openssl

RUN apk add --no-cache libcap

RUN cp /usr/bin/php83 /usr/bin/php
RUN setcap "cap_net_bind_service=+ep" /usr/bin/php

# Definir el identificador del grupo y del usuario
ARG WWWGROUP=1000
ARG USER_ID=1337

# Crear el grupo y el usuario con los identificadores especificados
RUN addgroup -g $WWWGROUP sail && \
    adduser -D -s /bin/sh -G sail -u $USER_ID sail

RUN apk add php83-apache2
RUN rc-update add apache2 default
RUN apk add phpmyadmin
RUN chown -R apache:apache /etc/phpmyadmin
WORKDIR /var/www/localhost/htdocs

RUN rm index.html
RUN cp -r /usr/share/webapps/phpmyadmin/* .
RUN echo -e "<?php\nphpinfo();\n?>" >> ./info.php
#RUN rc-service apache2 start
#CMD ["rc-service", "apache2", "start"]
CMD ["httpd", "-D", "FOREGROUND"]

This are the commands I’ve been trying to use to setup the eviroment variables, needed to display the wanter ‘Server’ field on login page:

leandro@leandro-Lenovo-B50-10:~/sail/apache_alpine$ docker build -t my-apache2 .
[+] Building 134.7s (25/25) FINISHED                                                                                                                                              docker:default
 => [internal] load build definition from Dockerfile                                                                                                                                        1.0s
 => => transferring dockerfile: 1.82kB                                                                                                                                                      0.0s
 => [internal] load metadata for docker.io/library/alpine:latest                                                                                                                            4.3s
 => [auth] library/alpine:pull token for registry-1.docker.io                                                                                                                               0.0s
 => [internal] load .dockerignore                                                                                                                                                           0.4s
 => => transferring context: 2B                                                                                                                                                             0.0s
 => CACHED [ 1/20] FROM docker.io/library/alpine:latest@sha256:c5b1261d6d3e43071626931fc004f70149baeba2c8ec672bd4f27761f8e1ad6b                                                             0.3s
 => => resolve docker.io/library/alpine:latest@sha256:c5b1261d6d3e43071626931fc004f70149baeba2c8ec672bd4f27761f8e1ad6b                                                                      0.3s
 => [ 2/20] RUN apk update                                                                                                                                                                  5.0s
 => [ 3/20] RUN apk add apache2                                                                                                                                                             4.7s 
 => [ 4/20] RUN echo "ServerName localhost" >> /etc/apache2/httpd.conf                                                                                                                      2.2s 
 => [ 5/20] RUN apk add openrc                                                                                                                                                              4.3s 
 => [ 6/20] RUN rc-update add apache2 && openrc default                                                                                                                                     2.9s 
 => [ 7/20] RUN apk add --no-cache         gnupg         curl         ca-certificates         zip         unzip         git         supervisor         libpng-dev         libjpeg          43.1s 
 => [ 8/20] RUN set -eux;     apk add --no-cache --virtual     dpkg     gnupg     openssl                                                                                                   5.4s 
 => [ 9/20] RUN apk add --no-cache libcap                                                                                                                                                   4.8s 
 => [10/20] RUN cp /usr/bin/php83 /usr/bin/php                                                                                                                                              2.3s 
 => [11/20] RUN setcap "cap_net_bind_service=+ep" /usr/bin/php                                                                                                                              2.4s 
 => [12/20] RUN addgroup -g 1000 sail &&     adduser -D -s /bin/sh -G sail -u 1337 sail                                                                                                     2.4s 
 => [13/20] RUN apk add php83-apache2                                                                                                                                                       6.5s 
 => [14/20] RUN rc-update add apache2 default                                                                                                                                               2.0s 
 => [15/20] RUN apk add phpmyadmin                                                                                                                                                         12.2s 
 => [16/20] RUN chown -R apache:apache /etc/phpmyadmin                                                                                                                                      2.2s 
 => [17/20] WORKDIR /var/www/localhost/htdocs                                                                                                                                               1.2s 
 => [18/20] RUN rm index.html                                                                                                                                                               2.1s 
 => [19/20] RUN cp -r /usr/share/webapps/phpmyadmin/* .                                                                                                                                     6.4s 
 => [20/20] RUN echo -e "<?php\nphpinfo();\n?>" >> ./info.php                                                                                                                               2.1s 
 => exporting to image                                                                                                                                                                     11.9s 
 => => exporting layers                                                                                                                                                                    11.5s
 => => writing image sha256:87594483041eab34efe44f18fd96e02c2e21906867ce4d66b0ca935659ee7968                                                                                                0.1s
 => => naming to docker.io/library/my-apache2                                                                                                                                               0.1s

View build details: docker-desktop://dashboard/build/default/default/p3o1665s7ilubtk1b96nm6aqr

Reduce build time with Docker Build Cloud: https://docs.docker.com/go/docker-build-cloud

And then:

leandro@leandro-Lenovo-B50-10:~/sail/apache_alpine$ docker run --env 'PMA_ARBITRARY=1' -dit --name my-running-app -p 8080:80 my-apache2
e7d3490bfed251662065e64e14ef4bf9d469d6737cb1debb960a81e83c846f65

So, I’m having a result like this:
enter image description here

enter image description here

Any suggestions? If there’s more info needed, please tell me.

Thank’s a lot!

Leandro

You mean optimize the size, right? I don’t think you will improve performance just by switching to Alpine. If anything, you can introduce some limitations as not everything is supported on Alpine. Quote from the official PHP image description

This variant is useful when final image size being as small as possible is your primary concern. The main caveat to note is that it does use musl libc instead of glibc and friends, so software will often run into issues depending on the depth of their libc requirements/assumptions. See this Hacker News comment thread for more discussion of the issues that might arise and some pro/con comparisons of using Alpine-based images.

That is a PHPMyAdmin installation and configuration issue so in situations like this, you need to check the official documentation of the software:

https://docs.phpmyadmin.net/en/latest/config.html

You probably need to allow “arbitrary servers” https://docs.phpmyadmin.net/en/latest/config.html#cfg_AllowArbitraryServer.

1 Like

@rimelek
That’s right, I’m just trying to optimize the size.
I really didn’t took into consideration the limitations that an Alpine-based image may bring, so then I’ll intensively test my app with that image. If there’s something that doesn’t work anymore after switching to Alpine, I’ll guess I should go back to the previous Debian/Ubuntu based images I had before. I should read more carefully that official PHP image description.

I’ve actually read this Docker environment variables section at the docs, where is indicated that setting the PMA_ARBITRARY env variable with value 1 when running a Docker container, would set the

$cfg[‘AllowArbitraryServer’]

parameter as true, so then I should obtain the expected result.
However, I should watch more carefully all the config files obtained in my Alpine-based image I’m creating, and so comparing them to the previous Debian-based image, which actually works as expected.
So then, I’ll keep on trying to achieve that, by analyzing more in depth all the files and settings involved for that purpose.

Really thank you!
Leandro

I’ve found a solution!
Exploring by the shell the contents of the container built over the default ‘phpmyadmin:latest’ image, I’ve found that the config files of the phpMyAdmin installation over the Debian base image, provided by that package, were quite different from a standard phpMyAdmin installation, since it was meant to handle environment variables provided by Docker from the user, and also meant to run from the root URL of the container, instead of ‘/phpmyadmin’ sub-path.

So on, I’ve just copied the content of those config files on the same folder of my Dockerfile (with just a little modification), and then build the image with those files, replacing the ones which the standard installation of phpMyAdmin generated.

So, here are the contents of my files:

‘(root)/docker-compose.yml’:

version: "1.0"
services:
    laravel.test:
        build:
            context: ./
            dockerfile: ./docker/8.3/Dockerfile
            args:
                WWWGROUP: '${WWWGROUP}'
        image: sail-8.3/app
        #command: sh -c "npm install && npm run build"
        extra_hosts:
            - 'host.docker.internal:host-gateway'
        ports:
            - '${APP_PORT:-80}:80'
            - '${VITE_PORT:-5173}:${VITE_PORT:-5173}'
        environment:
            WWWUSER: '${WWWUSER}'
            LARAVEL_SAIL: 1
            XDEBUG_MODE: '${SAIL_XDEBUG_MODE:-off}'
            XDEBUG_CONFIG: '${SAIL_XDEBUG_CONFIG:-client_host=host.docker.internal}'
            IGNITION_LOCAL_SITES_PATH: '${PWD}'
        volumes:
            - '.:/var/www/html'
            #- './docker/init.sh:/init.sh'
            #- './docker/8.3/start-container:start-container'
#            - './docker/8.3/install-deps.sh:/usr/local/bin/install-deps.sh'

        networks:
            - sail
        depends_on:
            - mariadb
            - phpmyadmin
    mariadb:
        #image: 'mariadb:10'
        image: yobasystems/alpine-mariadb:10
        ports:
            - '${FORWARD_DB_PORT:-3306}:3306'
        environment:
            MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}'
            MYSQL_ROOT_HOST: '%'
            MYSQL_DATABASE: '${DB_DATABASE}'
            MYSQL_USER: '${DB_USERNAME}'
            MYSQL_PASSWORD: '${DB_PASSWORD}'
            MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
        volumes:
            - 'sail-mariadb:/var/lib/mysql'
            - './docker/mysql/create-testing-database.sh:/docker-entrypoint-initdb.d/10-create-testing-database.sh'
        networks:
            - sail
        healthcheck:
            test:
                - CMD
                - mysqladmin
                - ping
                - '-p${DB_PASSWORD}'
            retries: 3
            timeout: 5s

    phpmyadmin:
      build:
        context: ./
        dockerfile: ./docker/phpmyadmin/Dockerfile
        args:
            WWWGROUP: '${WWWGROUP}'
      image: sail-myadmin/app
      #image: 'phpmyadmin:latest'
      #image: jackgruber/phpmyadmin
      #image: 'phpmyadmin:fpm-alpine'

      ports:
          - 8081:80
      networks:
          - sail
      environment:
          - PMA_ARBITRARY=1
networks:
    sail:
        driver: bridge
volumes:
    sail-mariadb:
        driver: local

‘(root)/docker/phpmyadmin/Dockerfile’:

FROM alpine

ENV SUPERVISOR_PHP_USER="sail"

RUN apk update
RUN apk add apache2
RUN echo "ServerName localhost" >> /etc/apache2/httpd.conf
RUN apk add openrc
RUN rc-update add apache2 && openrc default

RUN apk add --no-cache \
        gnupg \
        curl \
        ca-certificates \
        zip \
        unzip \
        git \
        supervisor \
        libpng-dev \
        libjpeg \
        librsvg \
        nano \
        php83 \
        php83-cli \
        php83-dev \
        php83-pdo_pgsql \
        php83-gd \
        php83-curl \
        php83-xml \
        php83-mbstring \
        php83-openssl \
        php83-json \
        php83-dom \
        php83-ctype \
        php83-tokenizer \
        php83-session \
        php83-fileinfo \
        php83-xmlwriter \
        php83-simplexml \
        php83-tokenizer \
        php83-pdo_mysql \
        php83-mysqli \
        php83-phar \
        mysql-client \
    && rm -rf /var/cache/apk/*

RUN set -eux; \
    apk add --no-cache --virtual \
    dpkg \
    gnupg \
    openssl

RUN apk add --no-cache libcap

RUN cp /usr/bin/php83 /usr/bin/php
RUN setcap "cap_net_bind_service=+ep" /usr/bin/php

# Definir el identificador del grupo y del usuario
ARG WWWGROUP=1000
ARG USER_ID=1337

# Crear el grupo y el usuario con los identificadores especificados
RUN addgroup -g $WWWGROUP sail && \
    adduser -D -s /bin/sh -G sail -u $USER_ID sail

RUN apk add php83-apache2
RUN rc-update add apache2 default
RUN apk add phpmyadmin
RUN chown -R apache:apache /etc/phpmyadmin
WORKDIR /var/www/localhost/htdocs

RUN rm index.html
RUN cp -r /usr/share/webapps/phpmyadmin/* .
RUN rm config.inc.php

COPY ./docker/phpmyadmin/config.inc.php ./config.inc.php
COPY ./docker/phpmyadmin/config.secret.inc.php ./config.secret.inc.php
COPY ./docker/phpmyadmin/config.user.inc.php ./config.user.inc.php
RUN echo -e "<?php\nphpinfo();\n?>" >> ./info.php
#RUN rc-service apache2 start
#CMD ["rc-service", "apache2", "start"]
CMD ["httpd", "-D", "FOREGROUND"]

‘(root)/docker/phpmyadmin/config.inc.php’:

<?php

require './config.secret.inc.php';

/* Ensure we got the environment */
$vars = [
    'PMA_ARBITRARY',
    'PMA_HOST',
    'PMA_HOSTS',
    'PMA_VERBOSE',
    'PMA_VERBOSES',
    'PMA_PORT',
    'PMA_PORTS',
    'PMA_SOCKET',
    'PMA_SOCKETS',
    'PMA_USER',
    'PMA_PASSWORD',
    'PMA_ABSOLUTE_URI',
    'PMA_CONTROLHOST',
    'PMA_CONTROLPORT',
    'PMA_PMADB',
    'PMA_CONTROLUSER',
    'PMA_CONTROLPASS',
    'PMA_QUERYHISTORYDB',
    'PMA_QUERYHISTORYMAX',
    'MAX_EXECUTION_TIME',
    'MEMORY_LIMIT',
    'PMA_UPLOADDIR',
    'PMA_SAVEDIR',
];

foreach ($vars as $var) {
    $env = getenv($var);
    if (!isset($_ENV[$var]) && $env !== false) {
        $_ENV[$var] = $env;
    }
}
if (isset($_ENV['PMA_QUERYHISTORYDB'])) {
    $cfg['QueryHistoryDB'] = (bool) $_ENV['PMA_QUERYHISTORYDB'];
}

if (isset($_ENV['PMA_QUERYHISTORYMAX'])) {
    $cfg['QueryHistoryMax'] = (int) $_ENV['PMA_QUERYHISTORYMAX'];
}

/* Arbitrary server connection */
if (isset($_ENV['PMA_ARBITRARY']) && $_ENV['PMA_ARBITRARY'] === '1') {
    $cfg['AllowArbitraryServer'] = true;
}

/* Play nice behind reverse proxys */
if (isset($_ENV['PMA_ABSOLUTE_URI'])) {
    $cfg['PmaAbsoluteUri'] = trim($_ENV['PMA_ABSOLUTE_URI']);
}

/* Figure out hosts */

/* Fallback to default linked */
$hosts = ['db'];

/* Set by environment */
if (! empty($_ENV['PMA_HOST'])) {
    $hosts = [$_ENV['PMA_HOST']];
    $verbose = [$_ENV['PMA_VERBOSE']];
    $ports = [$_ENV['PMA_PORT']];
} elseif (! empty($_ENV['PMA_HOSTS'])) {
    $hosts = array_map('trim', explode(',', $_ENV['PMA_HOSTS']));
    $verbose = array_map('trim', explode(',', $_ENV['PMA_VERBOSES']));
    $ports = array_map('trim', explode(',', $_ENV['PMA_PORTS']));
}

if (! empty($_ENV['PMA_SOCKET'])) {
    $sockets = [$_ENV['PMA_SOCKET']];
} elseif (! empty($_ENV['PMA_SOCKETS'])) {
    $sockets = explode(',', $_ENV['PMA_SOCKETS']);
}

/* Server settings */
for ($i = 1; isset($hosts[$i - 1]); $i++) {
    $cfg['Servers'][$i]['host'] = $hosts[$i - 1];
    if (isset($verbose[$i - 1])) {
        $cfg['Servers'][$i]['verbose'] = $verbose[$i - 1];
    }
    if (isset($ports[$i - 1])) {
        $cfg['Servers'][$i]['port'] = $ports[$i - 1];
    }
    if (isset($_ENV['PMA_USER'])) {
        $cfg['Servers'][$i]['auth_type'] = 'config';
        $cfg['Servers'][$i]['user'] = $_ENV['PMA_USER'];
        $cfg['Servers'][$i]['password'] = isset($_ENV['PMA_PASSWORD']) ? $_ENV['PMA_PASSWORD'] : '';
    } else {
        $cfg['Servers'][$i]['auth_type'] = 'cookie';
    }
    if (isset($_ENV['PMA_PMADB'])) {
      $cfg['Servers'][$i]['pmadb'] = $_ENV['PMA_PMADB'];
      $cfg['Servers'][$i]['relation'] = 'pma__relation';
      $cfg['Servers'][$i]['table_info'] = 'pma__table_info';
      $cfg['Servers'][$i]['table_coords'] = 'pma__table_coords';
      $cfg['Servers'][$i]['pdf_pages'] = 'pma__pdf_pages';
      $cfg['Servers'][$i]['column_info'] = 'pma__column_info';
      $cfg['Servers'][$i]['bookmarktable'] = 'pma__bookmark';
      $cfg['Servers'][$i]['history'] = 'pma__history';
      $cfg['Servers'][$i]['recent'] = 'pma__recent';
      $cfg['Servers'][$i]['favorite'] = 'pma__favorite';
      $cfg['Servers'][$i]['table_uiprefs'] = 'pma__table_uiprefs';
      $cfg['Servers'][$i]['tracking'] = 'pma__tracking';
      $cfg['Servers'][$i]['userconfig'] = 'pma__userconfig';
      $cfg['Servers'][$i]['users'] = 'pma__users';
      $cfg['Servers'][$i]['usergroups'] = 'pma__usergroups';
      $cfg['Servers'][$i]['navigationhiding'] = 'pma__navigationhiding';
      $cfg['Servers'][$i]['savedsearches'] = 'pma__savedsearches';
      $cfg['Servers'][$i]['central_columns'] = 'pma__central_columns';
      $cfg['Servers'][$i]['designer_settings'] = 'pma__designer_settings';
      $cfg['Servers'][$i]['export_templates'] = 'pma__export_templates';
    }
    if (isset($_ENV['PMA_CONTROLHOST'])) {
      $cfg['Servers'][$i]['controlhost'] = $_ENV['PMA_CONTROLHOST'];
    }
    if (isset($_ENV['PMA_CONTROLPORT'])) {
      $cfg['Servers'][$i]['controlport'] = $_ENV['PMA_CONTROLPORT'];
    }
    if (isset($_ENV['PMA_CONTROLUSER'])) {
      $cfg['Servers'][$i]['controluser'] = $_ENV['PMA_CONTROLUSER'];
    }
    if (isset($_ENV['PMA_CONTROLPASS'])) {
      $cfg['Servers'][$i]['controlpass'] = $_ENV['PMA_CONTROLPASS'];
    }
    $cfg['Servers'][$i]['compress'] = false;
    $cfg['Servers'][$i]['AllowNoPassword'] = true;
}
for ($i = 1; isset($sockets[$i - 1]); $i++) {
    $cfg['Servers'][$i]['socket'] = $sockets[$i - 1];
    $cfg['Servers'][$i]['host'] = 'localhost';
}
/*
 * Revert back to last configured server to make
 * it easier in config.user.inc.php
 */
$i--;

/* Uploads setup */
if (isset($_ENV['PMA_UPLOADDIR'])) {
    $cfg['UploadDir'] = $_ENV['PMA_UPLOADDIR'];
}

if (isset($_ENV['PMA_SAVEDIR'])) {
    $cfg['SaveDir'] = $_ENV['PMA_SAVEDIR'];
}

if (isset($_ENV['MAX_EXECUTION_TIME'])) {
    $cfg['ExecTimeLimit'] = $_ENV['MAX_EXECUTION_TIME'];
}

if (isset($_ENV['MEMORY_LIMIT'])) {
    $cfg['MemoryLimit'] = $_ENV['MEMORY_LIMIT'];
}

/* Include User Defined Settings Hook */
if (file_exists('/etc/phpmyadmin/config.user.inc.php')) {
    include '/etc/phpmyadmin/config.user.inc.php';
}

/* Support additional configurations */
if (is_dir('/etc/phpmyadmin/conf.d/')) {
    foreach (glob('/etc/phpmyadmin/conf.d/*.php') as $filename) {
        include $filename;
    }
}

‘(root)/docker/phpmyadmin/config.secret.inc.php’:

<?php
$cfg['blowfish_secret'] = '5Cr~1@RsNaF3t!c,7NwVJ(c6"i*/#0M#';

‘(root)/docker/phpmyadmin/config.user.inc.php’:

//Empty

Despite it might still there might be lots of things to improve, this actually is working fine!

Later I will maybe uploading some images, showing this working.

Best regards!

Leandro

I’ve now made an improved Dockerfile:

FROM alpine as myadmin
RUN apk update && \
    apk add --no-cache phpmyadmin

# Fase 2: Configuración de Apache y PHP
FROM alpine

ENV SUPERVISOR_PHP_USER="sail"

# Actualización de paquetes y configuración inicial de Apache y PHP
RUN apk update && \
    apk add --no-cache \
        apache2 \
        gnupg \
        curl \
        ca-certificates \
        zip \
        unzip \
        git \
        supervisor \
        libpng-dev \
        libjpeg \
        librsvg \
        php83 \
        php83-zip \
        php83-cli \
        php83-dev \
        php83-pdo_pgsql \
        php83-gd \
        php83-curl \
        php83-xml \
        php83-mbstring \
        php83-openssl \
        php83-json \
        php83-dom \
        php83-ctype \
        php83-tokenizer \
        php83-session \
        php83-fileinfo \
        php83-xmlwriter \
        php83-simplexml \
        php83-pdo_mysql \
        php83-mysqli \
        php83-phar \
        mysql-client \
        php83-apache2 \
        libcap && \
    echo "ServerName localhost" >> /etc/apache2/httpd.conf && \
    cp /usr/bin/php83 /usr/bin/php && \
    setcap "cap_net_bind_service=+ep" /usr/bin/php && \
    rm -rf /var/cache/apk/*

# Copiar phpMyAdmin desde la fase de construcción
COPY --from=myadmin /usr/share/webapps/phpmyadmin/ /var/www/localhost/htdocs/
COPY --from=myadmin /etc/phpmyadmin /etc/phpmyadmin
COPY --from=myadmin /usr/share/phpmyadmin /usr/share/phpmyadmin

WORKDIR /var/www/localhost/htdocs

# Ajustes de permisos y configuración de Apache
RUN chown -R apache:apache /etc/phpmyadmin && \
    chmod -R 777 /var/www/localhost/htdocs && \
    echo -e "<?php\nphpinfo();\n?>" > /var/www/localhost/htdocs/info.php && \
    rm -rf /var/cache/apk/*

# Definir el identificador del grupo y del usuario
ARG WWWGROUP=1000
ARG USER_ID=1337

# Crear el grupo y el usuario con los identificadores especificados
RUN addgroup -g $WWWGROUP sail && \
    adduser -D -s /bin/sh -G sail -u $USER_ID sail

# Eliminar archivos innecesarios
RUN rm -f index.html config.inc.php

# Copiar archivos de configuración personalizados
COPY ./docker/phpmyadmin/config.inc.php /var/www/localhost/htdocs/config.inc.php
COPY ./docker/phpmyadmin/config.secret.inc.php /var/www/localhost/htdocs/config.secret.inc.php
COPY ./docker/phpmyadmin/config.user.inc.php /var/www/localhost/htdocs/config.user.inc.php
RUN echo -e "<?php\nphpinfo();\n?>" >> /var/www/localhost/htdocs/info.php

# Comando para iniciar Apache
CMD ["httpd", "-D", "FOREGROUND"]

If somebody find it useful, I may upload the image to Docker Hub