EC2 + Docker 기반 Jenkins, Nginx, Certbot, Unity CLI, Firebase App Distribution, Slack 연동 완전 자동화 구성
GitHub → Webhook → Nginx (443/80) → Jenkins (내부 8080) → Unity Build & Test → APK 생성 → Firebase 배포 → Slack 알림 + 테스터 관리
infra/
├── docker-compose.yml
├── .env
├── jenkins/
│ └── jenkins_home/
├── nginx/
│ ├── nginx.conf
│ ├── ssl/
│ └── healthcheck.conf
├── certbot/
│ └── init-letsencrypt.sh
scripts/
├── build.sh
├── test.sh
├── deploy.sh
├── notify.sh
├── manage-testers.sh
unity-project/
└── BuildScript.cs
version: '3.8'
services:
jenkins:
image: jenkins/jenkins:2.504.2-lts
container_name: jenkins
restart: unless-stopped
expose:
- "8080"
networks:
- backend
volumes:
- ./jenkins/jenkins_home:/var/jenkins_home
- /var/run/docker.sock:/var/run/docker.sock
nginx:
image: nginx:stable
container_name: nginx
restart: unless-stopped
depends_on:
- jenkins
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/healthcheck.conf:/etc/nginx/conf.d/healthcheck.conf
- ./nginx/ssl:/etc/letsencrypt
- ./nginx/ssl:/var/www/certbot
healthcheck:
test: ["CMD", "curl", "-f", "<http://localhost/health>"]
interval: 10s
retries: 5
networks:
- backend
certbot:
image: certbot/certbot
container_name: certbot
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do sleep 6h & wait $${!}; certbot renew --webroot -w /var/www/certbot --quiet; nginx -s reload; done'"
volumes:
- ./nginx/ssl:/etc/letsencrypt
- ./nginx/ssl:/var/www/certbot
networks:
- backend
networks:
backend:
driver: bridge
| ID | 설명 |
|---|---|
| firebase\_app\_id | Firebase 프로젝트 App ID |
| firebase\_token | Firebase CLI 인증 토큰 |
| slack\_webhook | Slack Webhook URL |
pipeline {
agent {
docker {
image 'unityci/editor:2022.3.12f1-android'
args '-v /var/run/docker.sock:/var/run/docker.sock'
}
}
environment {
UNITY_PROJECT_PATH = 'unity-project'
BUILD_OUTPUT_PATH = 'build/output.apk'
FIREBASE_APP_ID = credentials('firebase_app_id')
FIREBASE_TOKEN = credentials('firebase_token')
SLACK_WEBHOOK = credentials('slack_webhook')
TESTER_GROUP = 'testers'
}
triggers {
githubPush()
}
stages {
stage('Checkout') {
steps {
git url: '<https://github.com/your-org/unity-game-repo.git>', branch: 'main'
}
}
stage('Build') {
steps {
sh './scripts/build.sh $UNITY_PROJECT_PATH'
archiveArtifacts artifacts: 'build/output.apk', fingerprint: true
}
}
stage('Deploy') {
steps {
sh './scripts/deploy.sh $FIREBASE_APP_ID $BUILD_OUTPUT_PATH $FIREBASE_TOKEN $TESTER_GROUP'
sh './scripts/manage-testers.sh $FIREBASE_APP_ID $FIREBASE_TOKEN $TESTER_GROUP'
}
}
}
post {
success { sh './scripts/notify.sh success' }
failure { sh './scripts/notify.sh failure' }
}
}
#!/bin/bash
UNITY_PROJECT_PATH=$1
BUILD_PATH="build/output.apk"
/opt/unity/Editor/Unity \\
-batchmode \\
-nographics \\
-silent-crashes \\
-logFile /dev/stdout \\
-projectPath "$UNITY_PROJECT_PATH" \\
-executeMethod "BuildScript.BuildAndroid" \\
-buildTarget Android \\
-quit
#!/bin/bash
firebase appdistribution:distribute "$2" --app "$1" --token "$3" --groups "$4"
#!/bin/bash
# 예: CSV에서 이메일 읽어 등록
#!/bin/bash
curl -X POST -H 'Content-type: application/json' \\
--data '{"text":"Build $1!"}' "$SLACK_WEBHOOK"