🚀 Why CI/CD?
CI/CD automates every stage of your software delivery process:
- CI (Continuous Integration): Automatically builds and tests your code on each commit.
- CD (Continuous Deployment): Automatically deploys your application to the production environment after passing tests.
Together, CI/CD reduces errors, improves productivity, and ensures reliable releases—critical in agile and DevOps workflows.
🏗️ Project Overview
You’ll learn how to:
- Use GitHub Actions to automate Maven build and GCP deployment.
- Securely manage SSH keys and secrets.
- Use Docker for containerization (optional).
- Deploy to a GCP Compute Engine VM running Ubuntu.
🔧 Prerequisites
Before you begin:
- GCP project with Compute Engine VM set up (Ubuntu OS, Java installed).
- GitHub repository for your Spring Boot project.
- Domain name (e.g., from No-IP) and optional SSL certificate via Let’s Encrypt.
- SSH key pair added to your GitHub and GCP metadata.
- Application setup (e.g.,
application.properties
, MySQL, Redis, etc.) already running on the VM.
📁 GitHub Repository Setup
-
Add Secrets to GitHub:
Navigate toSettings → Secrets and Variables → Actions
, and add:-
GCP_SSH_PRIVATE_KEY
: Your private SSH key (no passphrase). -
GCP_VM_IP
: Your VM’s external IP. -
GCP_VM_USER
: The SSH username (usually your GCP email-based user). -
KEYSTORE_BASE64
: Base64 encodedkeystore.p12
SSL cert file.
-
To create KEYSTORE_BASE64
:
base64 cert/keystore.p12 > keystore_base64.txt
-
Public Key in GCP VM:
Upload your public SSH key (gcp_ssh_key.pub
) using GCP’s OS Login or manually via~/.ssh/authorized_keys
.
📜 GitHub Actions Workflow File (.github/workflows/deploy.yml
)
name: Deploy Java App to GCP VM
on:
push:
branches: [main]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up JDK 23
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '23'
- name: Build with Maven
run: mvn clean package -DskipTests
- name: Set up SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.GCP_SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H ${{ secrets.GCP_VM_IP }} >> ~/.ssh/known_hosts
- name: Deploy JAR to GCP VM
run: |
scp -i ~/.ssh/id_rsa target/*.jar ${{ secrets.GCP_VM_USER }}@${{ secrets.GCP_VM_IP }}:/home/${{ secrets.GCP_VM_USER }}/app.jar
ssh -i ~/.ssh/id_rsa ${{ secrets.GCP_VM_USER }}@${{ secrets.GCP_VM_IP }} << 'EOF'
sudo pkill -f "java -jar" || true
nohup java -jar /home/${{ secrets.GCP_VM_USER }}/app.jar --spring.config.location=/home/${{ secrets.GCP_VM_USER }}/application.properties > app.log 2>&1 &
EOF
🔐 SSL and Secrets Management
Use Let’s Encrypt to generate a free SSL certificate:
sudo apt install certbot
sudo certbot certonly --standalone -d your-domain.ddns.net
Convert to keystore.p12
for Spring Boot:
openssl pkcs12 -export -in fullchain.pem -inkey privkey.pem -out keystore.p12 -name mysslkey -password pass:yourpassword
Encode and add it to GitHub as KEYSTORE_BASE64
, then restore it in your workflow:
- name: Restore keystore.p12
run: |
mkdir -p src/main/resources/cert
echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 --decode > src/main/resources/cert/keystore.p12
🐳 Bonus: Dockerizing Your Java App
To containerize your app:
- Create a
Dockerfile
:
FROM openjdk:17-slim
COPY target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
- Add Docker build/push to your GitHub Actions:
- name: Build Docker Image
run: docker build -t youruser/demo-spring-app .
- name: Push to Docker Hub
run: |
echo "${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}" | docker login -u "${{ secrets.DOCKER_HUB_USERNAME }}" --password-stdin
docker push youruser/demo-spring-app
- Pull and run the container on GCP VM:
docker pull youruser/demo-spring-app
docker run -d --name demo -p 8080:8080 youruser/demo-spring-app
✅ CI/CD Flow Summary
- Developer pushes code to GitHub
main
branch. - GitHub Actions:
- Builds the project using Maven.
- Deploys
.jar
or Docker image to GCP VM.
- App runs on VM, accessible via your domain and secured with SSL.
🎯 Conclusion
Setting up a CI/CD pipeline with GitHub Actions and GCP Compute Engine offers a powerful, scalable, and fully automated deployment workflow for your Java apps. By leveraging GitHub’s native integration with Secrets and Actions, plus the flexibility of GCP, you can deploy with confidence and consistency.