Walkthrough - revant/xkcd-proxy-monorepo GitHub Wiki

Backend

npm i lerna @nestjs/cli -g
mkdir xkcd-proxy-monorepo
cd xkcd-proxy-monorepo
lerna init -i
cd packages
nest new xkcd-proxy-server
cd xkcd-proxy-server && npm i xkcd --save
code .

Change code

// ... AppService
import * as xkcd from 'xkcd';
// ...
  getXkcd(res) {
    xkcd(data => res.json(data));
  }
// ... AppController, 
// note: import Res from nestjs
  @Get('xkcd')
  xkcd(@Res() res) {
    this.appService.getXkcd(res);
  }
// ... main.ts
  await app.listen(8000);

Run Tests and Checks

npm run format -- -c
npm run lint
npm run test
npm run test:e2e

Create Docker Entry Point Script (in docker/ directory of xkcd-proxy-server root) and make it executable chmod +x docker-entrypoint.sh

#!/bin/bash

if [ "$1" = 'start' ]; then
  su digithinkit -c "node dist/main.js"
fi

exec runuser -u digithinkit "$@"

Place .dockerignore

node_modules
dist

Place Dockerfile

FROM node:latest
# Copy app
COPY . /home/digithinkit/xkcd-proxy
WORKDIR /home/digithinkit/
RUN cd xkcd-proxy \
    && npm install \
    && npm run prestart:prod \
    && rm -fr node_modules \
    && npm install --only=production

FROM node:slim
# Setup docker-entrypoint
COPY docker/docker-entrypoint.sh usr/local/bin/docker-entrypoint.sh
RUN ln -s usr/local/bin/docker-entrypoint.sh / # backwards compat

# Add non root user
RUN useradd -ms /bin/bash digithinkit
WORKDIR /home/digithinkit/xkcd-proxy
COPY --from=0 /home/digithinkit/xkcd-proxy .

RUN chown -R digithinkit:digithinkit /home/digithinkit

# set project directory
WORKDIR /home/digithinkit/xkcd-proxy

# Expose port
EXPOSE 8000

ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["start"]

Build and try image

cd ../../ # from root of monorepo
docker build -t xkcd-proxy-backend packages/xkcd-proxy-server
docker run --name xkcd_proxy_backend -d -p "8000:8000" xkcd-proxy-backend:latest

Frontend

cd packages # change to monorepo-root/packages
npm i nwb -g
nwb new react-app xkcd-proxy-client
cd xkcd-proxy-client
npm i
npm run test
npm run build

Change App.js

// Edit UI to show result of `GET /xkcd` 

Place docker/nginx.conf

upstream nodejs {
    server localhost:8000;
}

server {
    listen 8080;
    server_name localhost;
    root /var/www/html;

    location ~* ^/(xkcd) {
        try_files $uri $uri/ @nodejs;
    }

    location / {
        try_files $uri $uri/ /index.html;
    }

    location @nodejs {
        proxy_redirect off;
        proxy_http_version 1.1;
        proxy_pass http://nodejs;
        proxy_set_header Host $host ;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

Place .dockerignore

node_modules
dist

Place Dockerfile

FROM node:latest
# Copy app
COPY . /home/digithinkit/xkcd-proxy-client
WORKDIR /home/digithinkit/
RUN cd xkcd-proxy-client \
    && npm install \
    && npm run build

FROM nginx:latest
COPY --from=0 /home/digithinkit/xkcd-proxy-client/dist /var/www/html
COPY ./docker/nginx.conf /etc/nginx/conf.d/xkcdproxy.conf

Build and try image

# from monorepo root
docker build -t xkcd-proxy-frontend packages/xkcd-proxy-client
docker run --name xkcd_proxy_frontend -d -p "8080:8080" xkcd-proxy-frontend:latest

Drone Pipe-line

kind: pipeline
name: default

steps:
- name: test-backend
  group: tests
  image: node:latest
  commands:
  - cd packages/xkcd-proxy-server
  - npm install
  - npm run format -- -c
  - npm run lint
  # Set environment to test
  - export NODE_ENV=test
  - npm run test
  - npm run test:e2e

- name: test-frontend
  group: tests
  image: node:latest
  commands:
  - cd packages/xkcd-proxy-client
  - npm install
  - npm run test

- name: build-backend
  image: plugins/docker
  settings:
    repo: bloomstack/xkcd-proxy-server
    username:
      from_secret: docker_username
    password:
      from_secret: docker_password
    dockerfile: packages/xkcd-proxy-server/Dockerfile
    context: packages/xkcd-proxy-server
    tags:
      - edge
  when:
    event:
      - push
    branch:
      - staging

- name: build-frontend
  image: plugins/docker
  settings:
    repo: bloomstack/xkcd-proxy-client
    username:
      from_secret: docker_username
    password:
      from_secret: docker_password
    dockerfile: packages/xkcd-proxy-client/Dockerfile
    context: packages/xkcd-proxy-client
    tags:
      - edge
  when:
    event:
      - push
    branch:
      - staging

Helm chart CD (Part 2)