오토에버 클라우드 2기 36일차
git action을 이용해서 도커 이미지를 도커 허브에 배포
1. 소스 파일을 작성
1
2
3
4
5
6
7
8
9
10
11
12
// hello.go
package main
import (
"fmt"
"os"
)
func main() {
fmt.Printf("Hello, World\n")
fmt.Fprintln(os.Stdout, "go go go go")
}
로컬에서 실행 테스트 터미널에서 아래 명령어를 실행하여 애플리케이션이 정상적으로 동작하는지 확인
go run hello.go
2. 이미지 생성 및 컨테이너 구동
도커 이미지를 만드는 방법으로는 컨테이너를 만들고 커밋 명령을 이용해서 컨테이너를 이미지로 생성(명령 이용)
dockerfile을 이용해서 이미지 생성
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# Dockerfile
# 1. 빌드 스테이지 (Build Stage)
# Go 소스 코드를 컴파일하여 실행 파일을 만듭니다.
FROM golang:1.15-alpine3.12 AS gobuilder-stage
# 작업 디렉터리 설정
WORKDIR /usr/src/goapp
# 현재 디렉터리의 go 파일을 컨테이너의 작업 디렉터리로 복사
COPY hello.go .
# Go 애플리케이션을 빌드합니다.
# CGO_ENABLED=0: C 라이브러리 의존성 없이 빌드하여 정적 바이너리 생성
# GOOS=linux GOARCH=amd64: 리눅스 amd64 환경용으로 크로스 컴파일
# -o: 생성될 실행 파일의 경로와 이름 지정
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /usr/local/bin/gostart
# ---
# 2. 런타임 스테이지 (Runtime Stage)
# 실제 애플리케이션을 실행할 최종 이미지를 만듭니다.
# 'scratch'는 비어있는 가장 작은 베이스 이미지입니다.
FROM scratch AS runtime-stage
# 빌드 스테이지에서 생성된 실행 파일만 복사합니다.
# 이렇게 하면 Go 컴파일러나 소스 코드 없이 실행 파일만 포함되어 이미지 용량이 매우 작아집니다.
COPY --from=gobuilder-stage /usr/local/bin/gostart /usr/local/bin/gostart
# 컨테이너가 시작될 때 실행할 기본 명령어 설정
CMD ["/usr/local/bin/gostart"]
로컬에서 이미지 빌드 및 테스트 Dockerfile 작성이 완료되면, 로컬에서 이미지를 빌드하고 컨테이너를 실행하여 정상적으로 동작하는지 확인
이미지 빌드 docker build -t goapp:1.0 .
컨테이너를 생성해서 확인 docker run --name goapp-deploy goapp:1.0

