New Relic PHP Agent を Docker で動かす(Laravel)

PHP で作られたアプリケーションを New Relic APM で計測したい場合は [New Relic PHP Agent](https://docs.newrelic.com/docs/apm/agents/php-agent/getting-started/introduction-new-relic-php/) を利用しますが今回は Docker 環境を利用してインストール方法を紹介します。

今回環境作成に実行したリポジトリは以下になります。
https://github.com/yuzujoe/laravel-newrelic-php-agent

## 筆者環境

Apple M1 Max Sonoma 14.4.1
Docker version 24.0.7, build afdd53b
direnv 2.32.2

今回は環境作成時間短縮の為に [ucan-lab/docker-laravel](https://github.com/ucan-lab/docker-laravel) をテンプレートとして利用させてもらっています。

次から実際の手順を加えていきます。

## 環境変数の設定

今回は [direnv](https://direnv.net/) を利用しているので先に環境変数の設定をしておきます。

```shell
cp .envrc.sample .envrc
```

.envrc の中身を編集します

```.envrc
export NEW_RELIC_LICENSE_KEY=your_license_key

export APP_KEY=<php php artisan key:generate --show の結果を貼り付ける>
export APP_BUILD_TARGET=deploy
```

NEW_RELIC_LICENSE_KEY は [New Relic](https://docs.newrelic.com/docs/apis/intro-apis/new-relic-api-keys/) から API Key (INGEST)を取得してください。

## Dockerfile の設定

今回の全体はこうなっています。

```Dockerfile
FROM php:8.3-fpm-bullseye AS base

WORKDIR /workspace

# timezone environment
ENV TZ=UTC \
  # locale
  LANG=en_US.UTF-8 \
  LANGUAGE=en_US:en \
  LC_ALL=en_US.UTF-8 \
  # composer environment
  COMPOSER_HOME=/composer

ARG UID=1000
ARG GID=1000

COPY --from=composer:2.7 /usr/bin/composer /usr/bin/composer

RUN <<EOF
  apt-get update
  apt-get -y install --no-install-recommends \
    locales=2.31-13+deb11u10 \
    git=1:2.30.2-1+deb11u2 \
    unzip=6.0-26+deb11u1 \
    libzip-dev=1.7.3-1 \
    libicu-dev=67.1-7 \
    libonig-dev=6.9.6-1.1 \
    default-mysql-client=1.0.7
  locale-gen en_US.UTF-8
  localedef -f UTF-8 -i en_US en_US.UTF-8
  docker-php-ext-install \
    intl \
    pdo_mysql \
    zip \
    bcmath
  # permission denied bind mount in Linux environment
  groupadd --gid $GID phper
  useradd --uid $UID --gid $GID phper
  mkdir /composer
  mkdir -p /home/phper/.config/psysh
  chown phper:phper /composer
  chown phper:phper /workspace
  chown phper:phper /home/phper/.config/psysh
  apt-get clean
  rm -rf /var/lib/apt/lists/*
EOF

# New Relic Agent インストール
ARG NEW_RELIC_AGENT_VERSION
RUN curl -L https://download.newrelic.com/php_agent/archive/${NEW_RELIC_AGENT_VERSION}/newrelic-php5-${NEW_RELIC_AGENT_VERSION}-linux.tar.gz | tar -C /tmp -zx \
    && NR_INSTALL_USE_CP_NOT_LN=1 NR_INSTALL_SILENT=1 /tmp/newrelic-php5-${NEW_RELIC_AGENT_VERSION}-linux/newrelic-install install \
    && rm -rf /tmp/newrelic-php5-* /tmp/nrinstall*

FROM base AS development

COPY ./infra/docker/php/php.development.ini /usr/local/etc/php/php.ini

USER phper

FROM base AS development-xdebug

RUN <<EOF
  pecl install xdebug
  docker-php-ext-enable xdebug
EOF

COPY ./infra/docker/php/xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini

USER phper

FROM base AS deploy

COPY ./infra/docker/php/php.deploy.ini /usr/local/etc/php/php.ini
COPY ./infra/docker/php/newrelic.ini $PHP_INI_DIR/conf.d/newrelic.ini
COPY --chown=phper:phper ./src /workspace

RUN <<EOF
  composer install --quiet --no-interaction --no-ansi --no-dev --no-scripts --no-progress --prefer-dist
  composer dump-autoload --optimize
  chmod -R 777 storage bootstrap/cache
  php artisan optimize:clear
  php artisan optimize
EOF
```

ポイントは以下２点です

```Dockerfile
# New Relic Agent インストール
ARG NEW_RELIC_AGENT_VERSION
RUN curl -L https://download.newrelic.com/php_agent/archive/${NEW_RELIC_AGENT_VERSION}/newrelic-php5-${NEW_RELIC_AGENT_VERSION}-linux.tar.gz | tar -C /tmp -zx \
    && NR_INSTALL_USE_CP_NOT_LN=1 NR_INSTALL_SILENT=1 /tmp/newrelic-php5-${NEW_RELIC_AGENT_VERSION}-linux/newrelic-install install \
    && rm -rf /tmp/newrelic-php5-* /tmp/nrinstall*

...
COPY ./infra/docker/php/newrelic.ini $PHP_INI_DIR/conf.d/newrelic.ini

```

New Relic の Agent 取得と ini ファイルの設定です。
ini ファイルの中身はこうなっています。

```newrelic.ini
extension = newrelic.so

[newrelic]
newrelic.appname = laravel-newrelic-php-agent
newrelic.enabled = true
newrelic.daemon.dont_launch = 3
newrelic.daemon.address = newrelic-php-daemon:31339
newrelic.loglevel = verbosedebug #必要に応じて変更
newrelic.license = ${NEW_RELIC_LICENSE_KEY}
```

loglevel はこの状態だと大量に発生するので必要なレベルに置き換えてください。
細かい設定は New Relic のドキュメントにも掲載されています。

https://docs.newrelic.com/docs/apm/agents/php-agent/configuration/php-agent-configuration/

最後に `docker compose up` して何度か　`http://localhost` にアクセスすると Laravel のトップページが表示されると思うのでそれでアプリケーションとしてのセットは完了です。

同時に APM も立ち上がっており数分後にデータが流れ始めますので New Relic の画面を確認してもらって表示されていたら無事 APM の設定も成功になります。

![Screenshot 2024-05-12 at 23.29.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263293/b868f9e0-7d30-93c7-bb47-bc7cc83a894e.png)

この後は実際にアプリケーションを開発して New Relic APM でアプリケーションの計測をしながら改善をするための準備ができました。

本記事の本題はこれで以上ですが最後に PHP Agent を導入するうえでの注意点を紹介して締めたいと思います。


## 注意点

### Agent には root 相当の権限が必要

PHP Agent を導入するには root 相当の権限を要求されていますので注意が必要です。
実行時には root 権限は必要ないですが以下の項目には読み書きの権限を必要としているので必要に応じてユーザーに権限を付与してください。

```
A file in which to store the agent's log files
A file in which to store the agent's socket endpoint
A file in which to record the agent's process ID
```

https://docs.newrelic.com/docs/apm/agents/php-agent/troubleshooting/determine-permissions-requirements-php/


### 最初の処理が記録されない

APM にリクエストがくると Transaction として記録されるのですが PHP Agent の場合最初に記録されない問題があります。

これは New Relic daemon と言われる PHP Agent のデータを New Relic に転送するための Proxy のようなサービスを介するのですが初期起動時とアイドル状態の時に２回トランザクションを発生させる必要があり２回目から報告されるようになります。

ですので最初に curl などをしてみて記録されないと思った場合は数回リクエストをしてみてください。

https://docs.newrelic.com/docs/apm/agents/php-agent/getting-started/new-relic-daemon-processes/


:::note info
[New Relic株式会社のQiita Organization](https://qiita.com/organizations/newrelic)では、
新機能を含む活用方法を公開していますので、ぜひフォローをお願いします。
:::

:::note info
無料のアカウントで試してみよう！

[New Relic フリープランで始めるオブザーバビリティ！](https://qiita.com/ktst79/items/5ee74b34e6adb8a7a6fa)
:::