개발자의 오르막

Go, Makefile, Docker로 프로젝트 셋팅 및 빌드 정보 활용하기 본문

GoLang

Go, Makefile, Docker로 프로젝트 셋팅 및 빌드 정보 활용하기

계단 2022. 10. 8. 11:00

 

Keyword


golang , build , makefile , docker

 

 

Overview


실무에서 프로젝트를 구축할 때, 빌드 자동화, 버전관리 등에 대한 작업을 해야한다.

또한 배포할 때 우리가 빌드했던 프로젝트를 이미지화해서 원하고자 하는 버전을 서버에 배포할 수 있다. 이러한 작업들을 도와주는 Tool 이 바로 Makefile 과 Docker 이다.

  • Makefile
  • Dockerfile

Golang 프로젝트를 생성하고, Makefile 과 Dockerfile 을 활용해서 간단한 Golang 어플리케이션을 생성해 본다.

 

 

 

 

Go 프로젝트 실습


1. Go 프로젝트 디렉터리 생성

 

2. go 모듈 생성

Go module 은 go 패키지들의 종속성을 관리하는 패키지 관리 시스템이다.

go mod init {프로젝트 디렉터리명}
  • 최초 디렉터리에서 go.mod 를 설치하기 위해 위의 명령어를 실행한다.
  • go.mod 파일이 생성된다.

 

 

3. Go Application 실행 파일 생성

Go 에서 실행파일은 main package 의 *.go 파일이다.

Go 언어의 모든 코드는 반드시 패키지 선언으로 시작해야 한다.

main 패키지는 프로그램 시작점을 포함하는 특별한 패키지이다.

  • watcher.go
package main

func main() {
}

 

  • 실제로 main 패키지에 없이 코드상으로만 package main 을 명시하기만 하면 정상적으로 실행되지만 main 를 생성하여 *.go 파일을 만드는 것을 추천한다.
  • 실행파일 watcher.go 에 코드가 많아질 경우 같은 main package 안의 .go 파일의 import 가 가능하기 때문이다.
  • watcher.go 에서 Go 애플리케이션을 실행할 수 있다.

 

 

 

4. Build에 필요한 파일 생성

Build 를 하기에 앞서 해당 빌드 정보를 버전관리할 수 있도록 활용하는 방법이 있다.

  • 현재 빌드하는 Go 모듈의 버전을 version 1.x.x 로 표기하기를 원한다.
  • Go 모듈을 빌드하는 작업을 자동화하기 위해 Makefile 을 활용한다.
    • Makefile 은 linux 상에서 반복적으로 발생하는 컴파일을 쉽게하기 위해서 사용하는 make 프로그램의 설정 파일이다.
    • Makefile 을 통해 다양한 버전 정보, 빌드 옵션을 make 명령어로 자동화할 수 있다.

 

 

 

Makefile


Makefile 은 linux 상에서 반복적으로 발생하는 컴파일을 쉽게하기 위해서 사용하는 make 프로그램의 설정 파일이다.

Makefile 을 통해 다양한 버전 정보, 빌드 옵션을 make 명령어로 자동화할 수 있다.

 

 

Makefile 은 위의 이미지와 같이 해당 프로젝트 최상단에 Makefile 을 생성한다.

  • build.num 파일을 생성한다.
0
  • version.txt 파일을 생성한다.
1.0
  • Makefile 예시
CC=go
PROJECT_PATH=$(shell pwd)
PROJECT_NAME=sample
MODULE_NAME=sample
TARGET_DIR=bin
VERSION_FILE=version.txt
VERSION=$$(cat version.txt)
BUILD_NUM_FILE=build_num.txt
OUTPUT=$(PROJECT_PATH)/$(TARGET_DIR)/$(MODULE_NAME)_$(VERSION).$$(cat $(BUILD_NUM_FILE))
MAIN_DIR=/main
LDFLAGS=-X main.BUILD_TIME=`date -u '+%Y-%m-%d_%H:%M:%S'`
LDFLAGS+=-X main.GIT_HASH=`git rev-parse HEAD`
LDFLAGS+=-X main.BUILD_NUMBER=$$(cat $(BUILD_NUM_FILE))
LDFLAGS+=-X main.VERSION_NUMBER=$$(cat $(VERSION_FILE))
LDFLAGS+=-s -w

all: clean sample

#go build -ldflags "$(LDFLAGS)" -o ${OUTPUT} .
sample:
	@echo $$(($$(cat $(BUILD_NUM_FILE)) + 1 )) > $(BUILD_NUM_FILE)
	CGO_ENABLED=0 GOOS=linux go build -ldflags "$(LDFLAGS)" -o $(OUTPUT) $(PROJECT_PATH)$(MAIN_DIR)
	cp $(OUTPUT) ./docker/$(MODULE_NAME)

