Cloud/Docker

Docker In Action 7. Packaging software in images

로파이 2024. 12. 6. 22:33

이미지 빌드를 통한 소프트웨어 패키징

 

7.1 컨테이너로 부터 도커 이미지 빌드

 

도커에서 union filesystem (UFS)기반의 마운트를 통해 컨테이너의 파일 시스템 기능을 제공한다.

 

7.1.1 Packaging "Hello, World"

 

예시) 나만의 이미지 빌드

-> 기존 이미지로 컨테이너를 실행하자.

-> 컨테이너의 파일 시스템에 변경 사항을 만들자.

-> 변경 사항을 이미지로 커밋 한다. 

// 1. ubuntu:latest 이미지를 가져와 컨테이너를 실행한 후 HelloWorld 파일을 만든다.
docker container run --name hw_container ubuntu:latest touch /HelloWorld

// 2. 현재 컨테이너를 이미지로 커밋 하자
docker container commit hw_container hw_image

// 3. 기존 컨테이너를 정리
docker container rm -vf hw_container

// 4. 새로운 컨테이너에서 파일을 확인하자
docker container run --rm hw_image ls -l /HelloWorld

 

7.1.2 Git 기반 패키징 준비하기

 

Git 도구를 기존 이미지에 설치해서 패키징을 해보자

 

1) 도커 컨테이너를 하나 실행한다.

docker container run -it --name image-dev ubuntu:latest /bin/bash

 

2) 해당 컨테이너에 git을 설치한다.

apt-get update
apt-get -y install git

git version

exit을 통해 컨테이너 shell을 빠져 나온다.

 

7.1.3 파일 시스템 변경 사항을 확인해본다.

 

1) 파일 추가

docker container run --name tweak-a busybox:latest touch /HelloWorld
docker container diff tweak-a

- A : HelloWorld 파일이 추가되었다.

 

2) 파일 삭제

docker container run --name tweak-d busybox:latest rm /bin/vi
docker container diff tweak-d

- C: /bin 폴더에 변경 사항 존재

- D: /bin/vi 폴더가 삭제되었다.

 

3) 변경사항 만들기

docker container run --name tweak-c busybox:latest touch /bin/vi
docker container diff tweak-c

- C: /bin 폴더에 변경 사항 존재

- D: /bin/vi 폴더가  변경 사항 존재 (접근 시간 기록 등) 

 

 

7.1.4 새로운 이미지 커밋

 

commit 명령어 사용하여 컨테이너로 부터 이미지 만들기

-a 옵션으로 저자 및 -m 메시지를 지정한다.

docker container commit -a "@dockerinaction" -m "Added git" image-dev ubuntu-git

 

docker images {image_name} 이미지 확인하기

 

해당 이미지에 git 도구가 있는 지 확인

docker container run --rm ubuntu-git git version

 

entrypoint 사용하기

해당 옵션을 지정하는 경우, 컨테이너 시작 시 해당 명령어를 기본으로 실행한다. 말 그대로 프로그램 진입점을 의미. 

docker container run --name cmd-git --entrypoint git ubuntu-git

 

해당 컨테이너를 이미지로 커밋하고 다시 실행해보자. 지정한 entrypoint (git) 가 적용된다.

docker container commit -m "Set CMD git" -a "@dockerinaction" cmd-git ubuntu-git

docker contaienr rm -vf cmd-git

docker container run --name cmd-git ubuntu-git version

git version

 

7.1.5 이미지 속성 구성하기

 

commit을 한다는 것은 새로운 layer를 추가하는 것과 같다. commit으로 파일 시스템도 포함하지만 다음 실행 문맥과 관련된 메타 데이터도 layer에 포함된다

 

- 모든 환경 변수

- 기본 작업 폴더 경로

- 공개 포트

- 볼륨 정의

- 컨테이너 진입점

- 실행 명령어와 인수

 

다음 예시는 환경 변수를 이미지 레이어에 추가하는 예시이다.

docker container run --name rich-image-example -e ENV_EXAMPLE1=Rich -e ENV_EXAMPLE2=Example busybox:latest

docker conatiner commit rich-image-example rie

docker container run --rm rie /bin/sh -c "echo \$ENV_EXAMPLE1 \$ENV_EXAMPLE2"

rie 라는 이미지에는 ENV_EXAMPLE1, ENV_EXAMPLE2 환경 변수가 기록된다.

docker container run --name rich-image-example-2 --entrypoint "/bin/sh" rie -c "echo \$ENV_EXAMPLE1 \$ENV_EXAMPLE2"

docker container commit rich-image-example-2 rie

docker contianer run --rm rie

 

entrypoint를 "/bin/sh" 로 지정하고 명령어와 인수를 지정하는 -c 옵션을 사용한다.

해당 이미지에는 entrypoint와 명령어 메타 정보가 기록된다.

 

7.2 Docker 이미지와 레이어 더 알아보기

 

도커는 union fileysystem을 쓰기에 이미지 저자가 다음 중요사항을 알아야한다.

 

1) 저자는 파일의 추가, 삭제, 변경 내역은 이미지에 영향을 준다.

2) 저자는 레이어와 이미지와 관련된 레이어, 레파지토리, 태그와 연관 관계를 알아야한다.

 

mychange 파일을 생성하는 케이스

 

ubuntu:latest 이미지로부터 mod_ubuntu 컨테이너를 실행하고 mychage 파일을 만든다.

