[Docker 기본(4/8)] docker build & push

yjs0997
DT Evangelist 기술 블로그
8 min readJan 9, 2019

Docker 환경에 Service 및 Application을 구동시키 위한 전체적인 과정은 다음과 같습니다.

지금까지는, Docker Registry(Docker Hub)에 배포되어 있는 있는 Image를 이용해 Container를 구동시켰습니다. 이제부터는 위에서 정리한 과정대로, Dockerfile로 Image를 생성하고 다른 Machine에서 배포된 Image로 Container를 실행시켜 보겠습니다.

신규 Image 생성에서 배포까지

Dockerfile 작성

image-build-test 폴더를 생성한 뒤, 다음의 내용이 포함된 Dockerfile을 생성합니다.

image-build-test 폴더의 내부 구조는 다음과 같습니다.

Image Build

image-build-test 폴더 내에서 생성한 Dockerfile로 ${username}/my-base-image:1.0이란 이름의 Image를 Build합니다.

처음 Image를 Build하게 되면, Local Instance에 저장된 Base Image(여기서는 Ubuntu Image입니다)가 존재하지 않기 때문에, Docker Registry(Docker Hub)로부터 Pull을 받습니다. 그 후, Dockerfile의 COPY명령어가 새로운 Layer로 생성되고, ${username}/my-base-image:1.0 Image가 Build됩니다.

생성된 Image를 확인해 보겠습니다.

Container를 Run

방금 생성한 Image를 Local에서 실행시켜 보겠습니다. 정상적으로 실행된다면, 아래와 같이 Container ID가 나타나고 docker ps로 실행중인 해당 Container를 목록에서 확인할 수 있습니다.

Image를 Docker Hub에 배포

이제는 생성한 Image를 Docker Registry에 배포해 보겠습니다. 따로, Docker Registry를 구성하지 않았기 때문에 배포되는 장소는 Docker Hub이며, 정상적으로 배포하기 위해서 먼저 Login을 하겠습니다.

로그인이 정상적으로 되었다면 docker push로 생성한 Image를 Docker Registry에 등록하겠습니다.

Console에 찍힌 로그를 보면, Unbuntu Image는 이미 Docker Registry에 존재하기 때문에 Mount만 되고, 그 외에 생성한 Layer만 추가로 Push되는 것을 볼 수 있습니다.

Hello World를 만들어 보자

처음에 hello-world를 실행시켜 봤었습니다. 지금부터는 직접 구현해 보겠습니다.

Dockerfile 변경

기 생성된 Dockerfile을 Dockerfile.base로 변경 한 후, ${username}/my-base-image:1.0 Image에 CMD Layer가 추가된 Image를 생성하는 Dockerfile을 새로 생성합니다.

다음과 같은 내용으로 hello.sh를 생성합니다.

hello.sh 파일을 저장하고 실행가능한 상태로 변경합니다.

변경된 폴더 구조는 다음과 같습니다.

Hello World Image Build

변경된 Dockerfile로 ${username}/my-final-image:1.0이란 이름의 Image를 Build합니다.

처음에 Build했을 때 보다는 월등히 빠르게 Build되는 것을 알 수 있습니다. ${username}/my-final-image:1.0의 Base Image가 이미 Local에 존재하기 때문에 CMD에 해당하는 Layer만 생성하면 되기 때문입니다.

생성된 Image를 확인합니다.

docker history [OPTIONS] IMAGE로 각 Image를 구성하는 Layer를 한번 확인해 보겠습니다. 두 Image 사이에서 공유하는 Layer는 암호화된 ID가 동일하다는 것을 확인할 수 있습니다.

${username}/my-base-image:1.0

${username}/my-final-image:1.0

다시 Push

${username}/my-final-image:1.0 Image를 Docker Registry에 Push합니다. Docker Registry에는 ${username}/my-base-image:1.0 Image의 Layer들이 이미 존재하고 있기 때문에, 추가된 Layer(Dockerfile에 추가된 CMD)만 Push됩니다.

다른 곳에서 Hello World를 실행해보자

새로운 환경에서 지금 만든 Image를 Container로 실행시켜 보겠습니다. 그 전에 docker-machine create로 새로운 Docker 환경을 구성하겠습니다.

새로 구성한 Docker 환경에 docker-machine ssh로 접속하겠습니다.

지금 만든 Image를 Pull받고,..

새로 구성된 환경이라 Image의 모든 Layer들을 내려받습니다. 그리고, docker run을 실행하면 !!!

처음에 정리했던 Build — Push — Pull — Run의 과정으로 Container가 실행되는 것을 확인할 수 있었습니다. Docker Engine이 설치된 어떤 환경에서도 지금 만든 Hello world는 실행될 것입니다. 여기서 더 나아가 Hello world는 다양한 메시지를 입력받거나 혹은, 저장되어 있는 메시지들을 출력하는 Application으로 발전할 수도 있습니다. 그렇다면, 이 Application의 기능이 Upgrade되어, 새로운 버전의 Image를 만들고 새로운 Container를 기동시켜야 한다면, 변경된 내용(입력받거나 혹은 저장된 메시지들)들은 어떻게 될까요?

우리는 이전에 Image와 Container의 Layer 구조를 살펴보면서, 해당 Container에 읽기/쓰기가 가능한 Layer내에 변경된 내용들이 저장된다는 것을 알고 있습니다. 그리고, 이 데이터들은 해당 Container와 같이 소멸된다는 것도 알고 있습니다. 그럼, Container가 소멸되었다가 새로 생성되어도, 이전의 데이터들을 유지하여 사용할 방법은 없을까요? 이 다음에는 Docker의 Volume을 이용하여, 데이터를 보존하는 방법에 대해서 확인해볼 필요가 있겠네요.

--

--