设置 Apache Docker 容器在执行 php shell CMD 后继续运行

设置 Apache Docker 容器在执行 php shell CMD 后继续运行

我正在尝试运行基于以下内容的 Docker 容器:

  • PHP 8.1
  • Apache 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 初始化完成之前无连接”)。因此,当您在尚未提取映像的机器上启动当前应用程序的容器时mariadb,您很可能会尝试执行init.php,通过该操作尝试连接到您的db,而您的db容器实际上尚未完全初始化。这再次导致心爱的SQLSTATE[HY000] [2002] Connection refused错误。Docker 本身提及等待解决方案作为一种解决方法,这就是我使用它的原因。上面显示的代码中它所做的只是:

  • 检查最多 30 秒内该地址是否db:3306可用。
  • 如果它在该时间内可用,则执行之后的所有操作--
  • 如果它在该时间内没有可用,则中断执行(此时容器初始化将失败)。

为了采取更严格的方法,init.php如果连接失败,您还可以在内部编写代码,在等待 5 秒的间隔后重新尝试连接数据库最多 x 次;这样也可以完成工作。

现在一切都正常运转了!

相关内容