Env::Dot
Tags: perl, dotenv, cli, docker
Published: 2023-04-28 08:58:06

# Env::Dot

In the category of "scratching my itch".

## Usage

### In Perl:

    use Env::Dot;
    print $ENV{'VAR_DEFINED_IN_DOTENV_FILE'};

### On Command Line:

    echo 'VAR="Good value"'>> .env
    envdot

Output:

    VAR='Good value'; export VAR


## Background

> An app’s config is everything that is likely to vary between deploys (staging, production, developer environments, etc).
> [The Twelve-Factor App](https://12factor.net/config)

Storing the often changing parts of configuration in environment variables is one of the principles of [The Twelve-Factor App](https://12factor.net/config).

From this principle follows the need to store those environment variables and their values in an easily accessible way. Hence, every developer maintains his or her own project specific `.env` files next to the project files in the same directory where they are used, for instance, when running locally or testing locally.

## Yet Another Dotenv Solution

As if we didn't have these enough already...

What is different with this one, except the name [Env::Dot](https://metacpan.org/pod/Env::Dot)?

### Flexibility in input

- `.env` files come in two formats: _Shell compatible_ and
  _Docker combatible_. `Env::Dot` supports both.
- If no `.env` file is present, then do nothing.
- If your `.env` file is located in another path,
  not the current working directory,
  you can use the environment variable
  `DOTENV_FILEPATHS` to tell where your dotenv file is located.
  You can specify several file paths; just separate
  them by `:`. `Dot::Env` will load all the files in the order
  you specify them.

### Flexibility in output

- Just use `Env::Dot` in your program and your `%ENV` will grow
  with the variables defined in `.env` file.
- There is also a command line executable, `envdot`,
  to read the `.env` file and write out commands to create
  the environment variables.
- Command `envdot` can write the env vars in `sh` (sh/Bash/Zsh),
  `csh` (C shell/tcsh) and `fish` (Fish) shell formats.
- Command `envdot` will by default also export variables but you can prevent this if you don't
  want the variables to be present in subshells and programs. This would
  make the variables only local to your current shell.

### Existing Environment Takes Precedence

Existing environment variables always take precedence to dotenv variables!

A dotenv variable (variable from a file) does not overwrite an existing environment variable. This is by design because a dotenv file is to augment the environment, not to replace it.

This means that you can override a variable in `.env` file by creating its counterpart in the environment. For instance:


    unset VAR
    echo "VAR='Good value'" >> .env
    perl -e 'use Env::Dot; print "VAR:$ENV{VAR}\n";'
    # VAR:Good value
    VAR='Better value'; export VAR
    perl -e 'use Env::Dot; print "VAR:$ENV{VAR}\n";'
    # VAR:Better value


### DotEnv File Meta Commands

The `file:` commands affect all rows following its use.

The `var:` commands affect only the subsequent variable definition. If there is another **envdot** command, the second overwrites the first and default values are applied again.

#### `file:type`

Changes how `Env::Dot` reads lines below from this commands. Default is:

    # envdot (file:type=shell)
    VAR="value"


Other possible value of `file:type` is `plain`. Docker is using these kinds of `.env` files. Variable name is followed by `=` and value is the rest of the row before linefeed.

    # envdot (file:type=plain)
    VAR=My var value


#### `var:allow_interpolate`

By default, when writing variable definitions for the shell,
every variable is treated as static and surrounded with single quotation marks (') in Unix shell which means shell will read the variable content as is. By setting this to `1` or `true`, you allow shell to interpolate. **This meta command is only useful when running `envdot` command to create variable definitions for `eval` command to read.**


    # envdot (var:allow_interpolate)
    DYNAMIC_VAR="$(pwd)/${ANOTHER_VAR}"



### `envdot`

`envdot` is a shell command which translates the dotenv files into shell commands. The file `.env` is of course the default input.

    envdot
    # VAR='Good value'; export VAR

It has the following parameters:

#### --export, --no-export

Write commands to set variables for local shell or for exporting
them. You usually want to export the variables to all subsequent
programs and subshells, i.e. make them into *environment
variables*.

Default: export

#### -s, --shell

Which shell (family) are you using? Supported: sh, csh, fish.

#### -e, --dotenv

Path to .env file.

Default: current directory .env


## Installation

If you need to use the `envdot` command in a restricted environment, such as a docker image build, there is a [FatPacked](https://metacpan.org/pod/fatpack) executable ready. Usable when using [CPAN](https://metacpan.org/pod/Env::Dot) is overkill.


    curl -LSs -o envdot https://raw.githubusercontent.com/mikkoi/envdot/master/envdot.self-contained
    chmod +x ./envdot


Or you can do this in a `Dockerfile`:


    RUN curl -LSs -o /usr/local/bin/envdot \
        https://raw.githubusercontent.com/mikkoi/env-dot/master/envdot.self-contained
    RUN chmod +x /usr/local/bin/envdot


There is no extra dependencies outside Perl's standard distribution, so `envdot` is as lean as it can be. And Perl, of course, is present in every more or less standard Linux distribution.