Docker 시작하기

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

리눅스의 컨테이너 기술은 굉장히 오래전부터 있던 기술입니다.
그런데 왜 최근에 화두로 떠오르고 있는걸까요?

저는 컨테이너 기술 활성화에 크게 기여한 것이 바로 Docker라고 생각합니다.

Docker는 Docker Store(구 Docker Hub)라는 퍼블릭한 레지스트리를 통해 여러 기업들에서 참여하여 이미지를 제공해주고 있지요.
오픈소스 솔루션 중에는 없는 이미지를 찾는게 더 어려운 것 같습니다.
이처럼 Docker 생태계가 잘 되어 있는데 그 생태계를 사용자들로 하여금 굉장히 쉽게 활용할 수 있도록 편의성을 제공해주고 있기 때문에 사용자들은 원하는 솔루션에 대한 이미지를 받아서 컨테이너로 띄우기만 하면 끝입니다.
또한 컨테이너는 경량화된 독립적 형태로 운영되기 때문에 새로운 기술을 빠르게 적용할 수 있고, 컨테이너가 실행 가능한 환경이라면 어디에서든 똑같은 환경을 그대로 구축할 수 있게 됩니다.

즉, 뭔가 빠르고 적시 배포가 이루어져야 하는 상황에 아주 최적화된 형태가 바로 컨테이너로서 운영되는 형태인 것입니다. 그래서 마이크로서비스로 아키텍처를 구성하고 계신 굉장히 많은 분들이 Docker, Kubernetes를 활용하고 있습니다.

그럼 일반적으로 Docker를 이용하여 애플리케이션을 컨테이너로서 배포하고 관리하는 방법에 대해 살펴보도록 하겠습니다.

애플리케이션 배포

애플리케이션을 Docker에 배포하는 방법입니다.

앱준비

  • 샘플 앱 다운로드
Spring Boot 공식 가이드에서 제공하는 샘플입니다.
https://github.com/spring-guides/gs-spring-boot-docker.git
  • 샘플 앱 수정 및 빌드
샘플 프로젝트의 initial 폴더로 이동한 뒤 /src/main/java/hello/Application.java 파일에 아래와 같이 간단한 API를 추가합니다.
  • Application.java

Maven을 활용하여 애플리케이션을 빌드합니다.

Dockerfile 작성

Dockerfile은 Docker에서 이미지 레이어를 지정하고 컨테이너 내부 환경을 정의하는데 사용되는 간단한 파일 형식입니다.

아래와 같이 Dockerfile을 작성해봅니다.

Dockerfile

Dockerfile 을 작성하는데 필요한 기본 명령어 입니다. (참조 — Dockerfile 작성방법)

  • FROM : 기반이 되는 이미지를 설정합니다. Dockerfile은 FROM 명령어로 시작해야 합니다.
  • VOLUME : Docker 컨테이너에 의해 사용되는 데이터를 유지하는데 사용합니다.
    해당 실습에서는 Spring Boot 어플리케이션이 기본적으로 톰캣 작업 디렉토리로 /tmp 폴더를 사용하므로 해당 폴더를 VOLUME으로 추가합니다.
    그러면 호스트의 Docker 특정 영역에 임시 파일을 만들고 컨테이너 내부 디렉토리인 /tmp 에 링크합니다.
  • ADD : 파일이나 디렉토리 등을 복사하여 이미지 파일시스템에 추가합니다. 해당 실습에서는 프로젝트 JAR 파일[target/gs-spring-boot-docker-0.1.0.jar]이 컨테이너에 app.jar로 추가됩니다.
  • ENV : 환경변수를 설정합니다.
  • RUN : 새로운 레이어에서 명령어를 실행하고 결과를 커밋합니다. 보통 이미지 위에 다른 패키지(프로그램)을 설치하여 새로운 레이어를 생성할 때 사용합니다.
  • ** RUN 사용 예제 (ubuntu 위에 curl을 설치)
  • ENRTYPOINT : 컨테이너를 실행할 때 실행될 명령을 정의합니다.

ENTRYPOINT 작성에는 아래 두가지 방식이 있습니다. 권장되는 방식은 exec 형태입니다.

  • EXPOSE : 컨테이너가 런타임 시에 지정된 포트에서 수신 대기하고 있음을 정의합니다.
    이 명령어는 어떤 포트가 publish 되어야 하는지에 대해 이미지를 만든 사람과 컨테이너를 실행할 사람 사이에 일종의 규약처럼 기능합니다.
    해당 명령어로는 실제로 포트를 publish 할 수 없으며 docker run 명령어의 -p 또는 -P 플래그를 통해 가능합니다.