clean:
	rm -f $(PROJECT_PATH)/$(TARGET_DIR)/$(MODULE_NAME)_$(VERSION)*
  • Makefile 은 최상단에 사용할 변수들을 선언한다.
    • CC 는 Makefile 에서 goalng compiler 를 의미한다.
    • TARGET_DIR 은 해당 Makefile 로 만든 bulid 파일을 보관할 디렉터리를 의미한다.
    • MAIN_DIR 은 go 어플리케이션에서 패키징할 패키지를 의미한다.
    • LDFLAGS 는 golang 의 build 옵션으로 빌드 정보를 담아주는 역할을 한다.
    • OUTPUT 은 go 어플리케이션을 패키징할 때 생성되는 파일의 위치이다.
  • 그 후 매크로로 등록할 키워드와 명령어를 입력해준다.
    • all : make all 명령어를 통해 all 에 표기된 clean 과 reporter 를 실행시켜준다.
    • $(BUILD_NUM_FILE) : 다른 키워드가 실행되기 전에 먼저 실행되는 명령어이다.
    • reporter : build 번호를 업데이트하며 go 프로젝트의 빌드 명령어를 수행한다.
      • reporter 에서 생성되는 파일은 배포를 용이하게 하기 위해 /docker 디렉터리에 복사해준다.
    • clean : 기존 build 했던 파일이 있는 디렉터리는 삭제한다.
  • make 키워드를 해당 프로젝트 위치에서 실행시키면 Makefile 로 실행되는 명령어에 대한 로그와 함께 /bin/reporter실행파일이 생성됨을 알 수 있다.

 

 

Dockerfile


다음은 Dockerfile 을 작성해봅시다. 앞서 Makefile 로 생성한 실행파일을 서버환경에서 배포하기 위한 작업을 자동화해주는 것이 Dockerfile 입니다.

Docker 와 관련된 파일이 여러개가 될 수 있으니, docker 디렉터리를 생성해서 그 하위에 Dockerfile 을 생성해줍니다.

Docker 의 장점은 위에서 생성된 실행파일만을 서버에 배포하여 실행시키기 때문에 서버에 소스코드와 같은 파일 없이 배포할 수 있어 경량화를 유지할 수 있습니다.

 

 

 

 

 

Dockerfile 구문 및 옵션

  • Dockerfile
FROM alpine

MAINTAINER jake <arneg0shua@gmail.com>

ENV APP_UID 2001
ENV APP_USER gig
ENV APP_GROUP gig

ENV API_LOG_PATH /home/gig/log/reporter.log
ENV API_PORT 8085

RUN apk add curl

# PID 2001로 gig User 생성
RUN adduser $APP_USER -h /home/$APP_USER -u $APP_UID -D

# gig에서 작업
WORKDIR /home/gig
USER gig

RUN mkdir /home/gig/log && chmod -R 777 /home/gig/log

COPY ./reporter /home/gig/reporter

CMD /home/gig/reporter

EXPOSE 8081
EXPOSE 443
  • APP_UID : 사용자 식별자
  • FROM : Docker Base Image (기반이 되는 이미지, <이미지 이름>:<태그> )
  • MAINTAINER : 메인테이너 정보 (작성자 정보)
  • RUN : Shell Script 또는 명령을 실행
  • CMD : 컨테니어가 실행되었을 때 명령이 실행
  • LABEL : 라벨 작성 (docker inspect 명령으로 label 확인 가능)
  • EXPOSE : 호스트와 연결할 포트 번호를 설정
  • ENV : 환경변수 설정
  • ADD : 파일 / 디렉터리 추가
  • COPY : 파일 복사
  • ENTRYPOINT : 컨테니어가 시작되었을 때 스크립트 실행
  • VOLUME : 볼륨 마운트
  • USER : 명령 실행할 사용자 권한 지정
  • WORKDIR : “RUN” , “CMD” , “ENTRYPOINT” 명령이 실행될 작업 디렉터리
  • ARG : Dockerfile 내부 변수
  • ONBUILD : 다른 이미지의 Base Image 로 쓰이는 경우 실행될 명령 수행
  • SHELL : Default Shell 지정

이로써 우리는 Dockerfile 을 통해 도커 이미지를 생성할 수 있다.

그러나 우리는 도커 build 명령어부터 도커 Repository 에 이미지를 push 하는 것까지 명령어를 실행시켜줘야 한다.

이 부분은 shell script 를 통해 자동화를 한다.

 

 

 

Docker 쉘 스크립트 파일


  • make_docker.sh
#!/bin/bash

BUILD_NUM=$(cat ../build_num.txt)
APP_VERSION=$(cat ../version.txt)
TARGET_VERSION="$APP_VERSION.$BUILD_NUM"
target="kjuiop/reporter"

function usage() {
	echo 'Usage: ./make_docker.sh'
	echo 'example: ./make_docker.sh'
	echo 'or'
	exit 1
}

function question() {
	# 아래의 $1 은 이 함수의 파라미터 임.
	while true; do
		read -p "$1" yn
		case $yn in
			yes ) break;;
			y ) break;;
			no ) exit;;
			n ) exit;;
			* ) echo "Please answer yes or no.";;
		esac
	done
}

question "Do you want to DOCKET BUILD to [$target:$TARGET_VERSION]? (yes/no) "

echo "========================================"
echo "BUILD_NUM      : ${BUILD_NUM}"
echo "APP_VERSION    : ${APP_VERSION}"
echo "TARGET_VERSION : ${TARGET_VERSION}"
echo "========================================"

docker build -f Dockerfile --tag $target:$TARGET_VERSION .
docker build -f Dockerfile --tag $target:latest .

question "Do you want to PUSH to [$target:$TARGET_VERSION]? (yes/no) "
docker push $target:$TARGET_VERSION
docker push $target:latest
  • make_docker.sh 파일을 실행하기 위해서는 권한 부여가 필요하다. chmod 777 ./make_docker.sh
  • make_docker.sh 파일을 실행하면 도커 이미지가 원격 레파지토리로 push 된다.

 

 

 

Reference


 

Comments