3. GitHub Actions CI/CD 파이프라인 구축
이제 이 모든 과정을 GitHub Actions를 통해 자동화 main 브랜치에 코드를 push 할 때마다 자동으로 이미지를 빌드하고 Docker Hub에 배포하도록 설정한다
GitHub Actions 핵심 개념 정리
Workflow: 자동화된 전체 프로세스. .github/workflows/ 디렉터리에 YAML 파일로 정의
- Event: 워크플로우를 실행시키는 특정 활동 (예: push, pull_request)
- Job: 하나 이상의 Step으로 구성되며, 가상 머신(Runner)에서 실행되는 작업 단위
- Step: Job 내에서 순차적으로 실행되는 개별 명령어 또는 Action
- Action: 워크플로우의 가장 작은 빌드 블록으로, 재사용 가능한 코드 조각 (예: actions/checkout, docker/login-action)
- Runner: 워크플로우가 실행될 가상 환경 (예: ubuntu-latest, windows-latest)
GitHub Repository Secrets 설정
보안을 위해 Docker Hub 계정 정보(사용자 이름, 비밀번호/토큰)를 코드에 직접 노출하면 안된다 GitHub의 Secrets 기능을 사용하여 안전하게 관리
Docker Hub Access Token 생성:
Docker Hub에 로그인 후, Account Settings > Security > New Access Token으로 이동하여 토큰을 생성
GitHub Repository Secrets 등록:
- 자동화할 GitHub 저장소로 이동
- Settings > Secrets and variables > Actions 메뉴로 이동
- New repository secret 버튼을 클릭하여 아래 두 개의 Secret을 등록
- DOCKERHUB_USERNAME: Docker Hub 사용자 이름을 값으로 입력
- DOCKERHUB_TOKEN: 위에서 생성한 Docker Hub Access Token을 값으로 입력
Workflow YAML 파일 작성 및 설명
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# .github/workflows/actiontest.yml
# 워크플로우의 이름
name: Docker Image CI for Go App
# 워크플로우를 트리거할 이벤트 설정
on:
# 'main' 브랜치에 push 이벤트가 발생했을 때 실행
push:
branches: ["main"]
# 실행될 작업(들)을 정의
jobs:
# 'build-and-push' 라는 이름의 Job 정의
build-and-push:
# 이 Job이 실행될 가상 환경(Runner) 지정
runs-on: ubuntu-latest
# Job 내에서 실행될 단계(Step)들
steps:
# 1. 소스 코드 체크아웃
# Runner에 레포지토리의 소스 코드를 가져옵니다.
- name: Checkout repository
uses: actions/checkout@v3
# 2. Docker Hub 로그인
# actions/login-action을 사용하여 Docker Hub에 로그인합니다.
# 사용자 이름과 토큰은 위에서 설정한 GitHub Secrets에서 가져옵니다.
- name: DockerHub Login
uses: docker/login-action@v2
with:
username: $
password: $
# 3. Docker 이미지 빌드 및 푸시
# Docker 이미지를 빌드하고 태그를 지정한 후, Docker Hub에 푸시합니다.
- name: Build and push Docker image
uses: docker/build-push-action@v3
with:
# Dockerfile이 있는 경로 (현재 디렉토리)
context: .
# 이미지를 Docker Hub로 푸시
push: true
# 이미지 태그 설정. <DockerHub유저명>/<레포지토리명>:latest 형식
tags: $/actiontest:latest
4. 워크플로우 실행 및 검증
1
2
3
git add .
git commit -m "Add Go app, Dockerfile, and GitHub Actions workflow"
git push origin main

최종 검증
이후 온라인 도커 이미지를 가져와서 빌드해본다
1
docker run --rm minnnning/actiontest:latest

도커 컴포즈
Dockerfile이 단일 애플리케이션을 이미지로 만드는 도구라면, Docker Compose는 여러 개의 컨테이너로 구성된 복잡한 애플리케이션 스택(예: 웹서버 + 데이터베이스 + 캐시서버)을 하나의 파일(docker-compose.yml)로 정의하고, 한 번의 명령어로 전체 시스템을 실행, 중지, 관리할 수 있게 해주는 도구
docker-compose.yml 주요 항목
- version: 파일 형식 버전을 지정
- services: 실행할 각 컨테이너(서비스)를 정의하는 최상위 키
- image: 서비스에서 사용할 Docker 이미지를 지정
- build: Dockerfile 경로를 지정하여 이미지를 직접 빌드할 수 있ek
- ports: 호스트와 컨테이너 간의 포트를 매핑 (-p 옵션과 동일)
- volumes: 호스트와 컨테이너 간의 디렉터리나 파일을 공유 (-v 옵션과 동일)
- environment: 컨테이너 내에서 사용할 환경 변수를 설정 (-e 옵션과 동일)
- depends_on: 다른 서비스에 대한 의존 관계를 설정하여 서비스 시작 순서를 제어
- restart: 컨테이너가 예기치 않게 종료되었을 때 재시작 정책을 설정 (예: always, on-failure)
- networks: 컨테이너들이 사용할 가상 네트워크를 정의
- volumes: 데이터 영속성을 위해 사용할 볼륨을 정의
docker-compose.yml 예제
1
2
3
4
5
6
7
8
9
10
11
12
# docker-compose.yml
version: "3.8"
services:
# 서비스의 이름을 'go-app'으로 정의
go-app:
# Docker Hub에 있는 이미지를 사용
image: your-dockerhub-username/actiontest:latest
# 컨테이너 이름을 'my-go-container'로 지정
container_name: my-go-container
# 컨테이너가 종료되면 항상 재시작
restart: always
- 실행: docker-compose.yml 파일이 있는 디렉터리에서 실행합니다. -d는 백그라운드 실행 옵션
docker-compose up -d
- 종료 및 삭제: 컨테이너와 네트워크를 중지하고 삭제
docker-compose down