Page tree
Skip to end of metadata
Go to start of metadata

src : https://www.joinc.co.kr/w/man/12/deb

1. Ubuntu 패키지 저장소 만들기

우분투 리눅스 운영체제는 데비안으로 부터 파생된 .deb 기반의 패키지 관리 시스템을 가지고 있다. 나는 현재 개발 중인 애플리케이션을 효율적으로 배포하기 위해서 프라이빗 패키지 저장소를 만들기로 했다. 배포 프로세스는 다음과 같다.


 배포프로세스

  1. Git을 이용해서 개발한다.
  2. CI툴은 git에서 코드를 가져와서 최신 빌드를 만든다.
  3. 빌드가 끝나면 .deb 로 만들어서 패키지 저장소에 복사한다.
  4. apt-get을 이용해서 패키지를 설치한다.


2. deb 패키지 만들기

현재 시간을 출력하는 간단한 웹 애플리케이션을 만들고, 이것을 deb 패키지로 만들어서 배포하려고 한다.


2.1. 테스트 애플리케이션


테스트용 go 애플리케이션이다. 애플리케이션의 이름은 mydate다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

package main

import (
"fmt"
"net/http"
"time"
)

func date(w http.ResponseWriter, r *http.Request) {
t := time.Now()
fmt.Fprintf(w, t.Format(time.RFC3339))
}
func main() {
http.HandleFunc("/time", date)
http.ListenAndServe("localhost:8082", nil)
}


애플리케이션의 빌드 디렉토리는 /home/workspace/mydate다. 아래와 같이 구성했다.

1
2
3
4
5

/home/workspace/mydata
├── dist
│ └── mydate
├── Makefile
└── mydate.go

  • mydata : mydata.go와 Makefile등 프로젝트를 위한 주요 파일들을 배치한다.
  • mydata/dist : .deb 배포파일을 만들기 위한 루트 디렉토리다.
  • mydata/dist/mydate : .deb 파일이 만들어지는 작업 디렉토리다. .deb 파일을 위한 메타파일, 패키징에 포함될 각종 파일들이 위치한다.


2.2. 애플리케이션 구성


제일 먼저 애플리케이션 배포를 위한 디렉토리를 설계했다.

1
2
3
4
5
6
7

/
├── etc
│ └── init.d
└── opt
└── joinc
├── bin
└── conf

  • /etc/init.d : mydate init.d 스크립트가 위치한다. 빈파일 하나 만들어서 테스트 한다.
  • /opt/joinc : joinc에서 배포하는 모든 애플리케이션에 여기에 복사한다.
  • /opt/joinc/bin : mydata 실행 파일을 복사한다.
  • /opt/joinc/conf : mydata 설정 파일을 복사한다. 설정파일의 이름은 mydata.ini다. 빈파일로 테스트 한다.


2.3. 패키징을 위한 디렉토리 생성


앞서 만든 애플리케이션 구성 계획에 따라서 패키징 디렉토리를 만든다. dist/mydate밑에 DEBAIN 디렉토리와 앞서 설계한 배포 디렉토리를 만들었다. 현재 디렉토리 구조는 아래와 같다.

1
2
3
4
5
6
7
8
9
10
11
12

/mydate
├── dist
│ └── mydate
│ ├── DEBIAN
│ ├── etc
│ │ └── init.d
│ └── opt
│ └── joinc
│ ├── bin
│ └── conf
├── Makefile
└── mydate.go



2.4. control 파일 만들기


DEBIAN 디렉토리 밑에는 패키징 정보를 담고 있는 control 파일이 위치한다. dpkg 명령은 control 파일을 읽어서 .deb 파일을 만든다. deb 패키징을 위한 핵심 파일이라고 할 만하다. 아래는 mydate를 위한 control 파일예제다.

1
2
3
4
5
6
7
8
9
10
11
12
13

Package: mydate
Version: 1.0.3
Section: devel
Priority: optional
Architecture: amd64
Depends: cmake, sqlite3
Recommends: libsqlite3-dev
Maintainer: yundream <yundream@gmail.com>
Homepage: http://www.joinc.co.kr
Description: mydate web api server
1.0.1 : message #1
1.0.2 : message #2
1.0.3 : message #3

Package 이름은 mydate이고, 버전은 1.0.3이며 amd64 아키텍처에서 작동하는 프로그램이라는 걸 지시하고 있다. Description에는 애플리케이션의 설명과 최근 변경 정보를 설정했다.


이제 배포할 파일들을 dist/mydate 밑에 있는 각 디렉토리에 복사하자.

