newrelic / newrelic-php-agent

The New Relic PHP Agent
https://opensource.newrelic.com/projects/newrelic/newrelic-php-agent
Apache License 2.0
120 stars 62 forks source link

Mac ARM64 support in Docker images #706

Open NiklasBr opened 1 year ago

NiklasBr commented 1 year ago

Description

Attempting to install using a simple Docker image results in this error when building on ARM64 platforms even though the change log appears to say that support has been introduced:

E: Unable to locate package newrelic-php5

Steps to Reproduce

Dockerfile:

FROM php:8.1-fpm

WORKDIR /var/www

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

RUN apt-get update && apt-get install -y --no-install-recommends wget gnupg2 \
    && echo 'deb http://apt.newrelic.com/debian/ newrelic non-free' | tee /etc/apt/sources.list.d/newrelic.list

RUN wget -O- https://download.newrelic.com/548C16BF.gpg | apt-key add -

RUN apt-get update \
    && DEBIAN_FRONTEND=noninteractive apt-get -y install newrelic-php5 \
    && NR_INSTALL_SILENT=1 NR_INSTALL_KEY=TEMPLICENSEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA /usr/bin/newrelic-install install \
    && apt-get autoremove -y \
    && apt-get remove -y gnupg2 \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

Expected Behavior

Completed installation.

Relevant Logs / Console output

[internal] load .dockerignore
    transferring 2/0 0.001
[internal] load build definition from Dockerfile
    transferring 1144/0 0.002
