|
| 1 | +# Production Deployment |
| 2 | + |
| 3 | +This service deploys as an immutable Docker image published to GitHub Container Registry (GHCR). Runtime configuration is injected through the EC2 `.env` file generated by GitHub Actions; private resource files are not copied into the image or bind-mounted from the host. |
| 4 | + |
| 5 | +## Required GitHub Secrets |
| 6 | + |
| 7 | +Deployment access: |
| 8 | + |
| 9 | +- `EC2_HOST` |
| 10 | +- `EC2_USER` |
| 11 | +- `EC2_SSH_KEY` |
| 12 | +- `GHCR_USERNAME` |
| 13 | +- `GHCR_READ_TOKEN` |
| 14 | + |
| 15 | +Runtime image and port: |
| 16 | + |
| 17 | +- `BACKEND_HTTP_PORT` (optional, defaults to `8080`) |
| 18 | + |
| 19 | +Spring and database: |
| 20 | + |
| 21 | +- `SPRING_APPLICATION_NAME` |
| 22 | +- `SPRING_DATASOURCE_URL` |
| 23 | +- `SPRING_DATASOURCE_USERNAME` |
| 24 | +- `SPRING_DATASOURCE_PASSWORD` |
| 25 | +- `SPRING_DATASOURCE_DRIVER_CLASS_NAME` |
| 26 | +- `SPRING_JPA_HIBERNATE_DDL_AUTO` |
| 27 | +- `SPRING_FLYWAY_URL` |
| 28 | +- `SPRING_FLYWAY_USER` |
| 29 | +- `SPRING_FLYWAY_PASSWORD` |
| 30 | + |
| 31 | +Authentication and OAuth: |
| 32 | + |
| 33 | +- `JWT_SECRETKEY` |
| 34 | +- `JWT_ACCESS_EXPIRATION` |
| 35 | +- `JWT_REFRESH_EXPIRATION` |
| 36 | +- `JWT_ACCESS_HEADER` |
| 37 | +- `JWT_REFRESH_HEADER` |
| 38 | +- `GOOGLE_WEB_CLIENT_ID` |
| 39 | +- `GOOGLE_APP_CLIENT_ID` |
| 40 | +- `SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_GOOGLE_CLIENT_SECRET` |
| 41 | +- `SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_GOOGLE_SCOPE` |
| 42 | +- `SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_GOOGLE_REDIRECT_URI` |
| 43 | +- `SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_GOOGLE_AUTHORIZATION_GRANT_TYPE` |
| 44 | +- `SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_GOOGLE_CLIENT_NAME` |
| 45 | +- `SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_GOOGLE_AUTHORIZATION_URI` |
| 46 | +- `SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_GOOGLE_TOKEN_URI` |
| 47 | +- `SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_GOOGLE_USER_INFO_URI` |
| 48 | +- `SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_GOOGLE_USER_NAME_ATTRIBUTE` |
| 49 | +- `SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_KAKAO_CLIENT_ID` |
| 50 | +- `SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_KAKAO_SCOPE` |
| 51 | +- `SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_KAKAO_REDIRECT_URI` |
| 52 | +- `SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_KAKAO_AUTHORIZATION_GRANT_TYPE` |
| 53 | +- `SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_KAKAO_CLIENT_NAME` |
| 54 | +- `SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_KAKAO_AUTHORIZATION_URI` |
| 55 | +- `SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_KAKAO_TOKEN_URI` |
| 56 | +- `SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_KAKAO_USER_INFO_URI` |
| 57 | +- `SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_KAKAO_USER_NAME_ATTRIBUTE` |
| 58 | +- `APPLE_CLIENT_ID` |
| 59 | +- `APPLE_TEAM_ID` |
| 60 | +- `APPLE_LOGIN_KEY` |
| 61 | +- `APPLE_PRIVATE_KEY_BASE64` |
| 62 | +- `FEATURE_APPLE_LOGIN_ENABLED` (optional, defaults to `true`) |
| 63 | + |
| 64 | +Firebase: |
| 65 | + |
| 66 | +- `FIREBASE_CREDENTIALS_BASE64` |
| 67 | + |
| 68 | +Set the base64 secrets from the ignored local credential files: |
| 69 | + |
| 70 | +```bash |
| 71 | +base64 -i ontime-back/src/main/resources/ontime-c63f1-firebase-adminsdk-fbsvc-a043cdc829.json | tr -d '\n' | gh secret set FIREBASE_CREDENTIALS_BASE64 --repo DevKor-github/OnTime-back |
| 72 | +``` |
| 73 | + |
| 74 | +```bash |
| 75 | +base64 -i ontime-back/src/main/resources/key/AuthKey_743M7R5W3W.p8 | tr -d '\n' | gh secret set APPLE_PRIVATE_KEY_BASE64 --repo DevKor-github/OnTime-back |
| 76 | +``` |
| 77 | + |
| 78 | +## Build And Release Flow |
| 79 | + |
| 80 | +Push to the `deploy` branch to trigger `.github/workflows/deploy.yml`. |
| 81 | + |
| 82 | +The workflow: |
| 83 | + |
| 84 | +1. Builds `ontime-back/Dockerfile` from the `ontime-back/` context. |
| 85 | +2. Pushes two GHCR tags: |
| 86 | + - `ghcr.io/devkor-github/ontime-back:<commit-sha>` |
| 87 | + - `ghcr.io/devkor-github/ontime-back:deploy-latest` |
| 88 | +3. Uploads `docker-compose.yml` to `/home/ubuntu/OnTime-back`. |
| 89 | +4. Writes `/home/ubuntu/OnTime-back/.env` from GitHub secrets. |
| 90 | +5. Runs `docker compose pull && docker compose up -d --remove-orphans`. |
| 91 | +6. Waits until the `ontime-container` Docker health status is `healthy`. |
| 92 | + |
| 93 | +## Health Verification |
| 94 | + |
| 95 | +The production image exposes a Docker healthcheck against: |
| 96 | + |
| 97 | +```text |
| 98 | +/actuator/health/readiness |
| 99 | +``` |
| 100 | + |
| 101 | +Manual checks on EC2: |
| 102 | + |
| 103 | +```bash |
| 104 | +cd /home/ubuntu/OnTime-back |
| 105 | +sudo docker compose ps |
| 106 | +sudo docker inspect -f '{{.State.Health.Status}}' ontime-container |
| 107 | +curl -fsS http://localhost:8080/actuator/health/readiness |
| 108 | +``` |
| 109 | + |
| 110 | +## Rollback |
| 111 | + |
| 112 | +Every deploy is tagged by commit SHA. To roll back, set `IMAGE_TAG` in `/home/ubuntu/OnTime-back/.env` to the previous known-good SHA, then restart from the existing Compose file: |
| 113 | + |
| 114 | +```bash |
| 115 | +cd /home/ubuntu/OnTime-back |
| 116 | +sudo docker compose pull |
| 117 | +sudo docker compose up -d --remove-orphans |
| 118 | +sudo docker inspect -f '{{.State.Health.Status}}' ontime-container |
| 119 | +``` |
| 120 | + |
| 121 | +Keep the previous SHA in the release notes or GitHub Actions deploy history so rollback does not depend on `deploy-latest`. |
0 commit comments