onpod › 활용 사례 › GitHub·GitLab에 push 하면 배포 끝

● Git 자동 배포

GitHub·GitLab에 push 하면 배포 끝

이미 쓰는 GitHub Actions·GitLab CI에 onpod 배포 단계 하나를 더해요. onpod ci init 한 줄이면 CI 파일과 이 앱 전용 키가 생기고, 그다음부터는 push가 곧 배포예요.

이런 적 있나요

코드를 고칠 때마다 손으로 배포하고 있다면

코드를 고치고, 커밋하고, push 하고, 다시 터미널을 열어 배포 명령을 치고, 끝날 때까지 지켜보고… 하루에 몇 번씩 반복하면 꽤 큰 일입니다. 배포를 맡던 사람이 자리를 비우면 고친 코드가 며칠씩 서비스에 못 올라가기도 하고요.

팀으로 일하면 더 헷갈립니다. 지금 서비스에 올라가 있는 게 어느 커밋인지, 누가 언제 올렸는지를 매번 물어봐야 하죠.

해결

onpod ci init 한 줄 — 그다음부터는 push가 배포

저장소 폴더에서 onpod ci init --app myapp을 실행하면 onpod이 두 가지를 만들어 줘요. CI 파일(GitHub은 .github/workflows/onpod-deploy.yml, GitLab은 .gitlab-ci.yml)과 이 앱 하나만 배포할 수 있는 키입니다.

새 CI 서비스로 옮기는 게 아니에요. 이미 쓰는 GitHub Actions·GitLab CI 안에 배포 단계가 하나 생길 뿐이라, 테스트·코드 리뷰 흐름은 그대로 두고 그 뒤에 배포만 자동으로 붙습니다.

3단계

처음 한 번만 하면 돼요

1CI 파일과 키 만들기

저장소 폴더에서 onpod ci init --app myapp. GitHub·GitLab은 저장소 주소를 보고 알아서 고릅니다.

2키를 저장소 비밀에 넣기

화면에 한 번 보이는 키를 ONPOD_TOKEN이라는 이름으로 넣어요. GitHub은 --set-secret을 붙이면 이것까지 대신 해 줘요.

3커밋하고 push

만든 파일을 커밋해 push 하는 순간 첫 배포가 돌아요. 이후로는 push 할 때마다 자동으로 다시 배포됩니다.

onpod — deploy
# 코딩 에이전트에게 말로 해도 돼요
나 GitHub에 push 하면 이 앱이 자동으로 배포되게 해줘

에이전트 → onpod ci init --app myapp --set-secret
✓ GitHub Actions 파일을 만들었어요 → .github/workflows/onpod-deploy.yml
✓ CI 전용 키를 저장소 비밀 ONPOD_TOKEN에 넣었어요
다음: 파일을 커밋하고 main에 push — 그 순간 첫 배포가 돌아요

만들어지는 파일

GitHub Actions 파일 예시

서버 앱 myapp을 main 브랜치에서 배포하는 경우예요. onpod CLI는 onpod.ai에서 받아 체크섬을 확인한 뒤 쓰고, 키는 저장소 비밀에서만 읽어요. GitLab이면 같은 일을 하는 .gitlab-ci.yml이 만들어지고, 이미 파일이 있으면 덮지 않고 .gitlab/onpod-deploy.yml을 따로 만들어 include 한 줄만 안내해요.

