Doppler: The Docker of Environment Variables

Doppler: The Docker of Environment Variables

We have been working on a few projects and the one tool that we always set up first is Doppler. Doppler makes it easy to load your environment variables seamlessly into any context, which means you don't need to redefine the same environment variables on your local machines, Github Actions, CircleCI, Heroku, Netlify, etc., over and over again!

We specifically use Doppler in our local development environment, in all of our Github Actions, in Vercel, and in our Docker containers (which are pushed to render). It is quite refreshing to not have to define and manage the environment variables in 4+ different contexts.

Normally we only talk about open source projects, but Doppler has been such an amazing tool to work with that we felt the need to share it. They have a pretty good free plan if you would like to give it a shot!

Setup

To get started, go ahead and create an account on Doppler. They have a very generous free plan which should cover most of your use cases. After creating an account, set up the cli, and create a project.

By default you should have three environments, dev, stg, and prd. You can easily delete the environments you don't want and add new custom environments. We currently do not have a staging environment but do have a custom "CI" environment, so our setup usually looks something like this:

image.png

  • dev contains values that allow us to work on our laptops such as sandboxed tokens and dummy data.
  • ci contains a subset of the production variables that are needed in the CI. For example, we need the DATABASE_URL to run migrations, but we don't need JOBS_REDIS_URL or STRIPE_TOKEN since those are more runtime related variables.
  • prd contains all of our production variables

Using in a Docker Container

Using Doppler in a Docker container is super easy. Setting the ENTRYPOINT to Doppler will make sure any commands you run afterward will use the environment variables.

EXPOSE 5000
ENTRYPOINT ["doppler", "run", "--"]
CMD ["npm", "start"]

When you run your container, make sure to pass in a DOPPLER_TOKEN as an environment variable so Doppler can load your variables. Check out their Docker docs for more information.

An additional bonus is that when you set ENTRYPOINT, it prefixes every command. That means that if you SSH into your container at a later date and run a command, they will automatically contain the correct environment variables.

Deploying Via Github Actions

We extensively use Doppler in our Github Actions. The first thing we do in every action is define the Doppler token at the top as a global env (don't forget to set up Github in the Doppler Integrations settings):

name: main
on: [push]
env:
  DOPPLER_TOKEN: ${{ secrets.DOPPLER_TOKEN }}
...

This allows any of the underlying jobs to use the variables stored in Doppler when they need it.

Then when we need to use the environment variables, we can simply run it with the Doppler command like so:

- run: doppler run -- prisma migrate up --experimental

In cases where we need to use an environment variable in the command itself, you'll need to use a tiny hack to substitute your values in like this:

- run: ssh-keyscan $(doppler run -- printenv PRODUCTION_HOST) >> ~/.ssh/known_hosts

In this case, Doppler is run in a sub-command and has its value substituted in the main command.

Conclusion

You should now have a very portable way to move your environment variables around. Check Doppler out at doppler.com