mirror of
https://github.com/adityachandelgit/BookLore.git
synced 2026-02-18 03:07:40 +01:00
WIP: Dockerize
This commit is contained in:
36
Dockerfile
Normal file
36
Dockerfile
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
# Stage 1: Build the Angular app
|
||||||
|
FROM node:22-alpine AS angular-build
|
||||||
|
|
||||||
|
WORKDIR /angular-app
|
||||||
|
|
||||||
|
COPY ./booklore-ui/package.json ./booklore-ui/package-lock.json ./
|
||||||
|
RUN npm install
|
||||||
|
COPY ./booklore-ui /angular-app/
|
||||||
|
|
||||||
|
RUN npm run build --prod
|
||||||
|
|
||||||
|
# Stage 2: Build the Spring Boot app with Gradle
|
||||||
|
FROM gradle:jdk21-alpine AS springboot-build
|
||||||
|
|
||||||
|
WORKDIR /springboot-app
|
||||||
|
|
||||||
|
COPY ./booklore-api/gradlew ./booklore-api/gradle/ /springboot-app/
|
||||||
|
COPY ./booklore-api/build.gradle ./booklore-api/settings.gradle /springboot-app/
|
||||||
|
COPY ./booklore-api/gradle /springboot-app/gradle
|
||||||
|
COPY ./booklore-api/src /springboot-app/src
|
||||||
|
|
||||||
|
RUN ./gradlew clean build
|
||||||
|
|
||||||
|
# Stage 3: Final image combining everything
|
||||||
|
FROM eclipse-temurin:21-jdk-alpine
|
||||||
|
|
||||||
|
RUN apk update && apk add nginx
|
||||||
|
|
||||||
|
COPY ./nginx.conf /etc/nginx/nginx.conf
|
||||||
|
COPY --from=angular-build /angular-app/dist/booklore/browser /usr/share/nginx/html
|
||||||
|
COPY --from=springboot-build /springboot-app/build/libs/booklore-api-0.0.1-SNAPSHOT.jar /app/app.jar
|
||||||
|
|
||||||
|
EXPOSE 8080 80
|
||||||
|
|
||||||
|
CMD /usr/sbin/nginx -g "daemon off;" & \
|
||||||
|
java -jar /app/app.jar
|
||||||
@@ -3,7 +3,6 @@ plugins {
|
|||||||
id 'org.springframework.boot' version '3.4.0'
|
id 'org.springframework.boot' version '3.4.0'
|
||||||
id 'io.spring.dependency-management' version '1.1.6'
|
id 'io.spring.dependency-management' version '1.1.6'
|
||||||
id 'org.hibernate.orm' version '6.6.2.Final'
|
id 'org.hibernate.orm' version '6.6.2.Final'
|
||||||
id 'org.graalvm.buildtools.native' version '0.10.3'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
group = 'com.adityachandel'
|
group = 'com.adityachandel'
|
||||||
@@ -33,11 +32,11 @@ dependencies {
|
|||||||
implementation 'org.springframework.boot:spring-boot-starter-websocket'
|
implementation 'org.springframework.boot:spring-boot-starter-websocket'
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-quartz'
|
implementation 'org.springframework.boot:spring-boot-starter-quartz'
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-actuator'
|
implementation 'org.springframework.boot:spring-boot-starter-actuator'
|
||||||
|
implementation 'org.springframework.boot:spring-boot-configuration-processor'
|
||||||
|
|
||||||
// Lombok
|
// Lombok
|
||||||
compileOnly 'org.projectlombok:lombok'
|
compileOnly 'org.projectlombok:lombok'
|
||||||
annotationProcessor 'org.projectlombok:lombok'
|
annotationProcessor 'org.projectlombok:lombok'
|
||||||
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
|
|
||||||
|
|
||||||
// Database & Flyway
|
// Database & Flyway
|
||||||
implementation 'com.h2database:h2'
|
implementation 'com.h2database:h2'
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ spring:
|
|||||||
name: booklore-api
|
name: booklore-api
|
||||||
datasource:
|
datasource:
|
||||||
driver-class-name: org.h2.Driver
|
driver-class-name: org.h2.Driver
|
||||||
url: jdbc:h2:tcp://localhost:9092/~/my-library-temp/config/db/booklore
|
url: jdbc:h2:~/my-library-temp/config/db/booklore
|
||||||
username: sa
|
username: sa
|
||||||
password: password
|
password: password
|
||||||
jpa:
|
jpa:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
app:
|
app:
|
||||||
path-book: '/Users/aditya.chandel/my-library-temp/books'
|
path-book: '/app/books'
|
||||||
path-config: '/Users/aditya.chandel/my-library-temp/config'
|
path-config: '/app/config'
|
||||||
|
|
||||||
spring:
|
spring:
|
||||||
servlet:
|
servlet:
|
||||||
@@ -15,7 +15,7 @@ spring:
|
|||||||
name: booklore-api
|
name: booklore-api
|
||||||
datasource:
|
datasource:
|
||||||
driver-class-name: org.h2.Driver
|
driver-class-name: org.h2.Driver
|
||||||
url: jdbc:h2:tcp://localhost:9092/~/my-library-temp/config/db/booklore
|
url: 'jdbc:h2:/app/config/db/booklore'
|
||||||
username: sa
|
username: sa
|
||||||
password: password
|
password: password
|
||||||
jpa:
|
jpa:
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
package com.adityachandel.booklore;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
|
|
||||||
@SpringBootTest
|
|
||||||
class BookloreApplicationTests {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void contextLoads() {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
7
booklore-ui/.dockerignore
Normal file
7
booklore-ui/.dockerignore
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
node_modules
|
||||||
|
npm-debug.log
|
||||||
|
dist
|
||||||
|
.vscode
|
||||||
|
.idea
|
||||||
|
.angular
|
||||||
|
.editorconfig
|
||||||
@@ -56,7 +56,7 @@
|
|||||||
{
|
{
|
||||||
"type": "initial",
|
"type": "initial",
|
||||||
"maximumWarning": "500kB",
|
"maximumWarning": "500kB",
|
||||||
"maximumError": "1MB"
|
"maximumError": "3MB"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "anyComponentStyle",
|
"type": "anyComponentStyle",
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import {BookTableComponent} from './book-table/book-table.component';
|
|||||||
import {animate, state, style, transition, trigger} from '@angular/animations';
|
import {animate, state, style, transition, trigger} from '@angular/animations';
|
||||||
import {MetadataFetchOptionsComponent} from '../../../metadata/metadata-options-dialog/metadata-fetch-options/metadata-fetch-options.component';
|
import {MetadataFetchOptionsComponent} from '../../../metadata/metadata-options-dialog/metadata-fetch-options/metadata-fetch-options.component';
|
||||||
import {MetadataRefreshType} from '../../../metadata/model/request/metadata-refresh-type.enum';
|
import {MetadataRefreshType} from '../../../metadata/model/request/metadata-refresh-type.enum';
|
||||||
import {Button, ButtonDirective, ButtonIcon} from 'primeng/button';
|
import {Button} from 'primeng/button';
|
||||||
import {AsyncPipe, NgClass, NgForOf, NgIf} from '@angular/common';
|
import {AsyncPipe, NgClass, NgForOf, NgIf} from '@angular/common';
|
||||||
import {VirtualScrollerModule} from '@iharbeck/ngx-virtual-scroller';
|
import {VirtualScrollerModule} from '@iharbeck/ngx-virtual-scroller';
|
||||||
import {BookCardComponent} from './book-card/book-card.component';
|
import {BookCardComponent} from './book-card/book-card.component';
|
||||||
@@ -30,8 +30,6 @@ import {InputText} from 'primeng/inputtext';
|
|||||||
import {FormsModule} from '@angular/forms';
|
import {FormsModule} from '@angular/forms';
|
||||||
import {BookFilterComponent} from './book-filter/book-filter.component';
|
import {BookFilterComponent} from './book-filter/book-filter.component';
|
||||||
import {Tooltip} from 'primeng/tooltip';
|
import {Tooltip} from 'primeng/tooltip';
|
||||||
import {WindowMaximizeIcon} from 'primeng/icons';
|
|
||||||
import {Ripple} from 'primeng/ripple';
|
|
||||||
|
|
||||||
export enum EntityType {
|
export enum EntityType {
|
||||||
LIBRARY = 'Library',
|
LIBRARY = 'Library',
|
||||||
@@ -44,7 +42,7 @@ export enum EntityType {
|
|||||||
standalone: true,
|
standalone: true,
|
||||||
templateUrl: './book-browser.component.html',
|
templateUrl: './book-browser.component.html',
|
||||||
styleUrls: ['./book-browser.component.scss'],
|
styleUrls: ['./book-browser.component.scss'],
|
||||||
imports: [Button, NgIf, VirtualScrollerModule, BookCardComponent, AsyncPipe, ProgressSpinner, Select, Menu, NgForOf, InputText, FormsModule, BookTableComponent, BookFilterComponent, Tooltip, ButtonDirective, WindowMaximizeIcon, ButtonIcon, Ripple, NgClass],
|
imports: [Button, NgIf, VirtualScrollerModule, BookCardComponent, AsyncPipe, ProgressSpinner, Select, Menu, NgForOf, InputText, FormsModule, BookTableComponent, BookFilterComponent, Tooltip, NgClass],
|
||||||
animations: [
|
animations: [
|
||||||
trigger('slideInOut', [
|
trigger('slideInOut', [
|
||||||
state('void', style({
|
state('void', style({
|
||||||
|
|||||||
34
build-docker.sh
Normal file
34
build-docker.sh
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Define variables
|
||||||
|
PROJECT_ROOT=$(pwd)
|
||||||
|
UI_DIR="$PROJECT_ROOT/booklore-ui"
|
||||||
|
API_DIR="$PROJECT_ROOT/booklore-api"
|
||||||
|
H2_JAR="$PROJECT_ROOT/h2-2.3.232.jar"
|
||||||
|
DOCKER_IMAGE_NAME="booklore-app"
|
||||||
|
|
||||||
|
# Step 1: Build Angular frontend
|
||||||
|
echo "Building Angular frontend..."
|
||||||
|
cd "$UI_DIR" || exit
|
||||||
|
npm install
|
||||||
|
npm run build --prod || { echo "Angular build failed"; exit 1; }
|
||||||
|
echo "Angular build completed."
|
||||||
|
|
||||||
|
# Step 2: Package Spring Boot API
|
||||||
|
echo "Packaging Spring Boot API..."
|
||||||
|
cd "$API_DIR" || exit
|
||||||
|
mvn clean package -DskipTests || { echo "Spring Boot build failed"; exit 1; }
|
||||||
|
API_JAR=$(find target -name "*.jar" | head -n 1)
|
||||||
|
echo "Spring Boot API packaged: $API_JAR"
|
||||||
|
|
||||||
|
# Step 3: Build Docker image
|
||||||
|
cd "$PROJECT_ROOT" || exit
|
||||||
|
echo "Building Docker image..."
|
||||||
|
docker build -t "$DOCKER_IMAGE_NAME" . || { echo "Docker build failed"; exit 1; }
|
||||||
|
echo "Docker image built: $DOCKER_IMAGE_NAME"
|
||||||
|
|
||||||
|
# Step 4: Clean up (optional)
|
||||||
|
echo "Cleaning up intermediate files..."
|
||||||
|
rm -rf "$UI_DIR/node_modules"
|
||||||
|
|
||||||
|
echo "Build process completed successfully!"
|
||||||
11
docker-compose.yml
Normal file
11
docker-compose.yml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
version: '3.8'
|
||||||
|
services:
|
||||||
|
booklore-app:
|
||||||
|
container_name: booklore
|
||||||
|
image: localhost:5000/booklore-app:v12
|
||||||
|
ports:
|
||||||
|
- "8081:8080"
|
||||||
|
- "4201:80"
|
||||||
|
volumes:
|
||||||
|
- /Users/aditya.chandel/my-library-temp/config:/app/config
|
||||||
|
- /Users/aditya.chandel/my-library-temp/books:/app/books
|
||||||
27
nginx.conf
Normal file
27
nginx.conf
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# the events block is required
|
||||||
|
events{}
|
||||||
|
|
||||||
|
http {
|
||||||
|
# include the default mime.types to map file extensions to MIME types
|
||||||
|
include /etc/nginx/mime.types;
|
||||||
|
|
||||||
|
server {
|
||||||
|
# set the root directory for the server (we need to copy our
|
||||||
|
# application files here)
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
|
||||||
|
# set the default index file for the server (Angular generates the
|
||||||
|
# index.html file for us and it will be in the above directory)
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
# specify the configuration for the '/' location
|
||||||
|
location / {
|
||||||
|
# try to serve the requested URI. if that fails then try to
|
||||||
|
# serve the URI with a trailing slash. if that fails, then
|
||||||
|
# serve the index.html file; this is needed in order to serve
|
||||||
|
# Angular routes--e.g.,'localhost:8080/customer' will serve
|
||||||
|
# the index.html file
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user