Deploying a Java Application on VPS: Advanced Level with CI/CD

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Deploying a Java Application on VPS: Advanced Level with CI/CD, Docker and SSL



In this article, we will look at the advanced process of deploying a Java application on a VPS (Virtual Private Server). We will not dwell on basic steps like installing JDK or running a JAR file. Instead, we will focus on setting up a CI/CD pipeline, containerization with Docker, using Nginx as a reverse proxy, automatically obtaining SSL certificates, as well as monitoring and fault tolerance of the application.



It is assumed that you already have a VPS with Ubuntu 22.04 LTS, a base domain, and are familiar with the Linux command line. All code examples are written in Java 17+ using Spring Boot, but the principles apply to any Java framework.



1. Containerizing a Java Application with Docker



The first step towards advanced deployment is packaging the application into a Docker container. This ensures environment reproducibility and simplifies deployment.



Create a Dockerfile in the project root:



# Use multi-stage build to reduce the size of the final imageFROM maven:3.9.6-eclipse-temurin-17 AS builderWORKDIR /appCOPY pom.xml .RUN mvn dependency:go-offlineCOPY src ./srcRUN mvn clean package -DskipTests

FROM eclipse-temurin:17-jre-alpineWORKDIR /appCOPY --from=builder /app/target/*.jar app.jarEXPOSE 8080ENTRYPOINT ["java", "-jar", "app.jar"]


docker-compose.yml file for running with a database:



version: '3.8'services:  app:    build: .    ports:      - "8080:8080"    environment:      - SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/mydb      - SPRING_DATASOURCE_USERNAME=user      - SPRING_DATASOURCE_PASSWORD=pass    depends_on:      - db    restart: unless-stopped

db: image: postgres:15-alpine environment: POSTGRES_DB: mydb POSTGRES_USER: user POSTGRES_PASSWORD: pass volumes: - pgdata:/var/lib/postgresql/data restart: unless-stopped

volumes: pgdata:


After building the image with the command docker compose build, you will have a container ready for deployment.



2. Setting up a CI/CD Pipeline (GitHub Actions)



Deployment automation is a key element of the advanced level. We use GitHub Actions to build, test, and send the image to the server.



Create the file .github/workflows/deploy.yml:



name: Deploy Java App to VPS

on: push: branches: [ main ]

jobs: build-and-deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4

- name: Set up JDK 17 uses: actions/setup-java@v4 with: java-version: '17' distribution: 'temurin'

- name: Build with Maven run: mvn clean package

- name: Build Docker image run: docker build -t myapp:latest .

- name: Save Docker image to tar run: docker save myapp:latest | gzip > myapp.tar.gz

- name: Copy image to VPS via SCP uses: appleboy/scp-action@v0.1.7 with: host: ${{ secrets.VPS_HOST }} username: ${{ secrets.VPS_USER }} key: ${{ secrets.VPS_SSH_KEY }} source: "myapp.tar.gz" target: "/opt/app/"

- name: Deploy on VPS uses: appleboy/ssh-action@v1.0.3 with: host: ${{ secrets.VPS_HOST }} username: ${{ secrets.VPS_USER }} key: ${{ secrets.VPS_SSH_KEY }} script: | cd /opt/app docker load < myapp.tar.gz docker compose down docker compose up -d rm myapp.tar.gz


Don't forget to add the secrets VPS_HOST, VPS_USER, VPS_SSH_KEY in the settings

Blogs

Book Recommendations