Deploying Next.js on Azure

This guide is geared towards developers who are looking to use Microsoft Azure as a hosting environment for their Next.js website/application.

You will need a GitHub and an Azure account to get your project deployed.

Benefits

  • Supports getStaticProps (Static-site Generation) and getServerSideProps (Server-side Rendering)
  • Supports ISR (Incremental Static Regeneration) with revalidate tag
  • Supports Preview Mode

Set Up the Instance

Sign Up for a Free Agility CMS account to gain access to an Instance.

Once you've created an account, you will be able to create a new Instance based off of the Blog Starter with Next.js.

Set Up Your Local Environment

Once logged into Agility CMS, you'll want to grab your API credentials so your Next.js site can authenticate and retrieve data from your instance.

From your Agility CMS dashboard, click into Settings > API Keys.

Take note of your GUIDLive API KeyPreview API Key and Security Key credentials and copy these somewhere temporarily as you'll need to use them later.

Get The Code

  1. Clone a copy of the Next.js Blog Starter repository and open it in your favourite Text Editor.
  2. Run yarn install to install the required packages and dependencies

Set up Authentication

  1. Rename the .env.local.example file to .env.local
  2. Place the GUIDLive API KeyPreview API Key and Security Key Values into your .env.local file
# Your Instance ID
AGILITY_GUID=

# Your Live API Key
AGILITY_API_FETCH_KEY=

# Your Preview API Key
AGILITY_API_PREVIEW_KEY=

# Your Security Key
AGILITY_API_SECURITY_KEY=

Create a Server

In the root of the project, create a server.js file with the following code:

const { createServer } = require("http");
const next = require("next");

const port = process.env.PORT || 3000;
const dev = false;
const app = next({ dev });
const handle = app.getRequestHandler();

app.prepare().then(() => {
  createServer((req, res) => {
    handle(req, res);
  }).listen(port, (err) => {
    if (err) throw err;
    console.log(`> Ready on <http://localhost>:${port}`);
  });
});

Start the Site

To ensure everything is working as expected, run the site locally. To start the site, run npm run dev or yarn dev to start up your development server. If successful, Next.js will compile your pages in real-time and you will be able to access the site in your browser on https://localhost:3000

Did you get a Build Error?

If you get an error during the build, check your log and ensure that you've entered the correct GUID and API Keys, as well as renamed the env.local.example file to .env.local.

Create a Repository

Create a new repository on your GitHub account and check in the updates we've made so far.

git init
git commit -m "first commit"
git branch -M main
git remote add origin git@github.com:joshua-isaac/agility-nextjs-azure.git
git push -u origin main

Deploy to Azure

In Azure, select your Subscription and create a new Resource

Create a Web App

Basics

Fill out your project details by selecting your Subscription and Resource Group (or create new)

Next, fill out your Instance details, for this tutorial we'll be using the following configuration:

  • Publish: Code
  • Runtime Stack: Node 14
  • Operating System: Windows
  • Region: Central US

Lastly, select your App Service Plan, for this tutorial we'll be using a Free Plan.

When you've entered your details, click on Next: Deployment.

Deployment

For our deployment we'll be using GitHub Actions, which is an automation framework that can build, test, and deploy your app whenever a new commit is made in your repository.

Connect to your GitHub account, then select your Organization, the Repository you created earlier, and select the Main branch.

When you're done, click on Review + create.

In the Deployment Center, click on Logs, then click on the current Build/Deployment. You will notice that GitHub Actions have been added to your pipeline.

The initial build will fail, as we need to add our Keys from Agility to our GitHub Actions.

In your Repository, click on Settings > Secrets > New Repository Secret to add your Agility CMS Credentials

AGILITY_GUID=
AGILITY_API_FETCH_KEY=
AGILITY_API_PREVIEW_KEY=
AGILITY_API_SECURITY_KEY=
AGILITY_LOCALES=en-us
AGILITY_SITEMAP=website

Pull the latest changes from your GitHub repository to your local machine:

git pull

You will notice a new .github/workflows directory with a .yml configuration file. Open the .yml file and add your Environment Variables to the Build Step:

  build:
    runs-on: windows-latest

    steps:
      - uses: actions/checkout@v2

      - name: Set up Node.js version
        uses: actions/setup-node@v1
        with:
          node-version: "14.x"

      - name: npm install, build, and test
        run: |
          npm install
          npm run build --if-present
          npm run test --if-present

        env:
          AGILITY_GUID: ${{ secrets.AGILITY_GUID }}
          AGILITY_API_FETCH_KEY: ${{ secrets.AGILITY_API_FETCH_KEY }}
          AGILITY_API_PREVIEW_KEY: ${{ secrets.AGILITY_API_PREVIEW_KEY }}
          AGILITY_SECURITY_KEY: ${{ secrets.AGILITY_SECURITY_KEY }}
          AGILITY_LOCALES: ${{ secrets.AGILITY_LOCALES }}
          AGILITY_SITEMAP: ${{ secrets.AGILITY_SITEMAP }}

      - name: Upload artifact for deployment job
        uses: actions/upload-artifact@v2
        with:
          name: node-app
          path: .

Push the changes back to GitHub:

git add .
git commit -m "updated .yml"
git push

Your site will re-build and re-deploy using the new secrets you've configured.

Configuration

You will also want to set up the same environment variables within your App Service Configuration. To do this, head to Configuration and add new application settings:

Log Stream

You may find using the Log Stream within your App Service useful when debugging.

Using Docker

Docker is a containerization technology that allows you to package your application and all development dependencies into a container.

A few of the many benefits are:

  • Docker enables more efficient use of system resources
  • Docker enables faster software delivery cycles
  • Docker enables application portability
  • Great for microservice architectures
  • Package your application and environments to run anywhere

How to Dockerize your Project

Before your start, make sure you have Docker installed locally on your machine.

Getting Started with Docker

At the root of your project, create a file named Dockerfile:

FROM node:14

# Create app directory
WORKDIR /app

# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json ./

RUN npm install

# Bundle app source
COPY . .

RUN npm run build

EXPOSE 3000
CMD ["npm","run","start"]

Azure DevOps

With the use of Azure Dev Ops (azure-pipelines.yml) and Docker (Dockerfile), you can use Docker to build an image, and then push it to the Azure Container registry of your choice. An Azure App Service that you set up would simply use the Registry to enable Continuous Deployment.

azure-pipelines.yml:

# Docker
# Build a Docker image 
# https://docs.microsoft.com/azure/devops/pipelines/languages/docker

trigger:
- master

resources:
- repo: self

variables:
  tag: '$(Build.BuildId)'

stages:
- stage: Build
  displayName: Build image
  jobs:  
  - job: Build
    displayName: Build & Deploy all Environments (sample)
    pool:
      vmImage: 'ubuntu-latest'
    steps:
    - task: Docker@2
      displayName: 'Build and Push Preview Env'
      inputs:
        containerRegistry: '$(containerRegistry)'
        repository: '$(containerRepository)'
        command: 'buildAndPush'
        Dockerfile: '**/Dockerfile'
        tags: 'latest'