
以下に基づいて Docker コンテナを実行しようとしています:
- PHP8.1 について
- アパッチ2.4
- MariaDB (最新の公式 Docker イメージ)
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:
スクリプト src/init.php は、DB に接続し、アプリケーションに必要なテーブルがまだ存在しない場合はそれを生成します。
/src/init.php
私の現在の問題は、Docker コンテナの実行が常に( )の実行の成功で終了することです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 の変数はシェル実行ではアクセスできないようです。
答え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
ご覧のとおり、もう1つ追加したものがあります。docker-compose
コンテナを同時に起動します(これ、セクション「MariaDBの初期化が完了するまで接続できません」)。このようにして、イメージがまだプルされていないマシンで現在のアプリケーションのコンテナを起動すると、コンテナが完全に初期化されていない状態で に接続しようとする をmariadb
実行しようとする可能性が非常に高くなります。これにより、再び愛されているエラーが発生します。Docker自体init.php
db
db
SQLSTATE[HY000] [2002] Connection refused
言及のそれを待つ回避策としてこのソリューションを使用しました。上記のコードで実行されるのは次のことだけです。
- アドレスが
db:3306
使用可能かどうかを最大 30 秒間確認します。 - その時間内に利用可能になった場合は、その後のすべてを実行します
--
。 - その時間内に利用できない場合は、実行を中断します (コンテナの初期化が失敗することになります)。
より厳密なアプローチとしては、init.php
接続が失敗した場合に 5 秒の間隔を空けてから最大 x 回 DB への接続を再試行するようにコードを記述することもできます。これも目的を果たします。
すべてが正常に動作しています。