Azure Container Apps for Micro Frontend
This will be our app's initial setup
In the pre-Azure changes, 8081 was the port for remote-app and 8080 for host-app as seen from here
GITHUB
Deploying this on Azure as a Container App.
Note:- Docker is like a ready-to-eat meal—it’s already cooked and packed, so you can take it anywhere.
- Azure Container Registry (ACR) is like a fridge where you store your meal until you need it.
- Azure Container Apps (ACA) is like a microwave or chef that heats it up and serves it when you're ready to eat.
So, Docker preps the meal, ACR stores it, and ACA serves it hot when needed!
As soon as you prep a meal, first store it first in the ACR fridge. And then serve it on need basis from ACA
Docker
If you think about the application lifecycle—setting up the environment, adding the package.json file, installing dependencies, bringing in your code, building it, and finally running the application—you simply write these steps in an organized way inside a Dockerfile. This ensures everything happens in the correct order automatically.
In our example we have 2 apps that run
Both these apps need their own Docker file./host-app/Dockerfile
FROM node:16-alpine
#STEP 1: Set the working directory
WORKDIR /app
#STEP 2: Copy package.json into the working directory
COPY package*.json ./
#STEP 3: Install dependencies
RUN npm install
#STEP 4: Copy the rest of the applciation
COPY . .
#Step 5: Build
RUN npm run build
#STEP 6: Expose the port app runs on
EXPOSE 8080
#STEP 6: WEBPACK SERVE
CMD ["npx", "webpack", "serve", "--host", "0.0.0.0"]
And the same contents go inside remote-app/Dockerfile (but port will be 8081)
Navigate to ./remote-app on command prompt
2. docker run -p <host machine's port> (your computer>:<container's port (inside the Docker container)> <image-name>:<tag-version>
- docker build -f Dockerfile -t remote-app:v1 .
- here the v1 is the tag version. You can keep incrementing for every buil
- The
.at the end tells Docker to use the current directory as the build context. - The context includes all files and directories inside this location, which might be required for the build process.
2. docker run -p 8081:8081 remote-app:v1
Repeat the same for host-app, but for port 8080
Azure
1. Creating a Resource group
2. Creating Container Registry
My Resource group: my-microFE-resourceGroup
My Container Registry: mymicrofeacr
Remote URL:
Host URL:
These are going to be my remote and host URLs. You will not know them before hand. But placing it here because we need to update the "public path" in both the webpacks. There is no "localhost" anymore.
3. Update Webpack
This is how the final webpack looks with the Azure URLsalso update the "devServer" as below
remote-app/webpack.config.js
const path = require("path");
const { ModuleFederationPlugin } = require("webpack").container;
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: "development",
entry: "./remoteModuleIndex.js",
output: {
publicPath: "https://mymicrofecontainerapp.salmonground-5ff0b0fe.westus2.azurecontainerapps.io/",
filename: "bundle.js",
path: path.resolve(__dirname, "dist"),
},
plugins: [
new ModuleFederationPlugin({
name: "remoteApp",
filename: "remoteModuleIndex.js",
exposes: {
"./Module": "./remoteModuleIndex.js",
},
}),
new HtmlWebpackPlugin({
template: './index.html', // Use our own template
filename: 'index.html' // Output file
})
],
devServer: {
port: 8081,
host: "0.0.0.0", // Allow external access from the container
allowedHosts: "all", // Allow all host headers
static: path.join(__dirname, "dist"),
},
};
host-app/webpack.config.js
const path = require("path");
const { ModuleFederationPlugin } = require("webpack").container;
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: "development",
entry: "./index.js",
output: {
publicPath: "https://mymicrofecontainerhostapp.salmonground-5ff0b0fe.westus2.azurecontainerapps.io/",
filename: "bundle.js",
path: path.resolve(__dirname, "dist"),
},
plugins: [
new ModuleFederationPlugin({
name: "hostApp",
remotes: {
remoteApp: "remoteApp@https://mymicrofecontainerapp.salmonground-5ff0b0fe.westus2.azurecontainerapps.io/remoteModuleIndex.js",
},
}),
new HtmlWebpackPlugin({
template: './index.html', // Use our own template
filename: 'index.html' // Output file
})
],
devServer: {
port: 8080,
host: "0.0.0.0", // Allow external access from the container
allowedHosts: "all", // Allow all host headers
static: path.join(__dirname, "dist"),
},
};
4. Create Container app
5. Create your own environment if needed
- My resource group: my-microFE-resourceGroup
- My Container Registry: mymicrofeacr
- My Container app name: mymicrofecontainerapp
- My Container app name for host: mymicrofecontainerhostapp
- My Container App Environment: mymicrofeenvironment
6. Let us now login to Azure Container Apps:
az acr login --name mymicrofeacr
az acr update --name mymicrofeacr --admin-enabled true
7. Build & Push Docker Images to ACR.
In your command prompt,/remote-app/
docker build -f Dockerfile -t remote-app:v1 .
/host-app/
docker build -f Dockerfile -t remote-app:v1 .
/host-app/
docker build -f Dockerfile -t host-app:v1 .
docker tag remote-app:v1 mymicrofeacr.azurecr.io/remote-app:v1
docker tag host-app:v1 mymicrofeacr.azurecr.io/host-app:v1
docker push mymicrofeacr.azurecr.io/remote-app:v1
docker push mymicrofeacr.azurecr.io/host-app:v1
8. Deploy
Now that we have pushed an image to the Container Registry, we will navigate to the "Container Apps > Containers > Edit & deploy "9. Verify!
it will take a while to deploy. You can now go to the "overview" tab of the container. Here you get your application URL where the app is deployedHost App
These were the PR changes made for to upgrade our Micro Front-End App
https://github.com/Kavshree/moduleFederation-MicroFE/pull/8
PUSHING UPDATES TO THE CODE
Make sure you are logged in to acraz acr login --name mymicrofeacr
az acr update --name mymicrofeacr --admin-enabled true
docker build -f Dockerfile -t remote-app:v2 .
docker build -f Dockerfile -t host-app:v2 .
docker tag remote-app:v4 mymicrofeacr.azurecr.io/remote-app:v2
docker tag host-app:v4 mymicrofeacr.azurecr.io/host-app:v2
docker push mymicrofeacr.azurecr.io/remote-app:v2
docker push mymicrofeacr.azurecr.io/host-app:v2
Navigate to the container app and edit the image version to the new version pushed
Navigate to the container app and edit the image version to the new version pushed
USING ENVIRONMENT VARIABLES
Now since the public path is updated, in order to work on our local changes, we need to revert it back without affecting the excising configs.remote-app/webpack.config.js
host-app/webpack.config.js
const path = require("path");
const { ModuleFederationPlugin } = require("webpack").container;
const HtmlWebpackPlugin = require('html-webpack-plugin');
const remoteURL = process.env.REMOTE_URL || "http://localhost:8081/";
console.log("Configured REMOTE_URL env variable: ", process?.env?.REMOTE_URL);
/* To configure the below environment variables in Azure Container
REMOTE_URL
https://mymicrofecontainerapp.salmonground-5ff0b0fe.westus2.azurecontainerapps.io
HOST_URL:
https://mymicrofecontainerhostapp.salmonground-5ff0b0fe.westus2.azurecontainerapps.io
**/
module.exports = {
mode: "development",
entry: "./remoteModuleIndex.js",
output: {
publicPath: remoteURL,
filename: "bundle.js",
path: path.resolve(__dirname, "dist"),
},
plugins: [
new ModuleFederationPlugin({
name: "remoteApp",
filename: "remoteModuleIndex.js",
exposes: {
"./Module": "./remoteModuleIndex.js",
},
}),
new HtmlWebpackPlugin({
template: './index.html', // Use our own template
filename: 'index.html' // Output file
})
],
devServer: {
port: 8081,
host: "0.0.0.0", // Allow external access from the container
allowedHosts: "all", // Allow all host headers
static: path.join(__dirname, "dist"),
},
};
host-app/webpack.config.js
const path = require("path");
const { ModuleFederationPlugin } = require("webpack").container;
const HtmlWebpackPlugin = require('html-webpack-plugin');
const hostURL = process.env.HOST_URL || "http://localhost:8080/";
const remoteURL = process.env.REMOTE_URL || "http://localhost:8081/";
console.log("Configured HOST_URL env variable: ", process?.env?.HOST_URL);
console.log("Configured REMOTE_URL env variable: ", process?.env?.REMOTE_URL);
/* To configure the below environment variables in Azure Container
REMOTE_URL
https://mymicrofecontainerapp.salmonground-5ff0b0fe.westus2.azurecontainerapps.io
HOST_URL:
https://mymicrofecontainerhostapp.salmonground-5ff0b0fe.westus2.azurecontainerapps.io
**/
module.exports = {
mode: "development",
entry: "./index.js",
output: {
publicPath: hostURL,
filename: "bundle.js",
path: path.resolve(__dirname, "dist"),
},
plugins: [
new ModuleFederationPlugin({
name: "hostApp",
remotes: {
remoteApp: `remoteApp@${remoteURL}remoteModuleIndex.js`,
},
}),
new HtmlWebpackPlugin({
template: './index.html', // Use our own template
filename: 'index.html' // Output file
})
],
devServer: {
port: 8080,
host: "0.0.0.0", // Allow external access from the container
allowedHosts: "all", // Allow all host headers
static: path.join(__dirname, "dist"),
},
};


Comments
Post a Comment