skip to Main Content

I have a task definition that looks like this (truncated for readability). And I need to get the host IP address dynamically available inside the PHP container. It’s required for Datadog to work.

[
  {
    ...
    "entryPoint": [
      "/usr/local/bin/entrypoint.sh"
    ],
    "portMappings": [
      {
        "hostPort": 0,
        "protocol": "tcp",
        "containerPort": 9000
      }
    ],
    ...

This is a container that runs a Symfony application, with php-fpm. So my entrypoint.sh looks like this:

#!/bin/sh

export TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
export DD_AGENT_HOST=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/local-ipv4)

echo "Datadog agent host: ${DD_AGENT_HOST}"

php-fpm -F

The echo debug prints the correct value in the cloudwatch logs. However when I log into this container after it starts en check the environment variables with php -i, the variable is not in there.

I made sure clear_env = no is in my www.conf. But no success.

Here’s my Dockerfile, for reference:

# Multi stage build. We first run composer install, and later copy it over in the 2nd image
FROM composer:2 as vendor

WORKDIR "/app/platform"

COPY ["./app/composer.json", "./app/composer.lock*", "/app/platform/"]

RUN composer install --no-interaction --no-dev --prefer-dist --ignore-platform-reqs

FROM php:8.1-fpm-buster as platform

RUN 
    # Symfony needs write access to some folders. We need to pre generate these
    mkdir -p "/app/platform/var" 
    && chmod 777 -R "/app/platform/var" 
    # Install necessary binaries and packages
    && apt-get update 
    && apt-get install -y gnupg g++ procps openssl git unzip zlib1g-dev libzip-dev libfreetype6-dev libpng-dev libjpeg-dev libicu-dev  libonig-dev libxslt1-dev acl libjpeg62-turbo-dev libmcrypt-dev zip vim 
    # Install php extensions
    #&& pecl install redis 
    #&& docker-php-ext-enable redis 
    && docker-php-ext-install pdo pdo_mysql zip xsl gd intl opcache exif mbstring soap 
    # Install Composer
    && curl -sS https://getcomposer.org/installer | php -- --install-dir="/usr/local/bin" --filename=composer && chmod +x "/usr/local/bin/composer"

# Datadog
ARG DD_ENV_ARG=placeholder
ENV DD_ENV=$DD_ENV_ARG

ENV DD_VERSION=1
ENV DD_SERVICE=platform-aws
ENV DD_PROFILING_ENABLED=true

COPY "./.docker-prod/platform/datadog-setup.php" "/app/platform/datadog-setup.php"
RUN php /app/platform/datadog-setup.php --php-bin=all --enable-profiling

COPY "./app" "/app/platform"
RUN perl -pi -e 's#^(?=access.logb)#;#' /usr/local/etc/php-fpm.d/docker.conf
COPY "./.docker-prod/platform/php.ini" "/usr/local/etc/php/conf.d/docker-php-config.ini"
COPY "./.docker-prod/platform/www.conf" "/usr/local/etc/php-fpm.d/www.conf"
COPY --from=vendor "/app/platform/vendor" "/app/platform/vendor"

WORKDIR "/app/platform"

RUN 
    composer dump-autoload --optimize --classmap-authoritative 
    && composer run-script post-install-cmd

# Entrypoint
COPY "./.docker-prod/platform/entrypoint.sh" "/usr/local/bin/entrypoint.sh"
RUN chmod +x "/usr/local/bin/entrypoint.sh"

I honestly tried everything to make this work, but no success. Even the documentation of datadog using the same kind of approach, but using that exact example also didn’t work: https://docs.datadoghq.com/containers/amazon_ecs/apm/?tab=ec2metadataendpoint&code-lang=php

Anyone any ideas?

2

Answers


  1. The issue is that environment variables set in the entrypoint script are not persisted and available to the main php-fpm process. When php-fpm starts, it has its own clean environment.

    There are a couple ways to address this:

    1. Set the environment variable directly in the Dockerfile:
    ENV DD_AGENT_HOST=<host_ip>
    

    The downside here is the IP is baked into the image, not dynamic.

    1. Have the entrypoint script write the IP to a file that is read by php:

    In entrypoint.sh:

    #!/bin/sh
    
    # Get IP
    export IP=$(curl...) 
    
    # Write to file
    echo "$IP" > /opt/dd_agent_host
    

    In php code:

    // Read IP from file
    $ip = file_get_contents('/opt/dd_agent_host'); 
    
    // Set as env var
    putenv('DD_AGENT_HOST=' . $ip);
    
    1. Set the env var in the php-fpm config:

    In entrypoint.sh:

    export IP=...
    
    # Add to php-fpm config
    echo "env[DD_AGENT_HOST] = $IP" >> /usr/local/etc/php-fpm.d/www.conf
    

    This will make it available to php-fpm without needing a file.

    So in summary, environment variables from the entrypoint don’t persist to the main process – you need to either bake it in, write to a file, or configure it directly for php-fpm.

    Boop.

    Login or Signup to reply.
  2. However, when I log into this container after it starts en check the environment variables with php -i, the variable is not in there.

    But… when you run php -i (or any PHP script) directly from the command line, you are invoking the PHP CLI (Command Line Interface) binary, not the PHP-FPM process. Environment variables set in php-fpm configurations (like /usr/local/etc/php-fpm.d/www.conf) will not necessarily be available in this context.

    If you are setting environment variables specifically for PHP-FPM, you will need to test them in the context of a PHP script that is being served by PHP-FPM and accessed via a web request.

    So, to truly check if DD_AGENT_HOST is available to PHP-FPM, create a PHP script like this:

    <?php
    
    $envName = 'DD_AGENT_HOST';
    $envValue = getenv($envName);
    
    echo "Environment Variable Name: {$envName}n";
    echo "Value: '{$envValue}'n";
    
    if (empty($envValue)) {
        echo "The value appears to be empty or not set.";
    } else {
        echo "The value is set and not empty.";
    }
    ?>
    

    Then serve it using PHP-FPM and your web server (Nginx, Apache, etc.).
    And Access it through a web request.

    That will give you a definitive answer whether the environment variable is available in the PHP-FPM context.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search