.github/workflows/onpod-deploy.yml
# onpod ci init이 만든 파일 — main 브랜치에 push 하면 onpod 앱 「myapp」의 새 버전을 서버에서 빌드해 배포해요(데이터·환경변수 그대로). # onpod-ci: app=myapp kind=server provider=github v1 # 필요한 비밀: ONPOD_TOKEN (Settings → Secrets and variables → Actions) # 다시 만들기: onpod ci init --app myapp --provider github --branch main --no-key --force name: "onpod deploy · myapp" on: push: branches: - "main" workflow_dispatch: concurrency: group: "onpod-deploy-myapp" cancel-in-progress: false permissions: contents: read jobs: deploy: if: github.ref == 'refs/heads/main' runs-on: ubuntu-latest timeout-minutes: 45 env: ONPOD_DISABLE_UPDATE_CHECK: "1" ONPOD_CONFIG: "/nonexistent/onpod-ci/config.json" ONPOD_URL: "https://api.onpod.ai" steps: - uses: actions/checkout@v7 with: persist-credentials: false - name: "onpod CLI 설치 (체크섬 확인)" run: | set -eu ONPOD_BIN="$RUNNER_TEMP/onpod-bin" mkdir -p "$ONPOD_BIN" case "$(uname -s)" in Darwin) ONPOD_OS=darwin ;; *) ONPOD_OS=linux ;; esac case "$(uname -m)" in aarch64|arm64) ONPOD_ARCH=arm64 ;; *) ONPOD_ARCH=amd64 ;; esac ONPOD_FILE="onpod-${ONPOD_OS}-${ONPOD_ARCH}" ONPOD_CLI_URL="https://onpod.ai/cli" onpod_get() { curl -fsSL --retry 3 --proto =https --proto-redir =https -o "$2" "$1"; } onpod_get "${ONPOD_CLI_URL}/${ONPOD_FILE}" "${ONPOD_BIN}/onpod" || { echo "::error::onpod CLI를 못 받았어요: ${ONPOD_CLI_URL}/${ONPOD_FILE}"; exit 1; } onpod_get "${ONPOD_CLI_URL}/sha256sums.txt" "${ONPOD_BIN}/sha256sums.txt" || { echo "::error::onpod CLI 체크섬 목록(sha256sums.txt)을 못 받았어요 — 설치를 멈춰요"; exit 1; } want="" while read -r h f; do if [ "${f#\*}" = "$ONPOD_FILE" ]; then want="$h"; fi; done < "${ONPOD_BIN}/sha256sums.txt" [ -n "$want" ] || { echo "::error::onpod CLI 체크섬 목록에 ${ONPOD_FILE}이 없어요 — 설치를 멈춰요"; exit 1; } if command -v sha256sum >/dev/null 2>&1; then echo "$want ${ONPOD_BIN}/onpod" | sha256sum -c -; else echo "$want ${ONPOD_BIN}/onpod" | shasum -a 256 -c -; fi || { echo "::error::onpod CLI 체크섬이 맞지 않아요 — 받은 파일을 쓰지 않아요"; exit 1; } chmod +x "${ONPOD_BIN}/onpod" echo "$ONPOD_BIN" >> "$GITHUB_PATH" "$ONPOD_BIN/onpod" --version - name: "onpod 배포" env: ONPOD_TOKEN: ${{ secrets.ONPOD_TOKEN }} run: | set -eu [ -n "${ONPOD_TOKEN:-}" ] || { echo "::error::ONPOD_TOKEN이 비어 있어요 — Settings → Secrets and variables → Actions에 onpod CI 키를 넣어 주세요 (키 만들기: onpod ci init --app myapp)"; exit 1; } ONPOD_SHA12=${GITHUB_SHA%"${GITHUB_SHA#????????????}"} if ! onpod app update myapp --build . --build-tag "myapp:$ONPOD_SHA12"; then echo "::error::onpod 배포가 실패했어요 — 위 오류를 보세요. 401이면 키가 틀렸거나 만료됐어요(새 키: onpod ci init --app myapp). 되돌리기: onpod app rollback myapp" exit 1 fi

안심하고 쓰도록

키와 권한은 꼭 필요한 만큼만

이 앱 하나만

CI 키는 그 앱 배포에만 쓸 수 있어요. 다른 앱·DB·결제·키 관리는 못 해요. 웹사이트면 그 사이트만.

1년 뒤 자동 만료

기본 1년이 지나면 저절로 무효가 되고, 필요하면 바로 지울 수도 있어요(onpod key rm).

키는 비밀에만

