設定 Apache Docker 容器在執行 php shell CMD 後繼續運行

設定 Apache Docker 容器在執行 php shell CMD 後繼續運行

我正在嘗試運行基於以下內容的 Docker 容器:

  • PHP 8.1
  • 阿帕契2.4
  • MariaDB(最新的官方 docker 映像)

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

腳本 src/init.php 只是連接到資料庫,並產生應用程式所需的表(如果尚不存在)。

我現在的問題是,Docker 容器的執行總是隨著/src/init.php( php-apache exited with code 0) 的成功執行而終止。我知道這對 Docker 來說是正常的,因為CMD根據文檔,容器只有在運行時才會持續存在。但我怎麼能確保容器繼續運作?並且init.php只需啟動腳本即可確保應用程式在容器啟動時擁有所需的一切?

更新

init.sh我嘗試使用以下內容來設定它:

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

然後我替換了:

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

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

這成功執行了 PHP 腳本,但無法執行 apache 命令,說:

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

所以看來apache的變數不能被shell執行存取?

答案1

好的,現在有了一個可行的解決方案。首先說一下原因:

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

是我使用了錯誤的命令工具在前台運行apache。使用apache2ctl而不是apache2完成了這項工作(在 中apache2,apache 的環境變數似乎不可用)。

接下來我的最終內容start.sh是:

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

現在我又添加了一項內容,如您所見。docker-compose同時啟動容器(參見,「MariaDB init 完成之前沒有連接」部分)。因此,當您在尚未提取映像的電腦上啟動當前應用程式的容器時mariadb,您很可能會嘗試執行init.php,透過它嘗試連接到您的db,而db容器實際上並未完全初始化。這又導致了人們喜愛的SQLSTATE[HY000] [2002] Connection refused錯誤。 Docker 本身提及等待解決方案作為解決方法,這就是我使用它的原因。上面顯示的程式碼中它所做的就是:

  • 最多 30 秒內檢查該位址是否db:3306可用。
  • 如果在該時間內可用,則執行 後的所有內容--
  • 如果它在這段時間內不可用,請中斷執行(此時容器初始化將失敗)。

對於更嚴格的方法,您還可以在您的程式碼中編寫程式碼,init.php如果連接失敗,則在等待 5 秒的間隔後重新嘗試連接到資料庫最多 x 次;這也能完成任務。

現在一切都正常運作了!

相關內容