Dockerfile Configuration
# Multi-stage build for efficiency
FROM maven:3.8-jdk-11 as build-stage
WORKDIR /workspace
COPY pom.xml .
COPY src ./src
# Build with caching and skip tests
RUN mvn package -DskipTests
# Runtime image
FROM openjdk:11-jre-slim
WORKDIR /app
COPY --from=build-stage /workspace/target/*.jar app.jar
# Run with production profile
ENTRYPOINT ["java", "-jar", "app.jar", "--spring.profiles.active=prod"]
Server Preparation
- Install Docker on the target server
- Note server credentials (IP, username, password) for GitHub Secrets
GitHub Actions Workflow
name: CI/CD Pipeline
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
env:
SERVER_IP: ${{ secrets.SERVER_IP }}
SERVER_USER: ${{ secrets.SERVER_USER }}
SERVER_PWD: ${{ secrets.SERVER_PWD }}
DEPLOY_DIR: "/deployments"
APP_PORT: 8080
VERSION: 1.0
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up JDK
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
- name: Build Docker image
run: |
docker build -t app:$VERSION .
docker save -o app.tar app:$VERSION
- name: Clean remote server
uses: appleboy/ssh-action@master
with:
host: ${{ env.SERVER_IP }}
username: ${{ env.SERVER_USER }}
password: ${{ env.SERVER_PWD }}
script: |
docker stop app || true
docker rm app || true
docker rmi app:$VERSION || true
rm -f $DEPLOY_DIR/app.tar
- name: Transfer image
run: |
scp -o StrictHostKeyChecking=no app.tar $SERVER_USER@$SERVER_IP:$DEPLOY_DIR
- name: Deploy application
uses: appleboy/ssh-action@master
with:
host: ${{ env.SERVER_IP }}
username: ${{ env.SERVER_USER }}
password: ${{ env.SERVER_PWD }}
script: |
docker load -i $DEPLOY_DIR/app.tar
docker run -d -p $APP_PORT:8080 --name app app:$VERSION
Verification Steps
- Check GitHub Actions execution logs
- On server, verify with:
docker ps for running containers
docker images for avialable images
- Access application at
http://<server-ip>:8080