[internal] load metadata for docker.io/library/composer:latest
[internal] load metadata for docker.io/library/php:8.1-fpm
[stage-0 3/6] COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
FROM docker.io/library/composer:latest@sha256:572a3d91b1233a8dc9397627f41832a6aa4d0dc63b18c1da816490e6b7f9536a
[stage-0 2/6] WORKDIR /var/www
[stage-0 1/6] FROM docker.io/library/php:8.1-fpm@sha256:69e7f00792d7bf942fe1ec275ce6b4616c2548223fad74bf38d8c103ff2e4e01
[stage-0 4/6] RUN apt-get update && apt-get install -y --no-install-recommends wget gnupg2     && echo 'deb http://apt.newrelic.com/debian/ newrelic non-free' | tee /etc/apt/sources.list.d/newrelic.list
    Get:1 http://deb.debian.org/debian bookworm InRelease [151 kB]
    Get:2 http://deb.debian.org/debian bookworm-updates InRelease [52.1 kB]
    Get:3 http://deb.debian.org/debian-security bookworm-security InRelease [48.0 kB]
    Get:4 http://deb.debian.org/debian bookworm/main arm64 Packages [8803 kB]
    Get:5 http://deb.debian.org/debian bookworm-updates/main arm64 Packages [4736 B]
    Get:6 http://deb.debian.org/debian-security bookworm-security/main arm64 Packages [48.9 kB]
    Fetched 9108 kB in 1s (6522 kB/s)
    Reading package lists...
    Reading package lists...
    Building dependency tree...
    Reading state information...
    The following additional packages will be installed:
    dirmngr gnupg gnupg-l10n gnupg-utils gpg gpg-agent gpg-wks-client
    gpg-wks-server gpgconf gpgsm libassuan0 libksba8 libncursesw6 libnpth0
    pinentry-curses
    Suggested packages:
    dbus-user-session libpam-systemd pinentry-gnome3 tor parcimonie xloadimage
    scdaemon pinentry-doc
    Recommended packages:
    libgpm2
    The following NEW packages will be installed:
    dirmngr gnupg gnupg-l10n gnupg-utils gnupg2 gpg gpg-agent gpg-wks-client
    gpg-wks-server gpgconf gpgsm libassuan0 libksba8 libncursesw6 libnpth0
    pinentry-curses wget
    0 upgraded, 17 newly installed, 0 to remove and 1 not upgraded.
    Need to get 9221 kB of archives.
    After this operation, 21.5 MB of additional disk space will be used.
    Get:1 http://deb.debian.org/debian bookworm/main arm64 wget arm64 1.21.3-1+b1 [967 kB]
    Get:2 http://deb.debian.org/debian bookworm/main arm64 libassuan0 arm64 2.5.5-5 [45.9 kB]
    Get:3 http://deb.debian.org/debian bookworm/main arm64 gpgconf arm64 2.2.40-1.1 [557 kB]
    Get:4 http://deb.debian.org/debian bookworm/main arm64 libksba8 arm64 1.6.3-2 [119 kB]
    Get:5 http://deb.debian.org/debian bookworm/main arm64 libnpth0 arm64 1.6-3 [18.6 kB]
    Get:6 http://deb.debian.org/debian bookworm/main arm64 dirmngr arm64 2.2.40-1.1 [770 kB]
    Get:7 http://deb.debian.org/debian bookworm/main arm64 gnupg-l10n all 2.2.40-1.1 [1093 kB]
    Get:8 http://deb.debian.org/debian bookworm/main arm64 gnupg-utils arm64 2.2.40-1.1 [880 kB]
    Get:9 http://deb.debian.org/debian bookworm/main arm64 gpg arm64 2.2.40-1.1 [903 kB]
    Get:10 http://deb.debian.org/debian bookworm/main arm64 libncursesw6 arm64 6.4-4 [122 kB]
    Get:11 http://deb.debian.org/debian bookworm/main arm64 pinentry-curses arm64 1.2.1-1 [75.2 kB]
    Get:12 http://deb.debian.org/debian bookworm/main arm64 gpg-agent arm64 2.2.40-1.1 [673 kB]
    Get:13 http://deb.debian.org/debian bookworm/main arm64 gpg-wks-client arm64 2.2.40-1.1 [532 kB]
    Get:14 http://deb.debian.org/debian bookworm/main arm64 gpg-wks-server arm64 2.2.40-1.1 [524 kB]
    Get:15 http://deb.debian.org/debian bookworm/main arm64 gpgsm arm64 2.2.40-1.1 [651 kB]
    Get:16 http://deb.debian.org/debian bookworm/main arm64 gnupg all 2.2.40-1.1 [846 kB]
    Get:17 http://deb.debian.org/debian bookworm/main arm64 gnupg2 all 2.2.40-1.1 [445 kB]
    debconf: delaying package configuration, since apt-utils is not installed
    Fetched 9221 kB in 1s (13.8 MB/s)
    Selecting previously unselected package wget.
    (Reading database ...(Reading database ... 5%
(Reading database ... 10%
(Reading database ... 15%
(Reading database ... 20%
(Reading database ... 25%
(Reading database ... 30%
(Reading database ... 35%
(Reading database ... 40%
(Reading database ... 45%
(Reading database ... 50%
(Reading database ... 55%
(Reading database ... 60%
(Reading database ... 65%
(Reading database ... 70%(Reading database ... 75%(Reading database ... 80%(Reading database ... 85%(Reading database ... 90%(Reading database ... 95%(Reading database ... 100%
(Reading database ... 13280 files and directories currently installed.)
    Preparing to unpack .../00-wget_1.21.3-1+b1_arm64.deb ...
    Unpacking wget (1.21.3-1+b1) ...
    Selecting previously unselected package libassuan0:arm64.
    Preparing to unpack .../01-libassuan0_2.5.5-5_arm64.deb ...
    Unpacking libassuan0:arm64 (2.5.5-5) ...
    Selecting previously unselected package gpgconf.
    Preparing to unpack .../02-gpgconf_2.2.40-1.1_arm64.deb ...
    Unpacking gpgconf (2.2.40-1.1) ...
    Selecting previously unselected package libksba8:arm64.
    Preparing to unpack .../03-libksba8_1.6.3-2_arm64.deb ...
    Unpacking libksba8:arm64 (1.6.3-2) ...
    Selecting previously unselected package libnpth0:arm64.
    Preparing to unpack .../04-libnpth0_1.6-3_arm64.deb ...
    Unpacking libnpth0:arm64 (1.6-3) ...
    Selecting previously unselected package dirmngr.
    Preparing to unpack .../05-dirmngr_2.2.40-1.1_arm64.deb ...
    Unpacking dirmngr (2.2.40-1.1) ...
    Selecting previously unselected package gnupg-l10n.
    Preparing to unpack .../06-gnupg-l10n_2.2.40-1.1_all.deb ...
    Unpacking gnupg-l10n (2.2.40-1.1) ...
    Selecting previously unselected package gnupg-utils.
    Preparing to unpack .../07-gnupg-utils_2.2.40-1.1_arm64.deb ...
    Unpacking gnupg-utils (2.2.40-1.1) ...
    Selecting previously unselected package gpg.
    Preparing to unpack .../08-gpg_2.2.40-1.1_arm64.deb ...
    Unpacking gpg (2.2.40-1.1) ...
    Selecting previously unselected package libncursesw6:arm64.
    Preparing to unpack .../09-libncursesw6_6.4-4_arm64.deb ...
    Unpacking libncursesw6:arm64 (6.4-4) ...
    Selecting previously unselected package pinentry-curses.
    Preparing to unpack .../10-pinentry-curses_1.2.1-1_arm64.deb ...
    Unpacking pinentry-curses (1.2.1-1) ...
    Selecting previously unselected package gpg-agent.
    Preparing to unpack .../11-gpg-agent_2.2.40-1.1_arm64.deb ...
    Unpacking gpg-agent (2.2.40-1.1) ...
    Selecting previously unselected package gpg-wks-client.
    Preparing to unpack .../12-gpg-wks-client_2.2.40-1.1_arm64.deb ...
    Unpacking gpg-wks-client (2.2.40-1.1) ...
    Selecting previously unselected package gpg-wks-server.
    Preparing to unpack .../13-gpg-wks-server_2.2.40-1.1_arm64.deb ...
    Unpacking gpg-wks-server (2.2.40-1.1) ...
    Selecting previously unselected package gpgsm.
    Preparing to unpack .../14-gpgsm_2.2.40-1.1_arm64.deb ...
    Unpacking gpgsm (2.2.40-1.1) ...
    Selecting previously unselected package gnupg.
    Preparing to unpack .../15-gnupg_2.2.40-1.1_all.deb ...
    Unpacking gnupg (2.2.40-1.1) ...
    Selecting previously unselected package gnupg2.
    Preparing to unpack .../16-gnupg2_2.2.40-1.1_all.deb ...
    Unpacking gnupg2 (2.2.40-1.1) ...
    Setting up libksba8:arm64 (1.6.3-2) ...
    Setting up wget (1.21.3-1+b1) ...
    Setting up libnpth0:arm64 (1.6-3) ...
    Setting up libassuan0:arm64 (2.5.5-5) ...
    Setting up gnupg-l10n (2.2.40-1.1) ...
    Setting up libncursesw6:arm64 (6.4-4) ...
    Setting up gpgconf (2.2.40-1.1) ...
    Setting up gpg (2.2.40-1.1) ...
    Setting up gnupg-utils (2.2.40-1.1) ...
    Setting up pinentry-curses (1.2.1-1) ...
    Setting up gpg-agent (2.2.40-1.1) ...
    Setting up gpgsm (2.2.40-1.1) ...
    Setting up dirmngr (2.2.40-1.1) ...
    Setting up gpg-wks-server (2.2.40-1.1) ...
    Setting up gpg-wks-client (2.2.40-1.1) ...
    Setting up gnupg (2.2.40-1.1) ...
    Setting up gnupg2 (2.2.40-1.1) ...
    Processing triggers for libc-bin (2.36-9+deb12u1) ...
    deb http://apt.newrelic.com/debian/ newrelic non-free
[stage-0 5/6] RUN wget -O- https://download.newrelic.com/548C16BF.gpg | apt-key add -
    --2023-07-31 14:27:18--  https://download.newrelic.com/548C16BF.gpg
    Resolving download.newrelic.com (download.newrelic.com)...Warning: apt-key is deprecated. Manage keyring files in trusted.gpg.d instead (see apt-key(8)).
    146.75.122.137
    Connecting to download.newrelic.com (download.newrelic.com)|146.75.122.137|:443...connected.
    HTTP request sent, awaiting response...200 OK
    Length: 1682 (1.6K) [application/octet-stream]
    Saving to: 'STDOUT'

    0K .                                                     100% 44.0M=0s

    2023-07-31 14:27:18 (44.0 MB/s) - written to stdout [1682/1682]

    OK
[stage-0 6/6] RUN apt-get update     && DEBIAN_FRONTEND=noninteractive apt-get -y install newrelic-php5     && NR_INSTALL_SILENT=1 NR_INSTALL_KEY=TEMPLICENSEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA /usr/bin/newrelic-install install     && apt-get autoremove -y     && apt-get remove -y gnupg2     && apt-get clean     && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
    Hit:1 http://deb.debian.org/debian bookworm InRelease
    Hit:3 http://deb.debian.org/debian bookworm-updates InRelease
    Hit:4 http://deb.debian.org/debian-security bookworm-security InRelease
    Ign:2 https://apt.newrelic.com/debian newrelic InRelease
    Get:5 https://apt.newrelic.com/debian newrelic Release [9960 B]
    Get:6 https://apt.newrelic.com/debian newrelic Release.gpg [163 B]
    Get:7 https://apt.newrelic.com/debian newrelic/non-free arm64 Packages [5400 B]
    Fetched 15.5 kB in 1s (28.6 kB/s)
    Reading package lists...
    W: http://apt.newrelic.com/debian/dists/newrelic/Release.gpg: Key is stored in legacy trusted.gpg keyring (/etc/apt/trusted.gpg), see the DEPRECATION section in apt-key(8) for details.
    Reading package lists...
    Building dependency tree...
    Reading state information...
    E: Unable to locate package newrelic-php5

Your Environment

Additional context

mdoelker commented 1 year ago

Even though the release notes and Docs say otherwise, the binaries are missing in the repository: https://apt.newrelic.com/debian/dists/newrelic/non-free/binary-arm64/

zsistla commented 1 year ago

Hi and thank you for your feedback.

As mentioned in the compatibility page, New Relic PHP agent 10.10.0 or later provides support for ARM64 by including binaries in a tarball distribution.The ARM64 binaries are only provided in the tarballs. Please see here for installation instructions: https://docs.newrelic.com/docs/apm/agents/php-agent/installation/php-agent-installation-arm64/#tarball-installation

NiklasBr commented 1 year ago

What is the expectation when building multi-architecture containers with Docker? Impossible by design?

zsistla commented 1 year ago

Hi @NiklasBr ,

Thanks for providing feedback about your usage case.

There's an example using the tarball in a dockerfile which would work on both x64 and arm64: https://docs.newrelic.com/docs/apm/agents/php-agent/advanced-installation/docker-other-container-environments-install-php-agent/#dockerfile-example

NiklasBr commented 1 year ago

@zsistla I am unable to expand the accordion with the Dockerfile example in your link, the Firefox console gives the following error message:

Uncaught SyntaxError: '' literal not terminated before end of script app-4198df041846dc9f45e0.js:2:3931723

Update: I could manually inspect the source code and extract the contents. Is there a way to get the latest version every request rather than hardcoding the point release? Like for example using the URL https://imagemagick.org/archive/binaries/magick will download the latest version to build without the need to constantly check the site for udpates. Or like Composer does which allows either or.

zsistla commented 1 year ago

Hi, apologies for that inconvenience. It seems you were able to extract the directions, but below are the details from the page:

To set up the PHP agent and daemon in the same Docker container:

Make sure a PHP installation is available in the container. For example: you might use a published Docker image like php:7.1. To install the agent, download the PHP agent package from New Relic's tar file download site and run the newrelic-install script with the install argument. Set the application name and license key via the newrelic.license and newrelic.appname entries in the newrelic.ini file.

Dockerfile example FROM php:7.1

RUN \ curl -L PHP_AGENT_URL | tar -C /tmp -zx && \ export NR_INSTALL_USE_CP_NOT_LN=1 && \ export NR_INSTALL_SILENT=1 && \ /tmp/newrelic-php5-/newrelic-install install && \ rm -rf /tmp/newrelic-php5- /tmp/nrinstall && \ sed -i \ -e 's/"REPLACE_WITH_REAL_KEY"/"YOUR_LICENSE_KEY"/' \ -e 's/newrelic.appname = "PHP Application"/newrelic.appname = "YOUR_APPLICATION_NAME"/' \ -e 's/;newrelic.daemon.app_connect_timeout =./newrelic.daemon.app_connect_timeout=15s/' \ -e 's/;newrelic.daemon.start_timeout =.*/newrelic.daemon.start_timeout=5s/' \ /usr/local/etc/php/conf.d/newrelic.ini

You must edit three parts of this example Dockerfile:

PHP_AGENT_URL: The download URL for your PHP agent version. To find the most recent version of the agent, go to download.newrelic.com/php_agent/release/. YOUR_LICENSE_KEY: Replace this with your license key. Note that "REPLACE_WITH_REAL_KEY" is an actual string in the default newrelic.ini file for the PHP agent. Don't edit that string. The sed command replaces that default string with the actual 40-character key, in quotes. YOUR_APPLICATION_NAME: Replace with the your application name, in quotes.

At the moment, to get the latest build without having to check/update the number requires something like:

NEWRELIC_FILE=$(curl -s https://download.newrelic.com/php_agent/release/ | grep -o ‘newrelic-php5-(\d+.)+-linux.tar.gz’ | head -n 1) || exit; \

curl -L https://download.newrelic.com/php_agent/release/${NEWRELIC_FILE} | tar -C /tmp -zx

NiklasBr commented 1 year ago

Looked promising but could not get it to work:

NEWRELIC_FILE=$(curl -s https://download.newrelic.com/php_agent/release/ | grep -o ‘newrelic-php5-(\d+.)+-linux.tar.gz’ | head -n 1) || exit; \

curl -L https://download.newrelic.com/php_agent/release/${NEWRELIC_FILE} | tar -C /tmp -zx

zsh: no matches found: ‘newrelic-php5-(d+.)+-linux.tar.gz’
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  1009  100  1009    0     0  11390      0 --:--:-- --:--:-- --:--:-- 11870
tar: Error opening archive: Unrecognized archive format
zsistla commented 1 year ago

HI @NiklasBr ,

Probably missing some backslash in there.

The following works to get the AGENT_VERSION:

          VERSION_REGEX='[1-9][0-9]\?\(\.[0-9]\+\)\{3\}'
          RELEASE_URL='https://download.newrelic.com/php_agent/release/'
          AGENT_VERSION="$(curl -s "$RELEASE_URL" | grep --only-match "$VERSION_REGEX" | head -n1)"

The following works to get the file:

NEWRELIC_FILE=$(curl 'https://download.newrelic.com/php_agent/release/' | grep -o 'newrelic-php5.*linux\.tar\.gz' | sed -e 's/^.*>//;s/<[^>]*>//g')
AdrienPoupa commented 11 months ago

This is the complete recipe I used in case somebody is interested:

RUN cd /tmp \
   && VERSION_REGEX='[1-9][0-9]\?\(\.[0-9]\+\)\{3\}' \
   && NEWRELIC_FILE=$(curl 'https://download.newrelic.com/php_agent/release/' | grep -o 'newrelic-php5.*linux\.tar\.gz' | sed -e 's/^.*>//;s/<[^>]*>//g') \
   && NEWRELIC_FOLDER=$(echo ${NEWRELIC_FILE} | sed 's/.tar.gz//g') \
   && curl https://download.newrelic.com/php_agent/release/${NEWRELIC_FILE} | tar -zx \
   && cd ${NEWRELIC_FOLDER} \
   && export NR_INSTALL_USE_CP_NOT_LN=1 \
   && export NR_INSTALL_SILENT=1 \
   && ./newrelic-install install \
   && cd /tmp \
   && rm -rf ${NEWRELIC_FOLDER}
AdrienPoupa commented 11 months ago

By the way, we got badly bit by https://github.com/newrelic/newrelic-php-agent/issues/399 when switching from the package-based installation to the tarball. We used to rely on the newrelic.ini file in mods-available but the install script will make two copies of the configuration file to the CLI and FPM conf.d folders without respecting mods-available.

We had to do this post installation to read from the mods-available config file, assuming you copied the file there:

rm /etc/php/8.1/fpm/conf.d/newrelic.ini /etc/php/8.1/cli/conf.d/newrelic.ini
   && ln -s /etc/php/8.1/mods-available/newrelic.ini /etc/php/8.1/fpm/conf.d/20-newrelic.ini

Side note, as it stands in the official configuration (-e 's/"REPLACE_WITH_REAL_KEY"/"YOUR_LICENSE_KEY"/'), the license key will be included in the Docker image, which is a bad practice imo.

NiklasBr commented 9 months ago

Thanks for your working recipe @AdrienPoupa!

lavarou commented 6 months ago

Side note, as it stands in the official configuration (-e 's/"REPLACE_WITH_REAL_KEY"/"YOUR_LICENSE_KEY"/'), the license key will be included in the Docker image, which is a bad practice imo.

To mitigate this I suggest following modification to the working recipe shared here:

# Install the latest New Relic PHP Agent
RUN \
    cd /tmp \
    # Discover the latest released version:
    && export NEW_RELIC_AGENT_VERSION=$(curl -s https://download.newrelic.com/php_agent/release/ | grep --only-match '[1-9][0-9]\?\(\.[0-9]\+\)\{3\}' | head -n1) \
    # Download the discovered version:
    && curl -o newrelic-php-agent.tar.gz https://download.newrelic.com/php_agent/release/newrelic-php5-${NEW_RELIC_AGENT_VERSION}-linux.tar.gz \
    # Install the downloaded agent:
    && tar xzf newrelic-php-agent.tar.gz \
    && NR_INSTALL_USE_CP_NOT_LN=1 NR_INSTALL_SILENT=0 ./*/newrelic-install install \
    # Configure the agent to use license key from NEW_RELIC_LICENSE_KEY env var:
    && sed -ie 's/[ ;]*newrelic.license[[:space:]]=.*/newrelic.license=${NEW_RELIC_LICENSE_KEY}/' $(php-config --ini-dir)/newrelic.ini \
    # Configure the agent to send telemetry to collector defined by NEW_RELIC_HOST env var:
    && sed -ie 's/[ ;]*newrelic.daemon.collector_host[[:space:]]=.*/newrelic.daemon.collector_host=${NEW_RELIC_HOST}/' $(php-config --ini-dir)/newrelic.ini \
    # Configure the agent to use app name from NEW_RELIC_APP_NAME env var:
    && sed -ie 's/[ ;]*newrelic.appname[[:space:]]=.*/newrelic.appname=${NEW_RELIC_APP_NAME}/' $(php-config --ini-dir)/newrelic.ini \
    # Cleanup temporary files:
    && rm newrelic-php-agent.tar.gz && rm -rf newrelic-php5-*-linux

This will cause the agent's configuration to use values for newrelic.appname and newrelic.license based on values of NEW_RELIC_LICENSE_KEY and NEW_RELIC_APP_NAME env vars provided at the time the container is started and not hardcoding them in the image.