J'ai besoin de trouver un moyen de déployer une application Angular dynamiquement, de sorte que la même image docker me permette de faire plusieurs déploiements (développement, staging, production) dans lesquels l'URL d'accès est modifiée.
Je réalise une application en Angular 7 en utilisant Angular-cli 6.4.1. Pour le déploiement, je crée un conteneur docker multistage où je construis l'image et la configure avec nginx.
Le problème est que pour le déploiement, nous utilisons un registre privé dans lequel nous utilisons un proxy qui gère les redirections, de sorte que mon application serait déployée selon le schéma : {SERVER_HOST} : {PORT} / {SERVER_LOCATION}
Lorsque j'essaie d'accéder à cette URL, seul le fichier index.html est chargé, puisque le reste des ressources est associé au chemin de base "/".
Angular fournit un argument dans le build (--base-href) qui permet de modifier le chemin de l'application entière, cependant cela ne m'aide pas puisque j'ai besoin de la même image Docker pour me permettre d'effectuer différents déploiements afin que le paramètre {SERVER_LOCATION} ne soit pas toujours le même.
J'ai également essayé de lire les variables d'environnement au moment de l'exécution pour modifier l'attribut href de la balise de base, mais il est difficile d'exécuter un code qui se trouve dans un fichier qui n'est pas chargé à côté de l'index.
Comme solution de contournement, j'ai décidé de créer une fonction dans l'index qui exécute une requête ajax qui collecte les paramètres de configuration afin de charger le reste des ressources, mais je n'aime pas cela car cela casse le fonctionnement d'Angular.
<-- This is working fine, but is not dynamic: -->
npm run build -- --prod --base-href https://myHost.net:8080/path/app/ --configuration=$configuration
<-- And this is working but is not Angular friendly -->
/** assets/data/appConfig.json */
{
"SERVER_HOST": "https://myHost.net:8080",
"SERVER_PATH": "/path/app/"
}
/** index.html */
<script>
(function() {
if (window.onerror) {
loadConfig();
}
function loadConfig() {
var xhttp = new XMLHttpRequest();
var url = 'assets/data/appConfig.json';
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var data = JSON.parse(this.response);
window.appBaseHref = data.SERVER_PATH;
document.getElementById("base").href = data.SERVER_PATH;
}
};
xhttp.open('GET', url);
xhttp.send();
}
})()
</script>
On m'a dit qu'il y avait une option pour sauter le proxy, mais je ne trouve pas le moyen de le faire, je ne sais pas comment le configurer. Je pense qu'il y a peut-être un ajustement à faire dans le fichier de configuration de nginx pour que l'application "lise" à partir de l'URL fournie et que le href de base de l'application soit toujours "/".
Actuellement mon fichier nginx.conf est :
server {
listen 80;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html =404;
}
location /documentation {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /documentation/index.html =404;
}
}
Où le chemin d'emplacement '/' est mon application angulaire et le chemin d'emplacement '/documentation' est le chemin réservé pour la documentation du projet.
Toute aide sera la bienvenue.
<--- Editer --->
Ces derniers jours, j'ai essayé plusieurs choses, et la vérité est que je ne sais pas trop comment continuer, puisque rien ne semble fonctionner.
J'ai configuré Nginx pour ajouter la propriété env $uri+$basepath, mais je me rends compte que la relation est exactement l'inverse. J'ai besoin que mon index.html fasse des requêtes vers la route du proxy au lieu du chemin '/', parce qu'à cause de cela, la requête n'entre même pas dans le log (le proxy ne me redirige pas parce qu'il n'a pas le préfixe de mon application).
Je vous donne un exemple : Mon application est hébergée sur : myHost:8080/myapp/front Lorsque j'entre cette url (myHost:8080/myapp/front), l'application charge l'index, mais les ressources associées (styles, runtime, polyfills, scripts et main) ne sont pas chargées parce qu'elles envoient la requête à : myHost:8080/{resourcePath} au lieu de myHost:8080/myapp/front/{resourcePath}.
À ce stade, je ne sais pas où aller. Je serais capable d'obtenir le résultat que je veux en mettant le flag --base-href /myapp/front, mais je veux que cette route soit dynamique et dépende de ma variable d'environnement du système VIRTUAL_HOST, que bien sûr je ne connais pas au moment de la construction de l'application.
Ensuite, je colle mon fichier docker et le fichier de configuration nginx.
Dockerfile (Les lignes commentées sont les propositions qui n'ont pas fonctionné de la manière attendue).
### STAGE 0: Based on Node.js, to build and compile Angular ###
FROM node:alpine as node
# Create app directory
WORKDIR /app
# Copy the dependencies to install once and let Docker use the cache for the next builds
COPY package*.json /app/
# Install all dependencies
RUN npm install
# Copy all the project into the image
COPY ./ /app/
# Argument to build the image according to the environment
ARG configuration=production
# Compiles our project
RUN npm run build -- --prod --configuration=$configuration
### STAGE 1: Based on Nginx, to have only the compiled app, ready for production with Nginx ###
FROM nginx:1.13.3-alpine
## Remove default nginx website
RUN rm -rf /usr/share/nginx/html/*
## From 'builder' stage copy over the artifacts in dist folder to default nginx public folder
COPY --from=node /app/dist/dsa-frontend /usr/share/nginx/html
# Add directive
# COPY nginx-custom.conf.template /etc/nginx/conf.d/default.conf.template
COPY nginx-custom.conf /etc/nginx/conf.d/default.conf
# CMD /bin/bash -c "envsubst '\$VIRTUAL_SERVICE_LOCATION' < nginx-custom.conf > /etc/nginx/conf.d/default.conf"
CMD ["nginx", "-g", "daemon off;"]
nginx-custom.conf
server {
listen 80;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /myapp/front$uri /myapp/front$uri/;
# try_files $uri $uri/ $uri$VIRTUAL_SERVICE_LOCATION $uri$VIRTUAL_SERVICE_LOCATION/ /index.html;
}
location /documentation {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /documentation/index.html =404;
}
}
Mais rien de tout cela ne semble fonctionner.
Enfin, nous avons pris la décision de supprimer le développement du proxy et d'ouvrir un nouveau port pour déployer cette application, de sorte que le chemin racine est désormais "/".
Et maintenant, tout fonctionne bien.