docker contaienr run --name mod_ubuntu ubuntu:latest touch /mychange

 

레이어 관점에서 동작

원본 이미지로 부터 새로운 변경 사항은 새로운 레이어 위에 쓰여진다.

- 추가, 삭제, 변경 모두 해당된다.

 

7.2.2 images, layers, repositories, and tags

 

images

union fileysystem은 레이어를 쌓으면서 만들어지며 항상 새로운 레이어가 위에 쌓인다.

 

 현재까지의 변경사항으로 이미지 만들기

docker container commit mod_ubuntu

이제 새로운 이미지 Id는 위와 같다.

 

repository

 

repository에서 이미지 주소는 다음과 같다.

${registry_host}/${user_or_organization_name}/${short_name}
//docker.io/dockerinaction/ch3_hello_registry

 

만약 이 주소로 이미지를 pull 한다면, 항상 short_name에 해당하는 이미지의 latest 태그 버전을 가져온다.

 

태그와 함께 이미지 생성

 

mod_ubuntu 컨테이너를 mytag 태그에 해당하는 myuser/myfirst_repo 이미지로 만든다.

docker container commit mod_ubuntu myuser/myfirstrepo:mytag

 

해당 이미지를 latest 태그로 만든다. (태그 부분이 생략되면 항상 latest)

docker tag myuser/myfirstrepo:mytag myuser/mod_ubuntu

 

7.2.3 이미지 크기와 레이어 제한 관리

 

latest 태그를 다시 (2.7) 태그한다.

docker image tag ubuntu-git:latest ubuntu-git:2.7

 

ubuntu-git에서 git을 제거한 버전으로 이미지를 빌드하고 latest 태그를 부여한다.

docker container run --name image-dev2 --entrypoint /bin/bash ubuntu-git:latest -c "apt-get remove -y git"
docker container commit image-dev2 ubuntu-git:removed
docker image tag ubuntu-git:removed ubuntu-git:latest
docker images "ubuntu-git"

최신 latest 버전에서 이미지 크기가 증가한 것을 볼 수 있다.

 

UFS는 레이어에 파일을 삭제한 사실을 기록하기 때문에 전체 이미지 크기는 변경사항이 많을 수록 커진다.

 

docker image history로 이미지의 변경 내역을 알아본다.

 

다음 정보가 제공된다.

- 축약된 layer ID

- 레이어 나이

- 생성하는 컨테이너의 초기 명령어

- 레이어의 총 파일 사이즈

 

 

docker save로 이미지를 TAR 파일로 내보내서 다시 import 한 다면 이미지 사이즈가 줄어들 수 는 있으나, 이미지 메타 정보를 잃기 때문에 좋은 방법은 아니다.

 

브랜치 방법; 모든 변경사항을 되돌릴 수 있는 이전의 버전으로 돌아가서 이미지를 새로 만드는 것이다. ubuntu-git으로부터 git을 제거하였다면 ubuntu:latest 이미지에서 브랜칭을 하여 목적에 맞는 새로운 이미지를 만든다.

 

7.3 Exporting and importing flat filysystems

 

이미지를 파일로 내보내어 컨테이너나 UFS에 벗어난 문맥에서 관리하는 방법이 있다.

 

docker container export ${컨테이너 이름}

 

위 명령어는 컨테이너를 tar 파일로 내보내는 명령어이다.

docker container create --name export-test dockerinaction/ch7:packed:latest ./echo For Export
docker container export --output contents.tar export-test
docker container rm export-test
tar -tf contents.tar

 

 

 

실행 파일을 빌드한 이미지를 만들고 컨테이너로 실행하기 (hostsystem linux only)

 

다음 go 내용을 빌드해본다.

package main
import "fmt"

func main() {
	fmt.Println("hello, world!")
}

 

마운트한 파일을 빌드하는 다음과 같이 컨테이너를 실행한다.

docker container run --rm -v "$(pwd)":/usr/src/hello -w /usr/src/hello golang:1.9 go build -v

 

tar 명령어로 압축 파일을 만든다.

tar -cf static_hello.tar hello

 

다음 entrypoint를 지닌 docker_inaction/ch7_static 이미지로 만든다.

docker import -c "ENTRYPOINT [\"/hello\"]" - dockerinaction/ch7_static < static_hello.tar

 

빌드한 이미지를 실행해본다.

docker container run dockerinaction/ch7_static

hello 실행 파일을 진입점으로 하는 컨테이너가 실행된다.

 

7.4 버전 관리

 

도커로 다중 버전을 관리하기 위해서는 repository tagging이 중요하다. 

1.9와 같은 숫자형 버전을 태그에 기입하여 어떤 라이브러리 버전을 사용하는 지 명시한다.

 

요약

 

- docker conatimer commit 명령어는 변경사항이 반영된 새로운 이미지를 만든다.

- 컨테이너가 commit된 경우 해당 이미지 구성 요소로 실행을 하게 된다.

- 이미지 레이어는 변경 내역이 적층된다.

- 이미지 사이즈는 구성 레이어 사이즈 의 합이다.

- docker image export, import는 이미지를 파일로 내보내고 파일로 부터 가져올 수 있다.

- docker image tag 명령어는 하나의 repository에서 여러 태그를 부여할 때 사용 가능 하다.

- stable 빌드 버전을 latest로 부여하라.