Skip to content

Complete stack to develop using NestJS, GraphQL, Redis, Docker, Kubernetes and Redis.

License

Notifications You must be signed in to change notification settings

tiagoboeing/nestjs-graphql-schemafirst-docker-k8s

Repository files navigation

NestJS + GraphQL Schema First (Complete stack)

NodeJS
NestJS GraphQL Docker Kubernetes Redis

This repository includes a full cycle NestJS stack to develop with containers:

  • NestJS + GraphQL Schema First (default application generated by @nestjs/cli) with some configurations:
    • class-validator package with middleware configured to show errors when input data don't matches with criteria's
    • nestjs-pino: replaces built-in Nest logger to register outputs using JSON syntax and easily allow to collect with ElasticSearch or tools like that.
    • Modules to work with Redis:
      • infra/redis-cache/redis-cache.module.ts: To use Redis as key/value, useful for cache functionality, needs cache-manager (already installed)
      • infra/redis-pubsub/redis-pubsub.module.ts: To use Redis as Pub/Sub
      • infra/redis-queue/redis-queue.module.ts: To use Redis as queue and execute async tasks
    • ms: Allow to easily convert values from string to milliseconds, like 1d, 1m, etc.
    • @golevelup/ts-jest: Allow to easily create mocks from providers and use them on tests
  • Dockerfile with multi-stage build and docker-compose to local development with live reload and debugger;
  • Redis (via Kubernetes with StatefulSet);
  • Dynatrace (via Kubernetes) - you will need to configure OneAgent following the DynaTrace docs;
  • Kubernetes deployments - application, ingress and service;
  • Docker Desktop StorageClass fix for Kubernetes (only when running locally);

GraphQL

The GraphQL includes:

Requirements

  • Node.js (v18);
  • Docker (with Docker Compose);
  • Kubernetes cluster (if you desire to use it);
  • DynaTrace account (if you desire to use it);

Configs

Environment variables are defined on:

See all available environment variables on environments.ts file.

Redis

The Redis auth credentials were changed to:

user default on +@pubsub ~* nopass
user admin on +@all ~* >adminpassword

Credentials:

Username Scope Password ACL (permissions)
default pubsub nopass (make it empty) +@read +@write +@list +@set +@string +@connection +@transaction +@stream +@pubsub +@scripting +@slow +@fast
admin all adminpassword +@all

Note: you can change the credentials in the redis-configmap.yaml file on these lines.

Local tests with Docker: to apply permissions on localhost, you will need to change the redis.conf on Docker folder too.

Key prefix

The keys stored on Redis for all modules (Queue, PubSub, Cache) will have a prefix to avoid conflicts with other applications. The value is defined on the REDIS_PREFIX environment variable. The default value is the value of name property on package.json file.

Resource/Module Key example
Cache/RedisCacheModule prefix:cache:key
Queue/RedisQueueModule prefix:key
PubSub/RedisPubSubModule prefix:key

DynaTrace

If you don't want to use DynaTrace, you can remove the opentelemetry.js file and will need to remove the Dockerfile excluding "--require", "./opentelemetry.js" on this line.

Workflow

Local development

You can start the application locally with:

# with Docker Compose
# -V remove volumes
# --build rebuild the images
docker-compose up --build -V

# You can specify the app port with SERVER_PORT (default will be 3000)
SERVER_PORT=4000 docker-compose up --build -V

# or simply with NodeJS
npm run start:dev

If you made changes on Redis container, run Docker Compose using --force-recreate to reload redis.conf file.

Docker Compose

To access services (like mocks) on host machine, you can simply use the DNS: host.docker.internal

Configuring environment variables

You can configure the environment variables in the file .env.

Note: the .env file will be used ONLY for local development. On production or another environment, you will need to change it via ConfigMap (if using K8S).

Execute without Docker Compose

You don't need to use Docker Compose to development, but using Redis you will need to install and configure it before.

Run Redis with Docker
# Create Docker network
docker network create redis

# Run Redis, attach network and expose port
docker run -d --rm --network redis --name redis -p 6379:6379 redis:6.2.3-alpine

In this case, running out of the Docker network the Redis Host (REDIS_HOST env) will be localhost or 127.0.0.1. Replace on the .env file.

Now you can simply start like any other NestJS app:

npm run start:dev

The advantage of use Docker to run all the stack is why all the configurations are made and the tunnel between the app and Redis will automatically defined. Redis host will be simply redis (Docker network name).

You can configure the environment variables in the file .env.

Note: the .env file will be used ONLY for local development. On production or another environment, you will need to change it via ConfigMap (if using K8S).

Build

On this repository we are using integration as the image name, but you can change it to whatever you want.

You can build the application with:

# Production build
# using multi-stage build
docker build --target production -t <image-name> .

Testing production image

docker run --rm -it -p 3000:3000 <image-name>

Kubernetes cluster

Firstly you will need to create a Kubernetes cluster. Use any engine, like K3D, MiniKube, Docker Desktop, etc.

You can get start (only at the first time) simply running:

# This command will create namespaces and apply deployments
sh ./infra/k8s/start-k8s-cluster.sh

Note: If you changed the Docker image name to other value (not integration), you will need to replace the K8S deployments with the new image.

Notes/links