Skip to content

3. Running the Application

Daniel Favour edited this page Jul 21, 2024 · 14 revisions

Running the Application Locally

Below are step-by-step instructions for setting up and running the Java web application using Maven and Spring Boot locally.

Steps

  1. Navigate to the Project Directory

    cd ~/hng_boilerplate_java_web/
    • cd is the command to change the current directory.
    • ~/hng_boilerplate_java_web/ specifies the path to the project directory.
  2. Resolve Maven Dependencies

    mvn dependency:resolve
    • mvn is the Maven command-line tool.
    • dependency:resolve downloads and resolves the dependencies defined in the pom.xml file.
  3. Setup the Database and Run Migration

  • DB Setup:

Install a Postgres DB depending on your system. Once it is running, create a database and configure the database environment variables in the application.properties file at src/main/resources/ directory.

  • Run Flyway Migrations:

Flyway migrations are a structured way to version control and manage changes to your database schema over time. It's a popular open-source tool designed to make database migrations easy, reliable, and consistent across different environments.

Instructions for the flyway migration have been provided in the READMe of this repository.

  1. Clean and Install the Project

    ./mvnw clean install
    • ./mvnw is the Maven wrapper script that ensures the correct Maven version is used.
    • clean removes the target directory to ensure a clean build.
    • install compiles the project, runs tests, and installs the built artifact in the local Maven repository.
  2. Run the Application in the Background

    nohup ./mvnw spring-boot:run > app.log 2>&1 &
    • nohup allows the application to run independently of the terminal session.
    • ./mvnw spring-boot:run uses the Maven wrapper to run the Spring Boot application.
    • > app.log redirects the standard output to a log file named app.log.
    • 2>&1 redirects the standard error to the same log file.
    • & runs the command in the background, allowing you to continue using the terminal.

By default, Spring Boot applications run on port 8080. In your browser, load localhost:8080 to see the application running.


Running the Application with Docker Locally

This guide explains how to run the application with Docker, leveraging a Dockerfile, a docker-compose.yml file, an init-db.sh script, and an nginx.conf file. Follow these steps to get your application up and running.

1. Dockerfile

The Dockerfile is used to build a Docker image for the Java application.

# Use the official OpenJDK 17 image as the base image
FROM openjdk:17-jdk-alpine

# Create a non-root user and group
RUN addgroup -S appgroup && adduser -S appuser -G appgroup

# Set the working directory inside the container
WORKDIR /app

# Copy the Maven wrapper and the pom.xml file to the container
COPY .mvn/ .mvn
COPY mvnw pom.xml ./

# Download the dependencies
RUN ./mvnw dependency:go-offline

# Copy the entire project to the container
COPY . .

# Change ownership of the application files to the non-root user
RUN chown -R appuser:appgroup /app

# Switch to the non-root user
USER appuser

# Expose the application port
EXPOSE 8080

# Run the application
CMD ["./mvnw", "spring-boot:run"]

This Dockerfile:

  • Uses an OpenJDK 17 image.
  • Creates a non-root user.
  • Copies the project files.
  • Installs dependencies offline.
  • Exposes port 8080 for the application.
  • Runs the Spring Boot application.

2. docker-compose.yml

The docker-compose.yml file defines the services for the application, including the backend, PostgreSQL database, Flyway migrations, and Nginx.

version: "3"

services:
  backend:
    build: .
    ports:
      - "8080:8080"
    environment:
      - spring.datasource.url=jdbc:postgresql://postgresdb:5432/app
      - spring.datasource.username=postgres
      - spring.datasource.password=postgres
      - spring.datasource.driver-class-name=org.postgresql.Driver
      - spring.flyway.enabled=true
      - spring.flyway.locations=classpath:db/migration
      - spring.flyway.user=postgres
      - spring.flyway.password=postgres
    networks:
      - backend-net
    depends_on:
      postgresdb:
        condition: service_healthy
    restart: unless-stopped

  postgresdb:
    image: postgres
    container_name: postgresdb
    restart: unless-stopped
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
      - POSTGRES_DB=app
    volumes:
      - ./init-db.sh:/docker-entrypoint-initdb.d/init-db.sh
      - postgresdataa:/var/lib/postgresql/data
    ports:
      - "5432:5432"
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - backend-net

  flyway:
    image: flyway/flyway:latest
    command: -url=jdbc:postgresql://postgresdb:5432/app -user=postgres -password=postgres migrate
    volumes:
      - ./src/main/resources/db/migration:/flyway/sql
    depends_on:
      postgresdb:
        condition: service_healthy
    networks:
      - backend-net

  nginx:
    image: nginx:latest
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
    networks:
      - backend-net
    depends_on:
      - backend
    restart: unless-stopped

networks:
  backend-net:
    driver: bridge
    
volumes:
  postgresdataa:

This docker-compose.yml file:

  • Defines services: backend, postgresdb, flyway, and nginx.
  • Configures environment variables for the services.
  • Specifies dependencies and health checks.
  • Sets up networking and volumes.

3. init-db.sh

The init-db.sh script initializes the PostgreSQL database.

#!/bin/bash
set -e

psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "app" <<-EOSQL
    DO \$\$
    BEGIN
        IF NOT EXISTS (SELECT FROM pg_database WHERE datname = 'app') THEN
            PERFORM dblink_exec('dbname=' || current_database(), 'CREATE DATABASE app');
        END IF;
    END
    \$\$;
EOSQL

This script:

  • Creates the app database if it does not exist.

4. nginx.conf

The nginx.conf file configures Nginx to serve as a reverse proxy for the backend service.

events {
    worker_connections 1024;
}

http {
    include mime.types;
    default_type application/octet-stream;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
    ssl_prefer_server_ciphers on;
  
    upstream backend {
        server backend:8080;
    }
    
    sendfile on;
    keepalive_timeout 100;

    server {
        listen 80;

        location / {
            proxy_pass http://backend;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
        error_log /var/log/nginx/error.log;
    }
}

This configuration:

  • Sets up Nginx to forward requests to the backend service running on port 8080.

Steps to Run the Application

  1. Ensure Docker and Docker Compose are installed.
  2. Clone the repository containing the above files.
  3. Navigate to the project directory:
    cd path/to/project
  4. Run Docker Compose to build and start the containers:
    docker-compose up --build

The application will be accessible at http://localhost:80 with Nginx proxying requests to the backend service. The PostgreSQL database will be initialized and ready for use.