What is this problem?
With a web based container using something like FPM there is usually no issue once the agent is installed in the container. But containers that run a single PHP script usually don’t report any data out of the box due to how the agent starts up and connects to New Relic servers. This is due to how the container may only run a single PHP script and shut down, not leaving time for the agent to report data captured for that script. Consider a container built like this:
FROM php:7.1.31-zts-alpine3.10 COPY ./ourscript.php /app/ WORKDIR /app CMD [ "php", "ourscript.php"]
A common use case for containers like this is a Laravel Queue container. Running the queue worker command as your entrypoint will not report data.
This is due to the first request for a given NewRelic.appname being lost as the agent tries to connect and register the appname with New Relic servers. With only one PHP request occurring in these containers this means the only request is lost! This is explained in more detail in my post about the PHP Agent startup process here:
What is the solution?
We need to do a couple things in this case:
Start the daemon in external startup mode before we run any PHP script. If we are in agent startup mode we’d need a second dummy PHP script to start the daemon before step 2.
Call a dummy PHP script to force the app to connect to New Relic servers. This request won’t be reported to New Relic and is lost.
(OPTIONAL) Give some time after our script runs so that it can report to New Relic. The Agent only reports data captured once a minute so a 30second PHP script container won’t report data. If you have used the API to stop/start/stop transactions within your script then this may not be necessary as transactions will report once a minute even before your PHP script finishes.
To accomplish this we’ll change our entrypoint from our script to a bash script which does some additional steps before running our PHP script.
#start the daemon manually /usr/bin/newrelic-daemon -c /etc/newrelic/newrelic.cfg wait #Dummy request to connect the app to New Relic and give it a second to finish php -i > /dev/null sleep 1 #Start our actual script php ourscript.php wait #Give it some time to report data to New Relic before container shuts down sleep 60
Our Dockerfile with the agent installed looks like this now:
FROM php:7.1.31-zts-alpine3.10 COPY ./ourscript.php /app/ COPY ./startup.sh /app/ WORKDIR /app #Download and install New Relic PHP Agent RUN \ curl -L https://download.newrelic.com/php_agent/release/newrelic-php5-18.104.22.168-linux-musl.tar.gz | tar -C /tmp -zx && \ NR_INSTALL_USE_CP_NOT_LN=1 NR_INSTALL_SILENT=1 /tmp/newrelic-php5-*/newrelic-install install && \ sed -i -e 's/"REPLACE_WITH_REAL_KEY"/"atotallyrealvalidkey"/' \ -e 's/newrelic.appname = "PHP Application"/newrelic.appname = "AlpineDockerTest"/' \ /usr/local/etc/php/conf.d/newrelic.ini #External startup mode requires a newrelic.cfg RUN cp /etc/newrelic/newrelic.cfg.template /etc/newrelic/newrelic.cfg #run this bash script that pre-heats the app with a dummy php command before running our actual script CMD [ "./startup.sh"]
This setup should have any command line PHP script reporting data to New Relic!