Angular & Docker: Environment Supported Configuration
We are constantly setting up a SPA with Angular 4, hosting it from Docker on Azure. Typically environments (Prod, Development, Testing) are installed in Angular using Config-Config, which are compiled if we use Angular -CLI build command. This is great, but the workflow with Docker is slightly different:
- Create Angular Application
- Initialize Docker container
- Set Docker Container Environment Variables
- Start Docker container
This means that we have a synchronization problem because at compile time we cannot tell in which environment the application will run. For the server (.net core) this is not a problem, since we can use the ASPNETCORE_ENVIRONMENT variable, but we have not found a solution for the application to become aware of the environment type. I'm pretty sure we're not the only people with this problem, but I haven't found a suitable solution yet. Is there some possibility that we don't know about?
source to share
Since my main goal was not to create a Container for each environment, and also to maintain an environment agnostic build process, I ended up with the following solution: I use the docker-stack file to add the command (My Docker image is NGinx):
command: /bin/bash -c "cp /usr/share/nginx/html/assets/app-settings/appsettings.__EnvironmentName__.json /usr/share/nginx/html/assets/app-settings/appsettings.json && find "/usr/share/nginx/html/assets/app-settings/" -type f -name "*.json" -not -name "appsettings.json" -exec rm {} ';' && exec nginx -g 'daemon off;'"
The command does three things:
- Copy environment specific appsettings.json (see below) as appsettings.json
- Delete all appsettings.xxx.json except appsettings.json
- Start nginx
The release process also replaces EnvironmentName with the specific environment it is deployed to. This means that each container now has an appsettings.json file with environment-specific data. In angular code, I only use environment files for environment independent information at compile time:
export const environment = { production: false };
Application settings are saved as assets:
To read the runtime information of appsettings.json, I created an appsettings provider service using a local http call:
@Injectable()
export class AppSettingsProviderService {
private appSettings: AppSettings;
public constructor(private http: LocalHttpService) {
}
public async provideAppSettingsAsync(): Promise<AppSettings> {
if (this.appSettings) {
return Promise.resolve(this.appSettings);
}
// This path needs to be relative to the files in the dist-folder
this.appSettings = await this.http.getAsync<AppSettings>('./assets/app-settings/appsettings.json');
return this.appSettings;
}
}
This also works during development, as in this case only appsettings.json is used and even when using ng serve the code compiles to dist, which means the relative path is still correct.
source to share