Backend Development Plan


In this article, we'll guide you through our backend development plan, focusing on three key areas to ensure a smooth setup with Docker:
  • Framework Choice: We selected NestJS as our framework because it's efficient and scalable, perfect for building a solid foundation.
  • User Authentication: We're using Keycloak to manage user roles effectively, ensuring secure and streamlined access for all users.
  • Containerization: To make everything run smoothly, we'll be dockerizing our backend. Docker helps maintain consistency across environments, simplifying development, deployment, and scaling.
Smooth Docker

Project setup

I started by creating a project directory and setting up a Docker environment for the application. Despite limited Docker experience, I successfully configured the containers and got the app running. Below are the steps I followed.

Creating the Dockerfile

First, I created a Dockerfile with the following content:
# Use the official Node.js image
FROM node:20-alpine

# Set the working directory
WORKDIR /usr/src/app

# Copy package.json and package-lock.json
COPY app/package*.json ./

# Install dependencies
RUN npm install

# Copy the rest of the application code
COPY app .

# Expose the application port
EXPOSE 3000

# Command to run the application
CMD ["npm", "run", "start:dev"]
This Dockerfile pulls an official Node.js image, sets the working directory, installs the necessary dependencies, and finally copies the application code. The application is then exposed on port 3000.

Creating Docker-compose

Next, I created a docker-compose.yaml file to manage the services, with the following content:
services:
  postgres:
    image: postgres:16.3
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    networks:
      - keycloak_network

  keycloak:
    image: quay.io/keycloak/keycloak:25.0.2
    command: start-dev
    environment:
      KC_HOSTNAME: localhost
      KC_HOSTNAME_PORT: 8080
      KC_HOSTNAME_STRICT_BACKCHANNEL: false
      KC_HTTP_ENABLED: true
      KC_HOSTNAME_STRICT_HTTPS: false
      KC_HEALTH_ENABLED: true
      KEYCLOAK_ADMIN: ${KEYCLOAK_ADMIN}
      KEYCLOAK_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD}
      KC_DB: postgres
      KC_DB_URL: jdbc:postgresql://postgres/${POSTGRES_DB}
      KC_DB_USERNAME: ${POSTGRES_USER}
      KC_DB_PASSWORD: ${POSTGRES_PASSWORD}
      KC_LOG_LEVEL: DEBUG # development
    ports:
      - 8080:8080
    restart: always
    depends_on:
      - postgres
    networks:
      - keycloak_network


  pgadmin:
    image: dpage/pgadmin4:latest
    environment:
      PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL}
      PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD}
    ports:
      - 5050:80
    depends_on:
      - postgres
    networks:
      - keycloak_network

  app:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - ./app:/usr/src/app # used for hot reloading only in development
    ports:
      - 3000:3000
    depends_on:
      - postgres
    networks:
      - keycloak_network
    environment:
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_HOST: postgres

volumes:
  postgres_data:
    driver: local

networks:
  keycloak_network:
    driver: bridge
This configuration defines multiple services: PostgreSQL for database management, Keycloak for authentication, pgAdmin for database administration, and the application itself. The services are connected via a shared Docker network, keycloak_network, and necessary environment variables are defined to maintain security and flexibility.

Creating .env file

To manage sensitive information and configuration settings, I created a .env file. This file allows easy modification of settings without hardcoding them in the configuration files:
POSTGRES_DB=lovecdb
POSTGRES_USER=myuser
POSTGRES_PASSWORD=mypassword
KEYCLOAK_ADMIN=admin
KEYCLOAK_ADMIN_PASSWORD=adminpassword
[email protected]
PGADMIN_DEFAULT_PASSWORD=adminpassword
Storing credentials and other environment-specific variables in a .env file helps keep your configuration clean and secure. Since this project is running locally, there's no immediate need to include the .env file in your .gitignore. However, if you plan to share or deploy the project, it's a good practice to add it to your .gitignore to prevent sensitive information from being exposed.

Running the Application

Create a New NestJS project

I began by creating a new NestJS project using the NestJS CLI. I navigated to the directory and ran the following command:
nest new app
This initialized a new NestJS project inside the app directory, setting up the basic structure and files I needed to get started.

Running the containers

With the NestJS project in place, I then focused on setting up my Docker environment. I ensured that Docker was running on my machine and returned to the root directory containing the docker-compose.yaml file.
To launch all the necessary services, including PostgreSQL, Keycloak, pgAdmin, and the application itself, I ran:
docker compose up -d
This command started all the services in detached mode, allowing them to run in the background.
Once everything was up and running, I could access the various services through my browser:

Conclusion

This is how I did our backend setup, ensuring a consistent, scalable, and secure environment using Docker, NestJS, and Keycloak. I hope you find this helpful!
In the next article, I'll guide you through configuring Keycloak with NestJS, connecting it to PostgreSQL, and exploring some other exciting features.
Happy coding!