Richten Sie den Apache Docker-Container so ein, dass er nach der Ausführung der PHP-Shell-CMD weiter ausgeführt wird

Richten Sie den Apache Docker-Container so ein, dass er nach der Ausführung der PHP-Shell-CMD weiter ausgeführt wird

Ich versuche, einen Docker-Container auszuführen, basierend auf:

  • PHP 8.1
  • Apache 2.4
  • MariaDB (neuestes offizielles Docker-Image)

Docker-Datei:

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: "127.0.0.1"
      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:

Das Skript src/init.php stellt einfach eine Verbindung zur Datenbank her und generiert die Tabellen, die die Anwendung benötigt, sofern sie nicht bereits vorhanden sind.

Mein Problem ist nun, dass die Ausführung des Docker-Containers immer mit der erfolgreichen Ausführung von /src/init.php( php-apache exited with code 0) beendet wird. Ich weiß, dass das bei Docker normal ist, da der Container CMDlaut Dokumentation nur so lange besteht, wie der ausgeführt wird. Aber wie kann ich sicherstellen, dass der Container weiter ausgeführt wird und dass das init.phpSkript einfach gestartet wird, um sicherzustellen, dass die Anwendung beim Start des Containers über alles verfügt, was sie benötigt?

AKTUALISIEREN

init.shIch habe versucht, dies mit dem folgenden Inhalt einzurichten :

#!/bin/sh
php src/init.php
apache2 -D FOREGROUND

Dann habe ich ersetzt:

CMD [ "sh", "-c", "php src/init.php" ]

mit

CMD ["sh", "-c", "/var/www/html/start.sh"]

Dadurch wird das PHP-Skript erfolgreich ausgeführt, der Apache-Befehl schlägt jedoch fehl, und es wird folgende Meldung angezeigt:

[core:warn] [pid 10] AH00111: Config variable ${APACHE_RUN_DIR} is not defined

Es scheint also, dass auf die Variablen von Apache durch die Shell-Ausführung nicht zugegriffen werden kann??

Antwort1

Ok, ich habe jetzt eine funktionierende Lösung. Zunächst einmal der Grund dafür:

[core:warn] [pid 10] AH00111: Config variable ${APACHE_RUN_DIR} is not defined

lag daran, dass ich das falsche Befehlstool verwendet habe, um Apache im Vordergrund auszuführen. Die Verwendung apache2ctlvon anstelle von apache2hat funktioniert (in apache2schienen die Umgebungsvariablen von Apache nicht verfügbar zu sein).

Als nächstes sind die endgültigen Inhalte von mir start.sh:

#!/bin/sh
wait-for-it.sh db:3306 --strict --timeout=30 -- php init.php && apache2ctl -D FOREGROUND

Wie Sie sehen, habe ich noch eine weitere Funktion hinzugefügt. docker-composestartet Container gleichzeitig (sieheDas, Abschnitt „Keine Verbindungen, bis MariaDB-Init abgeschlossen ist“). Wenn Sie also den Container der vorliegenden Anwendung auf einer Maschine starten, auf der das mariadbImage noch nicht heruntergeladen wurde, ist es sehr wahrscheinlich, dass Sie versuchen, auszuführen init.php, wodurch Sie versuchen, eine Verbindung zu Ihrem herzustellen db, ohne dass Ihr dbContainer tatsächlich vollständig initialisiert ist. Dies führt erneut zu dem beliebten SQLSTATE[HY000] [2002] Connection refusedFehler. Docker selbstErwähnungenDiewarte daraufLösung als Workaround, weshalb ich sie verwendet habe. Im oben gezeigten Code macht sie nur Folgendes:

  • Prüfen Sie maximal 30 Sekunden lang, ob die Adresse db:3306verfügbar ist.
  • Wenn es innerhalb dieser Zeit verfügbar wird, führen Sie alles danach aus --.
  • wenn es innerhalb dieser Zeit nicht verfügbar ist, unterbrechen Sie die Ausführung (in diesem Fall würde die Initialisierung Ihres Containers fehlschlagen).

Für einen strengeren Ansatz könnten Sie in Ihrem Code auch festlegen, dass init.phpbei einem Verbindungsfehler nach einer Wartezeit von 5 Sekunden maximal x-mal erneut versucht wird, eine Verbindung zu Ihrer Datenbank herzustellen. Auch das würde funktionieren.

Jetzt funktioniert alles voll!

verwandte Informationen