Angular on Docker — environment specific settings

Angular applications often have settings which vary depending on which environment they are running in. For example, when running it in production, an application may need to use a different URL to connect to a backend api, compared with a staging environment, or locally on a developer’s machine.

One solution is to put the settings in environment.ts file, and include an additional environment.{env-name}.ts files for each environment we need. This means we need to specify the environment when we build our application, which isn’t great when we want to deploy an image.

When the Angular application is deployed as a docker image, we really want the same image be used, regardless of which environment we’re deploying to, so a different solution is needed.

Firstly, we need to put the settings we need for local development into a json file. I put this file in the assets folder, which gets copied to the dist folder when the project is built (assuming you’re using angular cli).

Then we create a class to represent the settings in our Angular application:

a service which can be injected into any class which needs access to the settings:

and another service to request the settings on application startup:

This service needs to be registered as an APP_INITIALIZER in the app.module.ts:

With this in place, the application should load the settings provided in the settings.json file on startup.

To vary the settings based on environment, I add an additional file in the assets folder.

This has the same structure as the settings.json file, but specifies the name of an environment variable, instead of the setting value.

Then I modify my Dockerfile, so that when the container starts up, it replaces the environment variable names in the template file, with the values of those variables, and overwrites the settings.json file with the result, before starting the webserver.

In this case I’m using the standard nginx image — if you’re using something different you’ll need to make the appropriate changes.

I use envsubst to perform the variable substitution, and then I startup nginx.

Now when I start up the container, I can pass in my settings as environment variables.

So now a single image can be deployed to any number of environments, and the settings varied accordingly.