Integrate with Node.js

This page details steps needed to successfully integrate Node.js applications with Magnolia PaaS.

Magnolia application repository

Modify the Ingress configuration

To allow the splitting of requests between Node.js and Magnolia, the Ingress configuration needs to be altered in the file values.yaml in repository of the webapp.

values.yaml
# Values for Magnolia Helm Chart
ingress:
  annotations:
  hosts:
    - host: mgnl-author.{{ .Env.DEPLOYMENT }}.[project-name].magnolia-platform.com
      paths:
        - path: /
          instance: author
    - host: frontend-author.{{ .Env.DEPLOYMENT }}.[project-name].magnolia-platform.com
      paths:
        - path: /
          instance: frontend-author
    - host: mgnl-public.{{ .Env.DEPLOYMENT }}.[project-name].magnolia-platform.com
      paths:
        - path: /
          instance: public
    - host: frontend-public.{{ .Env.DEPLOYMENT }}.[project-name].magnolia-platform.com
      paths:
        - path: /
          instance: frontend-public
  tls:
    - hosts:
        - mgnl-author.{{ .Env.DEPLOYMENT }}.[project-name].magnolia-platform.com (1)
        - frontend-author.{{ .Env.DEPLOYMENT }}.[project-name].magnolia-platform.com
        - mgnl-public.{{ .Env.DEPLOYMENT }}.[project-name].magnolia-platform.com
        - frontend-public.{{ .Env.DEPLOYMENT }}.[project-name].magnolia-platform.com
1 The first domain listed in tls.hosts can only be a maximum 63 characters long.

You can use dummy domains like a.[project-name].magnolia-platform.com.

Subdomains (e.g. mgnl-author) and pathnames in hosts URLs can be changed.

Dockerize the frontend application

Dockerize your SPA application.

Below you can see example of Dockerizing React SPA and serving it with http-server application.

You can find more examples here.
frontend application repository
frontend-application-repository
...
└── spa (1)
└── http-server (2)
...
1 Folder with React SPA.
2 Folder with http-server application.
Dockerfile
FROM node:16 as dependencies (1)
WORKDIR /app
COPY http-server/package.json ./
COPY http-server/package-lock.json ./
RUN npm install

FROM node:16 as builder (2)
ARG ENV_VARIABLE_1
ENV REACT_APP_ENV_VARIABLE_1=$ENV_VARIABLE_1
WORKDIR /app
COPY spa/package.json ./
COPY spa/package-lock.json ./
RUN npm install
COPY spa ./
RUN npm run build

FROM node:16 as runner (3)
WORKDIR /app
COPY --from=dependencies /app/package.json ./package.json (4)
COPY --from=dependencies /app/node_modules ./node_modules (5)
COPY --from=builder /app/build ./public (6)
EXPOSE 3000 (7)
CMD ["npm", "start"] (8)
1 Stage to install http-server dependencies.
2 Stage to build React SPA.
3 Prepare the final image.
4 Copy package.json from dependencies stage to be used by http-server.
5 Copy node_modules from dependencies stage to be used by http-server.
6 Copy build files of React SPA to public folder, from which http-server serves the files.
7 Expose the port on which Node.js application is listening.
8 Start the Node.js application.

The .gitlab-ci.yml file

We need to extend CI/CD configuration with jobs to prepare and deploy the Node.js application image.

For CI/CD pipelines with runners hosted on k8s jobs that build Docker images, you must use the kaniko tool.

Check out this example on how to adjust your job.

.gitlab-ci.yml
stages:
  - prepare
  - deploy

# Prepare the frontend app
prepare:build-node-js-docker-image:
  stage: prepare
  image: 'docker:20'
  before_script:
    - apk add --no-cache git
    - git --version
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
    - export GIT_TAG=$(git describe --always) (1)
    - export DOCKER_BUILDKIT=1
    - export MAGNOLIA_DOCKER_AUTHOR=$CI_REGISTRY_IMAGE/author
    - export MAGNOLIA_DOCKER_PUBLIC=$CI_REGISTRY_IMAGE/public
  script:
    - docker build --pull -t "$MAGNOLIA_DOCKER_AUTHOR:$GIT_TAG" --build-arg ENV_VARIABLE_1=$ENV_VARIABLE_1 . (2)
    - docker push "$MAGNOLIA_DOCKER_AUTHOR:$GIT_TAG"
    - docker build --pull -t "$MAGNOLIA_DOCKER_PUBLIC:$GIT_TAG" --build-arg IS_PUBLIC=true --build-arg ENV_VARIABLE_1=$ENV_VARIABLE_1 .
    - docker push "$MAGNOLIA_DOCKER_PUBLIC:$GIT_TAG"
  rules:
    - if: $CI_COMMIT_BRANCH == "develop"
      variables:
        ENV_VARIABLE_1: foo
    - if: $CI_COMMIT_BRANCH == "master"
      variables:
        ENV_VARIABLE_1: bar

# Deploy the frontend app to the frontend pods
deploy:sync-node-js:
  stage: deploy
  image: registry.magnolia-platform.com/developers-artifact/spa-nodejs:1.0.2
  environment:
    name: $NAME
  before_script:
    - export KUBECTL_NAMESPACE=$NAME (3)
    - export MAGNOLIA_RELEASE=$NAME
    - export GIT_TAG=$(git describe --always)
    - export MAGNOLIA_DOCKER_AUTHOR=$CI_REGISTRY_IMAGE/author (4)
    - export MAGNOLIA_DOCKER_PUBLIC=$CI_REGISTRY_IMAGE/public
    - export MAGNOLIA_FRONTEND_PORT="3000"
    - export MAGNOLIA_FRONTEND_CPU="200m"
    - export MAGNOLIA_FRONTEND_MEMORY="1Gi"
    - export MAGNOLIA_FRONTEND_AUTHOR_REPLICAS="1" (5)
    - export MAGNOLIA_FRONTEND_PUBLIC_REPLICAS="2" (6)

  script:
    - cd /k8s/base
    - envsubst < kustomization-template.yaml > kustomization.yaml ; kustomize build .
    - kubectl -n $NAME apply -k . (7)
  rules:
    - if: $CI_COMMIT_BRANCH == "develop"
      variables:
        NAME: integration
    - if: $CI_COMMIT_BRANCH == "master"
      variables:
        NAME: prod
1 The GIT_TAG is used to set the tag for the created Docker image.
2 Build the image.
3 Export the environment variables used to customize the Kubernetes deployment.
4 You can specify different images for author and public.
5 Default number of frontend author replicas.
6 Default number of frontend public replicas.
7 Build the Kubernetes deployment files and apply them to the Kubernetes cluster.

CDN

The CDN uses cache headers coming from Node.js app.

Feedback