소개
이전 실습에서는 "품질 관리"(CI) 에 대해 배웠습니다. 이제 다음 단계인 패키징으로 넘어갑니다.
소프트웨어를 공장에서 생산하는 제품이라고 생각해 보겠습니다. 모든 품질 검사를 통과한 제품은 고객에게 배송하기 전에 상자에 넣고, 밀봉하고, 라벨을 붙여야 합니다. 소프트웨어 세계에서 이 "상자" 역할을 하는 것이 바로 Docker 컨테이너입니다.
이렇게 패키징된 결과물을 아티팩트라고 합니다. 빌드가 완료된 아티팩트는 레지스트리에 저장해야 이후 배포 단계에서 동일한 빌드 결과물을 가져올 수 있습니다.
이러한 재현성이 핵심입니다. 배포할 때는 대상 시스템마다 코드를 다르게 다시 빌드하는 대신, 이미 확인된 빌드 결과물을 사용해야 합니다.
GitHub 는 GitHub Container Registry(GHCR) 라는 레지스트리를 제공합니다.
이 실습에서는 로봇 도우미가 다음 작업을 수행하도록 설정합니다.
- 애플리케이션을 Docker 컨테이너로 패키징합니다.
- 버전 태그로 라벨을 지정합니다.
- GitHub 저장소에 자동으로 전송(푸시) 합니다.
사전 요구 사항
계속해서 github-actions-basics 저장소를 사용합니다.
Dockerfile 만들기
로봇이 애플리케이션을 패키징하려면 먼저 지침이 필요합니다. Docker 에서는 이 지침을 Dockerfile이라는 특수한 파일에 작성합니다.
프로젝트 디렉터리로 이동합니다.
cd ~/project
git clone https://github.com/your-username/github-actions-basics.git
cd github-actions-basics
참고: your-username을 실제 GitHub 사용자 이름으로 바꾸세요.
다음 내용으로 Dockerfile이라는 파일을 만듭니다. 파일 이름의 첫 글자는 대문자 D이고 확장자는 없습니다.
cat > Dockerfile << EOF
FROM node:16-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
CMD ["node", "index.js"]
EOF
이 패키징 지침은 로봇에게 다음 작업을 수행하도록 지시합니다.
FROM node:16-alpine: Node.js 가 이미 설치된 경량 기본 시스템에서 시작합니다.WORKDIR /app: 컨테이너 안에 작업 디렉터리를 만듭니다.COPY ...: 프로젝트 파일을 컨테이너 안으로 복사합니다.RUN npm install: 컨테이너 안에 필요한 종속 항목을 설치합니다.CMD ...: 누군가 이 컨테이너를 실행하면 애플리케이션을 시작합니다.
이제 파일을 저장소에 추가하고 GitHub 에 푸시합니다.
git add Dockerfile
git commit -m "Add Dockerfile"
git push
게시 워크플로 만들기
이제 패키징과 전송을 처리할 새 워크플로를 만듭니다. 워크플로 이름은 docker-publish.yml로 지정합니다.
파일을 만듭니다.
touch .github/workflows/docker-publish.yml
nano로 파일을 엽니다.
nano .github/workflows/docker-publish.yml
다음 설정을 추가합니다. 여기서는 permissions라는 새로운 개념을 사용합니다.
name: Docker Publish
on:
push:
branches: ["master", "main"]
permissions:
contents: read
packages: write
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
권한이 필요한 이유
보안을 위해 로봇은 기본적으로 제한된 접근 권한만 가집니다. 로봇이 GitHub 계정의 "packages" 영역에 항목을 업로드하도록 하려면 레지스트리에 접근할 수 있는 키를 명시적으로 제공해야 합니다. packages: write가 바로 그 역할을 합니다.
이는 파이프라인 설계에서 최소 권한 원칙을 보여 주는 좋은 예입니다. 워크플로에는 수행할 작업에 필요한 권한만 부여해야 합니다.
nano에서 저장하고 종료합니다 (Ctrl+X, Y, Enter).
빌드 및 푸시 단계 추가하기
이제 가장 중요한 부분인 실제 빌드와 푸시를 확인합니다.
Docker 에서 제공하는 공식 도구 (action) 두 가지를 사용합니다.
docker/login-action: 레지스트리에 로그인합니다.docker/build-push-action: 컨테이너를 빌드하고 전송합니다.
이 단계는 CI 와 전달 과정을 연결합니다. 테스트가 통과하면 파이프라인이 버전이 지정된 아티팩트를 만들고, 다른 시스템은 소스에서 다시 빌드하지 않고 나중에 이 아티팩트를 배포할 수 있습니다.
.github/workflows/docker-publish.yml을 다시 엽니다.
nano .github/workflows/docker-publish.yml
build-and-push 작업에 다음 단계를 추가합니다.
- name: Log in to the Container registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Docker image
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: ghcr.io/${{ github.repository }}/app:latest
특수 변수 이해하기
ghcr.io: GitHub "레지스트리"의 주소입니다.${{ github.actor }}: GitHub 사용자 이름을 자동으로 입력하는 변수입니다.${{ secrets.GITHUB_TOKEN }}: GitHub 가 로봇을 위해 생성하는 특별한 임시 비밀번호입니다. 별도로 할 일 없이 자동으로 작동합니다. 이 토큰을 사용하면 비밀번호를 직접 입력하지 않고도 로봇이 안전하게 로그인할 수 있습니다.tags: 컨테이너에 붙일 라벨을 만듭니다. 형식은레지스트리 주소 / 사용자 이름 / 저장소 이름 / 애플리케이션 이름 : 버전입니다.
nano에서 저장하고 종료합니다.
이제 이 워크플로를 GitHub 에 푸시하여 프로세스를 시작합니다.
git add .
git commit -m "Add Docker publishing workflow"
git push
아티팩트 확인하기
이제 로봇이 작업을 시작합니다. 서버를 설정하고, 로그인하고, 컨테이너를 빌드한 다음 업로드합니다.
- GitHub 에서 저장소로 이동합니다.
- Actions 탭을 클릭합니다.
- "Docker Publish" 워크플로 실행을 클릭합니다.
- 각 단계가 녹색으로 바뀌는지 확인합니다.