1
2
3

# cp mydate dist/mydate/opt/joinc/bin
# cp mydate.ini dist/mydate/opt/joinc/conf
# cp mydate.init dist/mydate/etc/init.d/mydate



2.5. .deb 패키지 생성


dpkg로 deb 패키지를 만들어 보자. dist 디렉토리로 이동 한 다음 아래 명령을 실행한다.

1
2
3
4

# dpkg -b mydate
dpkg-deb: `mydate' (`mydate.deb').
# ls
mydate mydate.deb

mydate/DEBIAN/control 내용을 읽어서 mydate.deb 파일을 만들었다. dpkg로 패키지 정보를 확인 할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# dpkg -I mydate.deb
new debian package, version 2.0.
size 1655280 bytes: control archive=344 bytes.
313 bytes, 13 lines control
Package: mydate
Version: 1.0.3
Section: devel
Priority: optional
Architecture: amd64
Depends: cmake, sqlite3
Recommends: libsqlite3-dev
Maintainer: yundream <yundream@gmail.com>
Homepage: http://www.joinc.co.kr
Description: mydate web api server
1.0.1 : message #1
1.0.2 : message #2
1.0.3 : message #3



2.6. .deb 패키지 설치및 삭제


mydate.deb를 설치해보자.

1
2
3
4
5
6
7
8
9
10

# sudo dpkg -i mydate.deb
[sudo] password for yundream:
Selecting previously unselected package mydate.
( ... 290768 .)
Preparing to unpack mydate.deb ...
Unpacking mydate (1.0.3) ...
mydate (1.0.3) ...
Processing triggers for systemd (225-1ubuntu9.1) ...
Processing triggers for ureadahead (0.100.0-19) ...
ureadahead will be reprofiled on next reboot

-L 옵션으로 설치한 파일들을 확인할 수 있다.

1
2
3
4
5
6
7
8
9
10
11

# dpkg -L mydate
/.
/etc
/etc/init.d
/etc/init.d/mydate
/opt
/opt/joinc
/opt/joinc/bin
/opt/joinc/bin/mydate
/opt/joinc/conf
/opt/joinc/conf/mydate.ini


-r 명령으로 삭제 할 수 있다.

1
2
3
4
5

# dpkg -r mydate
( ... 290773 .)
Removing mydate (1.0.3) ...
Processing triggers for systemd (225-1ubuntu9.1) ...
Processing triggers for ureadahead (0.100.0-19) ...



3. 원격 apt 패키지 저장소 만들기


격에 패키지 저장소를 만들기로 했다. 구축이 된다면, apt-get명령을 이용해서 패키지의 설치, 업그레이드, 삭제등을 수행 할 수 있다. 특히 Chef등의 프로비저닝 툴과 통합하면 높은 완성도의 애플리케이션 관리 시스템을 구축할 수 있다.


패키지 저장소의 IP 주소는 192.168.56.5다.

3.1. 웹 서버 설치 및 패키지 디렉토리 생성

apt 패키지 시스템은 HTTP프로토콜을 사용한다. NginX웹 서버를 설치했다.

1

# apt-get install -y nginx

NginX의 루트 디렉토리는 /var/www/html 이다. 여기에 deb 패키지 파일을 복사하기 위해서 stable devel 디렉토리를 만들었다. stable 디렉토리는 테스트와 안정화가 끝난 릴리즈 단계의 패키지, devel 에는 테스트 중인 패키지가 복사된다.

1
2
3

# cd /var/www/html
# mkdir -p joinc/stable
# mkdir -p joinc/devel



3.2. apt 저장소 업데이트


앞서 만든 mydate.deb 파일을 joinc/stable로 복사한다.

1

# cp mydate.deb /var/www/html/joinc/stable/


dpkg-scanpackages 명령으로 패키지 정보를 담고 있는 Packages.gz파일을 만들었다. 패키지를 사용하는 측은 이 파일을 읽어서, 패키지목록을 만든다.

1
2
3
4
5

# cd /var/www/html/joinc
# dpkg-scanpackages stable /dev/null | gzip -9c > stable/Packages.gz
dpkg-scanpackages: warning: Packages in archive but missing from override file:
dpkg-scanpackages: warning: mydate
dpkg-scanpackages: info: Wrote 1 entries to output Packages file.


