We\'recurrently setting up an SPA with Angular 4, hosting it with Docker on Azure. Usually, the environments (Prod, Development, Testing) are set in Angular with the Environment
Since my main goal was to not create a Container per environment but also to keep the build process environment-agnostic, I came up with the following solution: I'm using the docker-stack file to add a 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:
The release process also replaces EnvironmentName with the specific environment it is deploying to. This means, each container has now an appsettings.json in place with the environment-specific data. On the angular code, I'm using the environment-files just for compile-time, environment-agnostic, information:
export const environment = {
production: false
};
The appsettings are saved as assets:
To read the runtime information of appsettings.json, I've created a 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 works also during development, since just the appsettings.json is used in this case and even with ng serve, the code is compiled into dist, meaning the relative path is still correct.