Programster's Blog

Tutorials focusing on Linux, programming, and open-source

Docker - Create .env File On Startup

The Problem

When writing software today, one typically needs an .env file somewhere with all of your environment settings in it which are typically not stored in the code repository for security reasons. When using CI/CD with something like GitLab or Jenkins, one will typically pass these secrets/settings at the point of running the Docker container.

E.g.

docker-run \
  -e "DB_HOST=192.168.1.2" \
  -e "DB_USER=bob" \
  my-container-image-name

You will be able to view these variables if you were to enter the container as the root user and run the env command. However, your web application, running as the www-data user, will not necessarily have access to them, nor would you want it to have access to all of the settings. To work around this, I have my containers root user create the .env file for my web application, on startup of the container. The script below will do this.

Script

<?php

/*
 * This script creates a .env file from expected variables specified in this file.
 * If we find that an expected environment variable is missing, then we notify you and exit with a -1 exit code.
 * Call it with php create-env-file.php [output filepath]
 */

define('REQUIRED_ENV_VARS', [
    "APP_KEY",
    "DB_HOST",
    "DB_USER",
    "DB_PASSWORD",
]);

define('OPTIONAL_ENV_VARS', [
    "DB_PORT",
]);

define('ALL_VARS', [...REQUIRED_ENV_VARS, ...OPTIONAL_ENV_VARS]);


function main(string $outputFilepath)
{
    $env = shell_exec("env");
    $filteredLines = [];
    $lines = explode(PHP_EOL, $env);

    foreach ($lines as $index => $line)
    {
        $parts = explode("=", $line);

        if (in_array($parts[0], ALL_VARS))
        {
            $filteredLines[$parts[0]] = $line;
        }
    }

    foreach (REQUIRED_ENV_VARS as $expectedVariable)
    {
        $missingKeys = array_diff(REQUIRED_ENV_VARS, array_keys($filteredLines));

        if (count($missingKeys) > 0)
        {
            fwrite(STDERR, "Missing required environment variables: " . PHP_EOL);

            foreach ($missingKeys as $missingKey)
            {
                fwrite(STDERR, " - {$missingKey}" . PHP_EOL);
            }

            fwrite(STDERR, "... out of the follwoing env vars: " . PHP_EOL);
            fwrite(STDERR, "{$env}" . PHP_EOL);

            exit(-1);
        }
    }

    $content = implode(PHP_EOL, $filteredLines);
    file_put_contents($outputFilepath, $content);
}

if (count($argv) < 2)
{
    fwrite(STDERR, "Missing expected output filepath as parameter." . PHP_EOL);
    exit(-1);
}

main($argv[1]);
Last updated: 16th June 2021
First published: 20th May 2021