Configure el contenedor Apache Docker para que siga ejecutándose después de ejecutar php Shell CMD

Configure el contenedor Apache Docker para que siga ejecutándose después de ejecutar php Shell CMD

Estoy intentando ejecutar un contenedor Docker basado en:

  • PHP 8.1
  • Apache 2.4
  • MariaDB (última imagen oficial de Docker)

Archivo Docker:

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:

El script src/init.php simplemente se conecta a la base de datos y genera las tablas que la aplicación necesita, si aún no están presentes.

Mi problema ahora es que la ejecución del contenedor Docker siempre termina con la ejecución exitosa de /src/init.php( php-apache exited with code 0). Sé que esto es normal con Docker, ya que el contenedor solo persiste mientras se CMDesté ejecutando, según los documentos. Pero, ¿cómo puedo asegurarme de que el contenedor siga funcionando? ¿Y que el init.phpscript simplemente se inicia para garantizar que la aplicación tenga todo lo que necesita al iniciar el contenedor?

ACTUALIZAR

Intenté utilizarlo para configurar esto init.shcon el siguiente contenido:

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

Luego reemplacé:

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

con

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

Esto ejecuta con éxito el script PHP, pero no puede ejecutar el comando de Apache, diciendo:

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

Entonces, ¿parece que la ejecución del Shell no puede acceder a las variables de Apache?

Respuesta1

Ok, ahora tengo una solución que funciona. En primer lugar, el motivo de:

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

fue que usé la herramienta de comando incorrecta para ejecutar Apache en primer plano. usar apache2ctlen lugar de apache2hacer el trabajo (en apache2, las variables de entorno de Apache parecían no estar disponibles).

A continuación, los contenidos finales de mi start.shson:

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

Ahora hay una cosa adicional que he agregado, como puedes ver. docker-composeinicia contenedores simultáneamente (vereste, sección "No hay conexiones hasta que se complete el inicio de MariaDB"). Cuando inicia el contenedor de la presente aplicación en una máquina en la que mariadbaún no se ha extraído la imagen, es muy probable que intente ejecutar init.php, mediante el cual intenta conectarse a su db, sin que su dbcontenedor esté completamente inicializado. Esto nuevamente resulta en el querido SQLSTATE[HY000] [2002] Connection refusederror. Docker en símencionaelespéralosolución como solución alternativa, por eso la he usado. Todo lo que hace en el código que se muestra arriba es:

  • compruebe durante un máximo de 30 segundos si la dirección db:3306está disponible.
  • si está disponible dentro de ese tiempo, ejecute todo después --.
  • si no está disponible dentro de ese tiempo, interrumpa la ejecución (que es cuando fallaría la inicialización de su contenedor).

Para un enfoque más estricto a esto, también puede codificar dentro de su init.phppara volver a intentar conectarse a su base de datos por un máximo de x veces después de esperar un intervalo de 5 segundos si la conexión falla; y eso también haría el trabajo.

¡Todo está funcionando completamente ahora!

información relacionada