zcat으로 Packages.gz 파일을 보면, control 파일에 있던 내용들이 그대로 담겨있는 걸 알 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# zcat stable/Packages.gz
Package: mydate
Version: 1.0.3
Architecture: amd64
Maintainer: yundream <yundream@gmail.com>
Depends: cmake, sqlite3
Recommends: libsqlite3-dev
Filename: stable/mydate.deb
Size: 1655280
MD5sum: cc3ae6b4c782b7edea7c25ed0525575a
SHA1: 639a44b621dcbda773dd768a7ef26014e4cc43e7
SHA256: 4d880e5b1ebf58cf83b1487d636918853e6dc4a299746414756f526d37cc3833
Section: devel
Priority: optional
Homepage: http://www.joinc.co.kr
Description: mydate web api server
1.0.1 : message #1
1.0.2 : message #2
1.0.3 : message #3



3.3. apt-get을 이용해서 패키지 인스톨 하기


인스턴스를 하나 만든 다음 apt-get을 이용해서 mydate 패키지를 설치해보자. /etc/apt/sources.list에 저장소를 추가하고 update 한다.

1
2
3

# cat /etc/apt/sources.list
deb http://192.168.56.1/joinc/ stable/
# apt-get update

apt-cache로 패키지를 확인 할 수 있다.

1
2

# apt-cache search mydate
mydate - mydate web api server

install 명령으로 패키지를 설치할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# apt-get install mydate
...

...
:
libsqlite3-dev
:
sqlite3-doc
:
libsqlite3-dev mydate
0 , 2 , 0 85 .
2,143 k .
1,616 k .
? [Y/n] Y
: !
mydate
? [y/N]



4. control 파일 관리


control 파일로 부터 deb파일을 만들고 apt 저장소에 올리는 방법까지 살펴봤다. 하지만 실제 프로젝트에서 사용하려면 control 파일을 자동으로 관리 할 수 있어야 한다. 즉

  1. 패키지의 버전을 관리 해야 한다. control 파일의 Version 필드를 수작업으로 변경 할 수는 없는 노릇이다.
  2. description에 있는 메시지도 자동으로 관리해야 한다. git의 가장 최근 로그를 남기겨야 할 테다.

등의 작업을 해야 한다.


4.1. 버전과 로그 관리


git 버전과 연동하면 된다.


tag 명령을 이용해서, 현재 코드에 버전을 붙인다.

1
2

# git tag -a 1.0 -m "function a edit"
# git push

이제 코드를 commit 할 때마다 버전정보가 갱신이 된다. 현재 버전 정보는 git describe --tags 로 읽을 수 있다.

1
2

# git describe --tags
1.0-1-gdf2d7ed

이렇게 읽어온 버전 정보로 control 파일을 만들면 된다.


로그도 git 명령으로 읽어올 수 있다.

1
2
3
4
5
6

# git log -5 --pretty=format:"%ci %h %s"
2016-05-22 01:00:51 +0900 df2d7ed README
2016-03-25 12:05:41 +0900 eddd1d1 Debug #1
2016-02-16 13:52:38 +0830 73b29b8 Debug #2
2016-02-16 13:40:16 +0830 36faae2 Debug #3
2016-02-16 12:25:13 +0830 7278adb Debug #4

이 내용으로 control 파일의 Description을 만들 면 된다.



4.2. Makefile


control 파일을 만들고, control 파일로 부터 deb를 만드는 등의 작업은 Makefile로 자동화 할 수 있다. 대략 아래와 같은 느낌이 될 거다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# cat Makefile
default: build
# .
Version=$(shell git describe --tags)
devDir=/var/www/html/joinc/stable
releaseDir=/var/www/html/joinc/devel

build:
go build -ldflags "-X main.Version=$(Version)"

deb:
# build .
# control 릿 DEBIAN/control .
# dpkg -b deb .
# deb devel .
# dpkg-scanpackages Packages .

release:
# deb stable .
# dpkg-scanpackages Packages .

control 템플릿 파일은 아래와 비슷할 것이다. go에서 제공하는 템플릿을 기준으로 만들었다.

1
2
3
4
5
6
7
8
9
10
11

Package: mydate
Version: {{.Version}}
Section: devel
Priority: optional
Architecture: amd64
Depends: cmake, sqlite3
Recommends: libsqlite3-dev
Maintainer: yundream <yundream@gmail.com>
Homepage: http://www.joinc.co.kr
Description: mydate web api server
{{.Log}}

나는 git 레포지토리 정보를 읽어서 Version과 Log를 가져와서 템플릿파일로 부터 control을 만드는 간단한 프로그램을 만들었다. 이제 Jenkins와 같은 CI 툴과 연동하면, 완전한 배포 시스템을 만들 수 있다.

  • No labels