"Build and push Docker image" 단계가 성공적으로 완료되면 패키지가 레지스트리에 저장된 것입니다. 이제 패키지를 확인합니다.
- 저장소의 기본 페이지 (Code 탭) 로 이동합니다.
- 오른쪽 사이드바를 확인합니다. Packages 섹션이 표시되어야 합니다.
- 해당 섹션에 새 패키지가 표시됩니다.
패키지 이름을 클릭하면 세부 정보를 확인할 수 있습니다. 이것이 완성된 아티팩트입니다. 저장소에 접근할 수 있는 사용자 또는 저장소가 공개된 경우 모든 사용자가 이 이미지를 사용해 애플리케이션을 다운로드하고 실행할 수 있습니다.

요약
이 실습에서는 완전한 전달 파이프라인을 구축했습니다.
다음 내용을 배웠습니다.
- 패키징:
Dockerfile을 작성해 애플리케이션을 컨테이너에 넣는 방법 - 권한: 워크플로에 패키지 쓰기 권한을 부여하는 방법
- 레지스트리 저장: GitHub Container Registry(GHCR) 를 사용해 이미지를 저장하는 방법
- 자동화: 표준 action 을 사용해 코드를 자동으로 빌드하고 전송하는 방법
이제 로봇 도우미가 코드 확인 (CI) 과 코드 전송 (아티팩트) 을 수행할 수 있습니다. 다음 실습에서는 비밀번호와 같은 민감한 정보를 안전하게 처리하는 방법을 살펴봅니다.



