diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..f8266c3 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +.idea +*.iml +.git +build +cloud \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..fb187c3 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,37 @@ +# Building the image +FROM gradle:4.1-jdk8-alpine as build + +# Gradle image creates a 'gradle' user, so fallback to 'root' to do initial setup +USER root + +RUN mkdir -p /opt/app +WORKDIR /opt/app + +COPY settings.gradle . +COPY api ./api + +# Assemble artifact +RUN gradle clean build + + +# Run the application in a small container +FROM openjdk:8-jre-alpine as runtime + +RUN mkdir -p /opt/app + +WORKDIR /opt/app + +# Take artifact from previous step +COPY --from=build /opt/app/api/build/libs/api.jar . + +# Create new user to run application on behalf of +RUN addgroup -S -g 1001 app \ + && adduser -D -S -G app -u 1001 -s /bin/ash app \ + && chown -R app:app /opt/app + +USER app + +EXPOSE 8080 + +# Run as plain jar file +CMD ["java", "-jar", "api.jar"] diff --git a/Dockerfile.dev b/Dockerfile.dev new file mode 100644 index 0000000..b7d0b20 --- /dev/null +++ b/Dockerfile.dev @@ -0,0 +1,20 @@ +FROM gradle:4.1-jdk8-alpine + +# Gradle image creates a 'gradle' user, so fallback to 'root' to do initial setup +USER root + +ENV GRADLE_USER_HOME /opt + +RUN mkdir -p /opt/app +WORKDIR /opt/app + +# Copy gradle build scripts +COPY .env settings.gradle ./ +COPY api/build.gradle api/dotenv.gradle ./api/ + +# Fetch dependencies - do it before copying the source code to cache the layer +RUN ["gradle", "--no-daemon"] + +COPY api api + +ENTRYPOINT ["gradle", "--no-daemon"] diff --git a/README.md b/README.md index ca283a9..9598f96 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,12 @@ Spring Boot, GraphQL template project with batteries included.  - Logging level, e.g. `LOGGING_LEVEL_feign=DEBUG` - App properties, e.g. `APP_DEPENDENCY_API_HOST=example.com` - See [Spring Boot documentation on relaxed property binding](https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-relaxed-binding) +- Docker :whale: configuration for production deployment, development and test + - Remote debugging for development mode ## Required Software - JDK 1.8 +- Or docker + docker-compose ### Lombok @@ -31,7 +34,9 @@ Spring Boot, GraphQL template project with batteries included. ## Develop -1. Create top level `.env` file and add required [key-values](https://docs.oracle.com/cd/E23095_01/Platform.93/ATGProgGuide/html/s0204propertiesfileformat01.html) +1. Create `.env` file + +Create top level `.env` file and add required [key-values](https://docs.oracle.com/cd/E23095_01/Platform.93/ATGProgGuide/html/s0204propertiesfileformat01.html) e.g.: ``` @@ -39,15 +44,30 @@ APP_ICNDB_URL=https://api.icndb.com LOGGING_LEVEL_feign=DEBUG ``` -2. `$ gradlew bootRun` +2.1. Run + +- Gradle: `$ gradlew bootRun` +- Docker: `$ docker-compose up` (or `$ docker-compose up --build` if image should be rebuilt) + +2.2. Debug + +Run remote debugger from IDE. Debug port is 5005 ## Test -`$ gradlew test` +- Gradle: `$ gradlew test` +- Docker: `$ docker-compose -f docker-compose.test.yml up --build` ## Build -`$ gradlew buld` +- Gradle: `$ gradlew buld` +- Docker: `$ docker build -t spring-boot-graphql-template .` + +## Run productive + +Assuming that the Docker image is already built on the previous step + +- Docker (add `-d` to run in daemon mode): `$ docker run -e 'APP_ICNDB_URL=https://api.icndb.com' -p 8080:8080 spring-boot-graphql-template` ## Tech Stack - [Spring Boot](https://projects.spring.io/spring-boot/) : Application framework @@ -56,6 +76,8 @@ LOGGING_LEVEL_feign=DEBUG - [GraphQL](http://graphql.org/learn/) : API query runtime - [GraphQL and GraphiQL Spring Framework Boot Starters](https://github.com/graphql-java/graphql-spring-boot) - [GraphQL Java Tools](https://github.com/graphql-java/graphql-java-tools) +- Docker + - [Home Page](https://www.docker.com) ## Cloud Deployment diff --git a/api/build.gradle b/api/build.gradle index f3d8788..651a264 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -2,7 +2,7 @@ buildscript { ext { springBootVersion = '1.5.4.RELEASE' } - + repositories { mavenCentral() } @@ -15,7 +15,7 @@ buildscript { repositories { mavenCentral() } - + apply plugin: 'java' sourceCompatibility = 1.8 targetCompatibility = 1.8 @@ -26,6 +26,7 @@ apply from: 'dotenv.gradle' bootRun() { environment << dotenv + jvmArgs = ['-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005'] } dependencies { diff --git a/docker-compose.test.yml b/docker-compose.test.yml new file mode 100644 index 0000000..14d726a --- /dev/null +++ b/docker-compose.test.yml @@ -0,0 +1,9 @@ +version: "3" +services: + spring-boot-graphql-template-test: + command: clean test + build: + context: . + dockerfile: Dockerfile.dev + volumes: + - ${PWD}/api:/opt/app/api diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..10b128a --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,12 @@ +version: "3" +services: + spring-boot-graphql-template: + command: bootRun + build: + context: . + dockerfile: Dockerfile.dev + volumes: + - ${PWD}/api:/opt/app/api + ports: + - "8080:8080" + - "5005:5005" \ No newline at end of file diff --git a/gradlew b/gradlew old mode 100644 new mode 100755