Running React App in Azure App Service Linux with Continuous Deployment
React is a Javascript library for building User Interface. I had multiple requests to write this blog on best way to run SPA(Single page applications) at Azure App Service Linux.
Check my previous blog for deploying SPA (Single Page Applications) in Azure App Service (Windows)@ https://prmadi.com/running-angular2-app-on-azure-app-services-with-ci-cd/
Azure App Service is a PAAS solution to run Enterprise-grade Web Applications. Azure has recently announced App Services on Linux. It supports running web apps natively on Linux using Docker Technology.
You can find a Sample React project with below operations @ GitHub Link
Requirements:
- VS Code (or any other good editor)
- Node.js installed on your machine
Create Sample React App
- I have used Create React App module to quickly create a sample react application.
> npm install -g create-react-app > create-react-app azure-demo > cd azure-demo
If you open azure-demo folder in VS code. It should look like below
Run it in Local env
> npm start
Output:
Add deployment script
In Azure App Service, there is a good feature to run a bash script after moving code to App service. Check below links for more info
- https://github.com/projectkudu/kudu/wiki/Custom-Deployment-Script
- https://prmadi.com/azure-custom-deployment/
Basically, We would add below two files in root folder
.deployment
: https://github.com/prashanthmadi/azure-react-sample/blob/master/.deploymentdeploy.sh
: https://github.com/prashanthmadi/azure-react-sample/blob/master/deploy.sh
Above mentioned links would have content of each file
what are we doing in custom deployment script(deploy.sh
) ?
After Content is moved from remote git repository to /home/site/repository
. we use deployment script to perform below actions
- Navigate to
/home/site/repository
folder - execute command
npm install
- execute command
npm run build
that creates/home/site/repository/build
folder - Kudu Sync, moves content from
/home/site/repository/build
folder to/home/site/wwwroot
Create Web App(Linux) in Azure Portal
- Click on below button and enter required details in portal
This would create Azure App service Linux and uses below nginx image Docker Hub : https://hub.docker.com/r/prashanthmadi/azure-appservice-nginx/
(or)
Note: You can ignore below steps if you used Deploy to Azure button above
- Navigate to portal and select “Web App for Containers”
- Set
prashanthmadi/azure-appservice-nginx:1.13
as Image
- set
WEBSITES_ENABLE_APP_SERVICE_STORAGE
totrue
in Application settings
Push your App to Azure
- If your app is on bitbucket/github/local git, follow content in below link to setup continuous deployment
https://docs.microsoft.com/en-us/azure/app-service-web/app-service-continuous-deployment
Final Output
You can find a Sample React project with above operations @ GitHub Link
Extra features
You can control nginx configuration used in app container by creating nginx.conf
file @ /home/site
folder
Ex: default root folder is set to /home/site/wwwroot
. You can change it to /home/site/wwwroot/build
by creating nginx.conf
file @ /home/site
with below content.
worker_processes auto;
pid /var/run/nginx.pid;
daemon off;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log off;
tcp_nopush on;
keepalive_timeout 65;
gzip on;
server {
listen 80;
server_name www.example.com;
error_log /home/LogFiles/error.log warn;
root /home/site/wwwroot/build;
index Default.htm Default.html index.html index.htm hostingstart.html;
# Make site accessible from http://localhost/
server_name _;
sendfile on;
location ~* \.(js|css|png|jpg|jpeg|gif|ico|mp3|html)$ {
expires 1d;
}
}
}
If you are using react/angular, make sure all your requests end up at index.html else you would receive 404 errors. Below is the sample for location that should do the trick.
location / {
try_files $uri /index.html;
add_header Cache-Control public;
expires 1d;
}