I'm trying to run a Docker container based on:
- PHP 8.1
- Apache 2.4
- MariaDB (latest official docker image)
Dockerfile:
FROM php:8.1-apache
WORKDIR /var/www/html/
RUN pecl install xdebug \
&& apt update \
&& apt install libzip-dev -y \
&& docker-php-ext-enable xdebug \
&& a2enmod rewrite \
&& docker-php-ext-install zip \
&& rm -rf /var/lib/apt/lists/* \
&& docker-php-ext-install pdo pdo_mysql
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
COPY composer.json .
RUN groupadd -r user && useradd -r -g user user
USER user
RUN composer install --no-dev
COPY . .
EXPOSE 80
CMD [ "sh", "-c", "php src/init.php" ]
docker-compose.yml:
services:
php:
build: ./php
depends_on:
- db
- adminer
container_name: php-apache
ports:
- 80:80
volumes:
# setup xdebug to be able to use PHP step debugger, if needed
- ./php/conf.d/xdebug.ini:/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
- ./php/conf.d/error_reporting.ini:/usr/local/etc/php/conf.d/error_reporting.ini
# apache config (server name)
- ./apache/apache2.conf:/etc/apache2/apache2.conf
# apache config (rewrite rule to reroute all requests to unknown resources through to REST controller)
- ./apache/000-default.conf:/etc/apache2/sites-enabled/000-default.conf
# Source code
- ./php/src:/var/www/html/src
# unbind local composer components
- /php/vendor
- /php/composer.lock
- /php/composer.phar
environment:
MARIADB_HOST: db
MARIADB_USER: root
MARIADB_PASSWORD: top_very_secret
MARIADB_DB: apidb
adminer:
image: adminer
depends_on:
- db
restart: always
ports:
- 8080:8080
db:
image: mariadb
container_name: db
volumes:
- maria-db-storage:/var/lib/mysql
environment:
MARIADB_ROOT_PASSWORD: top_very_secret
MARIADB_DATABASE: apidb
ports:
- 3306:3306
volumes:
maria-db-storage:
src/init.php connects with the DB and creates tables the application needs, if they do not already exist. To connect, I use the environment variables like so:
new PDO(
"mysql:host={$_ENV['MARIADB_HOST']};dbname={$_ENV['MARIADB_DB']}",
$_ENV['MARIADB_USER'],
$_ENV['MARIADB_PASSWORD'],
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
]
);
And for the first time I docker-compose up
, I always get:
SQLSTATE[HY000] [2002] Connection refused
.
At the top of the src/init.php
script, I can successfully echo out all of the environment variables used in Docker. So they are all defined.
I'm really confused with this, as docker-compose up
and the DB connection only work after failing on the first time docker-compose up
fails (with the above-mentioned error). When then calling docker-compose down
, then do docker-compose up
again in the subsequent times, things all work flawlessly. Any idea why this happens?
I've been digging a little further, and I noticed that, wehn the mariadb image is built (e.g. when you first run docker-compose up
with the above mentioned file contents), I get the above-mentioned error plus the output:
PLEASE REMEMBER TO SET A PASSWORD FOR THE MariaDB root USER
So it seems that, at the moment of the image being built; the MARIADB_ROOT_PASSWORD
is for some reason not applied, but aftewards it is, and that that's the reason for the failed connection?
Currently, I suppose that this is due to this ?:
If there is no database initialized when the container starts, then a default database will be created. While this is the expected behavior, this means that it will not accept incoming connections until such initialization completes. This may cause issues when using automation tools, such as docker-compose, which start several containers simultaneously.
CMD
directive. You can add some commands to yourinit.php
to log the variables prior to establishing the database connection. In any case, this seems to be a Docker problem and not something related to MySQL.