Docker 이미지 생성

아래와 같이 docker build 명령어를 실행하여 Dockerfile을 통해 이미지를 생성합니다.

-t 옵션을 사용하여 [이미지명:태그] 형식의 태그를 지정합니다.

docker images 명령어를 통해 이미지가 제대로 생성되었는지 확인합니다.

애플리케이션 실행(이미지실행, 컨테이너실행)

docker run 명령어를 통해 생성한 이미지를 기반으로 애플리케이션을 실행합니다.

Docker에서는 애플리케이션이 하나의 컨테이너로 실행됩니다.

-p [호스트 포트:컨테이너 포트] 옵션을 통해 컨테이너의 포트를 호스트에 publish하여 호스트에서 접속 가능하도록 실행합니다.

애플리케이션 확인

아래와 같이 docker ps 명령어를 통해 실행중인 컨테이너 목록을 확인할 수 있습니다.

애플리케이션이 컨테이너로 실행되었음을 확인할 수 있습니다.

http://localhost:8080 으로 접속하여 확인해봅니다.

컨테이너 관리

컨테이너 생성

컨테이너 생성 및 확인은 위 애플리케이션 실행 및 확인을 참고합니다.

컨테이너 중지

아래와 같이 docker stop [컨테이너ID] 명령어를 통해 실행중인 컨테이너를 중지합니다.

docker ps 명령어에 -a 옵션을 통해 전체 컨테이너 목록을 확인해보면 STATUS가 Exited 상태임을 확인할 수 있습니다.

컨테이너 삭제

아래와 같이 docker rm [컨테이너ID] 명령어를 통해 컨테이너를 삭제합니다.

삭제하고 난뒤 컨테이너 목록을 보면 해당 컨테이너가 삭제되었음을 확인할 수 있습니다.

이미지 관리

컨테이너를 운영환경에 배포하는 등 이미지의 이식성을 위해 레지스트리를 통해 이미지를 관리해야 합니다.

레지스트리는 레파지토리의 모음이며 레지스트리에서 하나의 계정으로 여러 레파지토리를 생성할 수 있습니다.

Docker의 공용 퍼블릭 레지스트리인 Docker Hub는 사전에 이미 구성되어 있는 무료 레지스트리이지만 Docker Trusted Registry를 사용하여 private한 레지스트리를 설정할 수 있습니다.

Docker Hub 활용

Docker 계정이 없다면 https://hub.docker.com 에서 가입합니다.

Docker Hub에 로그인

docker login 명령어를 통해 로컬에서 Docker Hub에 로그인 합니다.

로컬 이미지 태깅

로컬에 만들어진 이미지를 Docker Hub에 업로드할 수 있도록 이미지 태깅이 필요합니다. 태깅을 하면 같은 이미지가 다른 이름으로 하나 더 만들어 집니다. docker tag image username/repository:tag 명령어를 통해 이미지를 원하는 곳에 업로드 할 수 있도록 합니다.

로컬 이미지를 Docker Hub 레파지토리와 연관시키는 표기법은 username/repository:tag 입니다.

태그는 선택 사항이지만 Docker 이미지의 버전을 제공하는 것이기 때문에 사용하기를 권장합니다.

새로 태그 된 이미지를 확인합니다.

Docker Hub로 이미지 업로드

docker push 명령어를 통해 레파지토리에 태그된 이미지를 업로드 합니다.

이제부터는 업로드한 이미지로 모든 컴퓨터에서 애플리케이션을 실행할 수 있습니다.

이미지가 로컬에 없다면 Docker는 Docker Hub 레지스트리의 레파지토리로부터 이미지를 가져옵니다.

Private Registry 활용

Private Registry로서 활용 가능한 Harbor를 이용해서 이미지를 보호할 수 있습니다.
오픈소스인 Harbor를 통해 Private Registry를 구축한 뒤 Docker Hub를 활용하는 방식과 동일하게 활용하면 됩니다.
(Harbor 레지스트리에 로그인 -> 이미지 태깅 -> Harbor 레지스트리로 이미지 업로드)
Harbor 이외에도 다양한 솔루션을 활용해서 Private Registry를 구축해 보세요.

기타 참고 자료

--

--