키 원문은 처음 한 번만 보여 주고, CI 파일에는 들어가지 않아요. 로그에도 찍히지 않아요.

되돌리기 한 줄

잘못 올라갔으면 onpod app rollback myapp. 커밋마다 이미지가 남아 원하는 커밋으로도 바로 돌아가요.

사내 GitLab + 사내 onpod

폐쇄망에서도 그대로 — 사내 러너가 사내 onpod을 불러요

회사 서버에 onpod을 설치해 쓰고(온프렘), 코드는 사내 GitLab에 두는 경우가 가장 잘 맞아요. 사내 GitLab 러너가 사내 onpod을 직접 부르기 때문에 바깥 인터넷이 필요 없습니다.

사내 onpod에 로그인한 상태로 onpod ci init을 실행하면, CI 파일에 사내 onpod 주소와 사내에서 CLI를 받는 주소가 기본값으로 들어가요. 러너에서 주소가 다르면 GitLab CI/CD 변수(ONPOD_URL·ONPOD_CLI_URL)로 바꾸면 되고, 사내 인증서는 File 형식 변수 ONPOD_CA_CERT로 넣어요.

자주 묻는 질문

궁금한 것들

이미 GitHub Actions(또는 GitLab CI)를 쓰는데, 바꿔야 하나요?
아니요. onpod ci init은 지금 쓰는 CI에 배포 단계가 든 파일을 하나 더할 뿐이에요. 테스트·빌드 작업은 그대로 두고, 그 브랜치에 push 됐을 때 onpod 배포만 따라붙습니다.
사내 GitLab(직접 설치한 GitLab)에서도 되나요?
됩니다. 저장소 주소로 GitLab을 알아보지 못하면 --provider gitlab을 붙이면 돼요. 사내(온프렘) onpod과 함께 쓰면 사내 러너가 사내 onpod을 직접 불러서 바깥 인터넷 없이 돌아요.
자체 러너(shell executor·docker executor)에서도 도나요?
둘 다 돌아요. docker executor는 alpine 계열 이미지로, shell executor는 이미지 없이 그 서버의 curl과 sha256sum만으로 동작하고 관리자 권한도 필요 없어요. 받은 CLI는 작업이 끝나면 지웁니다.
잘못 배포되면 어떻게 되돌리나요?
onpod app rollback <앱> 한 줄이면 직전 버전(이미지·실행 인자·환경변수까지)으로 돌아가요. 커밋마다 이미지가 남기 때문에 onpod app update <앱> --image :<커밋 12자>로 특정 커밋 버전으로도 다시 빌드 없이 돌아갈 수 있어요.
비용이 따로 드나요?
자동 배포 연결 자체는 무료예요. 드는 건 배포할 때마다 서버에서 빌드하는 잠깐의 CPU 시간뿐이고, 무료 앱은 그 빌드도 무료예요(계정당 하루 30번까지). 웹사이트 배포는 무료입니다. CI가 도는 러너 시간은 GitHub·GitLab 쪽 요금제를 따릅니다.
CI 키는 무엇을 할 수 있나요?
그 앱 하나를 배포·관리하는 것만 할 수 있어요. 다른 앱이나 DB, 결제, 키 관리에는 쓸 수 없고, 기본 1년 뒤 자동으로 만료돼요. 키 원문은 처음 한 번만 보여 주고 CI 파일·로그에는 남지 않아요.
push는 하되 배포는 건너뛰고 싶을 때는요?
커밋 메시지에 [skip ci]를 넣으면 그 push는 배포하지 않아요.

관련 키워드

Git 자동 배포push 자동 배포GitHub Actions 배포GitLab CI 배포CI/CDcontinuous deployment사내 GitLab온프렘 CIonpod ci init

이어 보기

관련 활용 사례

push 하면 배포 끝.

저장소 폴더에서 onpod ci init 한 줄, 또는 코딩 에이전트에게 “push 하면 자동 배포되게 해줘”라고 말하세요.