컨테이너와 이미지 동작

실행 중인 컨테이너는 실제로 그렇게 크지 않다.

이유는 이미지 위에 작은 부가 레이어인 컨테이너 레이어를 쌓아 구동하기 때문이다.

 

하나의 이미지로 컨테이너를 10개를 구동한다고 가정하면, 이미지는 모든 컨테이너가 공유하고 위에 읽기쓰기가 가능한 얇은 컨테이너 레이어만 10개가 얹힌 10 컨테이너가 구동되는 것이다.

 

 

로컬 호스트 머신과 실행 중인 컨테이너 데이터 통신 방법

주의할 것은 실행 중인 컨테이너로 데이터를 복사할 있다고 해서 코드 변경이나 추가를 반영하는 것은 그리 좋은 생각은 아니다.

보통은 컨테이너 로그파일을 호스트 머신으로 가져올 쓰게 된다.

 

 

로컬 프로젝트에 폴더와 파일을 만듦

컨테이너를 구동하고 컨테이너 속으로 파일을 복사한다

이때, 도커는 당연히 컨테이너 이름을 알아야 특정지을 있다.

 

그렇다면 파일이 제대로 복사되었는지 확인을 해보자

파일을 삭제한다.

 

파일이 정상적으로 복사됐기에 다시 역으로 복사도 됐다.

 

이름과 태그

이미지 빌드 -t 옵션으로 이름을 부여할 있다.

이름은  "이름 : 태그 " 구성되어 있다.

"이름" 범용적인 단어를 사용할 것이기에 중복되는 경우가 많을 것이다.

"태그" 이름이라는 범주에서 하나의 이미지를 특정하기 위해 주로 사용된다.

 

도커허브에서 node 살펴보기

 

이미지 공유 방법

이미지를 공유하는 방법에는 두가지가 있다.

  • 하나는 Dockerfile과 그에 맞는 소스코드를 받는 방법
  • 다른 하나는 이전과 같이 빌드되서 완성된 이미지를 받는 방법이다.

 

첫 번째 방법으로 도커 노드를 깃허브에서 소스코드를 받아 Dockerfile로 이미지 빌드해보기

깃허브에 공개되어 있다.

코드를 받았다면, 받은 파일 속에 Dockerfile 파일이 존재한다. 

Dockerfile방식 이미지 공유 방식은 이미지에 들어가야 하는 모든 주변 코드와 폴더 구조도 필요로 한다.

반면에 이미지 공유 방식은 이미지를 다운로드하기만 하면, 즉시 컨테이너를 실행할 수 있다.

빌드할 필요가 없고, 추가 코드나 주변 폴더도 필요하지 않다. 이미 모든 것이 이미지에 포함되어 있기 때문이다. 

이러한 이점으로 주로 완성된 이미지를 공유하는 것이 일반적이다.

 

DockerHub 이미지 푸시하기

완성된 이미지를 공유하는 대표적인 방법

도커에서 이미지 공유는 도커의 핵심 기능이다. 도커를 사용하는 이유는 종속성 설치나 별도의 환경설정 없이 컨테이너를 실행할 있는 것이다. 거기에 필수적인 것이 이미지 공유이다.

이미지 공유는 중요하기 때문에 도커는 이미지 공유를 위해 내장된 명령어가 있다.

 

도커 허브에 이미지 공유하는 방식은 가지가 있다.

공유 저장소, 개인 저장소 개인 저장소는 무료 사용자 기준 1개만 제공한다.

 

도커 허브에 접속해 가입 후 저장소 생성하기

 

Docker Hub Container Image Library | App Containerization

Deliver your business through Docker Hub Package and publish apps and plugins as containers in Docker Hub for easy download and deployment by millions of Docker users worldwide.

hub.docker.com

도커 허브에 푸시하는 방법은 간단하다. 푸시하고자하는 로컬 이미지 이름을 위와 같이 맞춰주면 된다.

 

 

만약 이미 완성된 이미지를 푸시하고 싶다면 아래와 같은 방법으로 이름을 변경해주면 된다.

 

여기서 주의깊에 것은 기존 이미지를 복제본을 생성한다는 것이다.

 

 

 

정상적으로 올라간 것을 있다.

 

만약 아래와 같이 업로드가 거부됐다면, 도커허브에 로그인을 안한 것이다.

저장소에 푸시할 있는 자는 저장소 주인만 푸시가 된다.

 

로그인을 했다면 정상적으로 푸시할 있다.

이전에 이미 푸시를 헀다면 변경된 부분만 푸시를 한다.

따라서 처럼 변경되지 않은 레이어는 푸시가 안된 것을 있다.

 

 

도커 허브에서 가져오기

공개 저장소로 올렸으니 로그아웃을 해야 완전히 정상적으로 받아지는 테스트 있다.

PULL 가져온 이미지는 도커허브에 올라간 이미지 항상 최신 버전을 가져온다.

 

 

사실 pull 하지 않아도 컨테이너를 구동 시킬 있다.

이유는 도커는 로컬에서 찾지 못하면 도커 허브에서 찾기 때문이다.

바꿔말하면, 로컬에 존재하면 도커허브에 올라간 최신의 이미지를 확인하지 않고 실행한다는 말도 된다.

따라서, PULL RUN 하는 것이 옳다.

 

 

 

 

 

 

이미지와 컨테이너 관계

이미지는 모든 설정 명령과 모든 코드가 포함된 공유 가능한 패키지이다.

즉, 이미지는 한 번 생성되면 내부 코드를 수정할 수가 없다. 

이미지는 컨테이너를 실행하기 위한 설계도와 같다. 컨테이너는 이미지를 기반으로 실행된다.

 

 

이미지 가져오기

이미지를 가져오는 대표적인 방법은 도커 허브 사이트를 이용하는 것이다.

https://hub.docker.com/

 

Docker Hub Container Image Library | App Containerization

Deliver your business through Docker Hub Package and publish apps and plugins as containers in Docker Hub for easy download and deployment by millions of Docker users worldwide.

hub.docker.com

도커는 도커허브에 연결하는 기능을 내장하고 있어, 만약 로컬에서 해당하는 이름에 이미지가 없다면 추가로 도커 허브를 탐색한다.

위의 경우 도커 허브에서 공식 노드 이미지를 받아 실행하게 된다.

도커 허브에서 이미지를 받을 때 가장 최신 버전을 받게 된다.

 

커스텀 이미지 만들기

이미지 생성의 핵심은 Dockerfile 이다.

Dockerfile 은 도커에 의해 식별되는 특별한 이름이다.

Dockerfile을 작성했다면, 빌드하는 명령어는 아래와 같다.

 

docker build .

빌드 과정을 보면 도커파일에 명시한 순서대로 빌드하는 것을 알 수 있다.

도커는 레이어 기반으로 쌓아가면서 이미지 파일을 생성한다.

 

마지막 해시값은 이미지를 생성할 때 이름을 부여하지 않았을 시 이름 역할을 하게 된다.

 

이미지 기반으로 컨테이너 생성하기

생성된 이미지는 docker run 명령어로 컨테이너를 생성과 구동을 할 수 있다.

컨테이너를 구동할 때 컨테이너 내부에서 사용할 포트와 실제 호스트 머신에서 접근할 포트 정보를 매핑해줘야한다.

-p 호스트포트:도커포트  

도커 포트는 컨테이너 내부에서 외부로 노출할 포트번호다. 도커를 구동하는 호스트 머신에서 이를 변경해서 매핑할 수 있다.

 

3000번 포트로 접속

코드를 변경한 후 컨테이너를 재기동

 

변경된 코드가 반영이 안된 것을 볼 수 있다. 이는 이미지는 빌드될 당시 상태를 스냅샷한 것과 같고, 한 번 빌드된 이미지는 읽기전용이다.  자바로 따지면 final 특성을 가진것이다. 따라서 수정을 할 수 없다. 

코드를 변경한 상태로 이미지를 다시 빌드를 해야 적용된다.

 

 

 

레이어 기반

이미지는 레이어 기반 구조로 이뤄진다.

이미지를 빌드하거나 이미지를 다시 빌드할 때 변경된 부분의 명령과 그 이후의 모든 명령이 재평가된다.

이미 빌드된 이미지를 다시 빌드할 때 CAHED로 빠르게 빌드가 수행된 것을 알 수 있다.

 

변경을 가한 WORKDIR 부터 이후 전부 재평가된 것을 볼 수 있다.

이러한 구조를 레이어 기반 아키텍처라 한다.

명령어 하나 하나가 레이어 처럼 쌓인다. 그렇기에 이전 명령어가 변경되면 이후 명령어는 전부 재평가되는 것이다.

다른 말로 이전 레이어의 변경은 이후 모든 레이어에 영향을 미친다.

 

이 레이어 기반 구조를 이해하면 빌드 시 최적화 방안을 모색할 수 있다.

앞서 빌드할 때 RUN npm install 로 종속성 다운로드 시 오래걸렸다. 이를 방지하기 위해 종속성 관련 package.json 앞으로 먼저 COPY한다면,  다른 소스 코드는 수정을 해도 오래걸리는 npm install 재평가되어 실행되지 않아 빠르게 빌드할 수 있다.

 

이미지와 컨테이너를 구성하고 관리

기본적으로 모든 명령어에 --help 도움을 받을 있다.

 

자주 사용하는 핵심 명령어

docker ps -a

   모든 컨테이너 목록

docker run

   이미지를 기반으로 컨테이너를 만들고 컨테이너 시작

docker start

   기존 컨테이너 시작

 

attached(연결) 모드, detached(분리) 모드

docker start 로 시작하는 경우, detached 모드가 디폴트

docker run으로 실행하는 경우, attached 모드가 디폴트

 

attached

attached 모드에선 컨테이너에 연결된 상태를 유지하기 때문에 서버에서 발생시킨 로그를 볼 수 있다.

detached

detached 모드에서 서버에서 발생한 로그를 보고 싶을 땐 docker logs 명령어를 사용하면 된다.

 

인터렉티브 모드

컨테이너와 통신하는 방법

attached 모드는 단순히 서버로부터 출력만 받는다.

 

docker run 사용 -it 상호작용 가능

run 시 상호작용 방법
start 시 상호작용 방법

이미지, 컨테이너 삭제하기

컨테이너 삭제

 

이미지 삭제 rmi(remove image)

 

 

사용하지 않는 컨테이너나 이미지를 일괄 삭제할 수도 있다.

prune 사용

자주쓰는 옵션 -rm

컨테이너를 재시작하지 않는 경우가 많다.

이유는 컨테이너를 재시작하는 시나리오는 대부분 코드의 변경이며 코드 변경은 다시 빌드해야됨을 의미한다. , 기존 컨테이너는 불필요해지는 경우가 많다.

 

컨테이너를 매번 새로 만들어 실행하기 위한 편리한 옵션(자동제거)

 

 

 

 

 

 

 

 

도커는 컨테이너를 생성하고 관리하기 위한 도구이다.

컨테이너란?

소프트웨어 개발에서 컨테이너는 표준화된 소프트웨어 유닛이다.

컨테이너는 코드 패키지이며 해당 코드를 실행하는데 필요한 종속성과 도구가 포함되어있다

따라서 환경설정이나 의존성 같은 것을 신경 쓰지 않고 항상 표준화된 동작 결과를 보장한다.

도커는 이런 컨테이너를 구축하기 위한 도구일 뿐이다.

 

현재 최신 OS는 컨테이너 지원이 내장되어 있어 과거보다 도커를 설치해 실행하기 쉬워졌다.

 

독립적이고 표준화된 소프트웨어 유닛의 필요성

  • 여러 개발자간 개발 환경을 PC마다 맞추기 얼마나 번거로운지 생각해보기
    • 종속성, 서버 설정, DB연결 등등...
  • 로컬 환경, 개발 환경, 운영 환경 각기 다른 조건에서 동일한 하게 동작하기까지 환경 구축이 얼마나 힘든지 생각해보기

이처럼 독립적이고 표준화된 소프트웨어는 대단히 중요한 가치가 있음을 알 수 있다.

 

 

가상 머신과 도커의 차이는?

https://www.docker.com/resources/what-container/

  • 컨테이너는 코드와 종속성을 함께 패키징하는 앱 계층의 추상화 모듈이다.
  • 도커 엔진 하나에 여러 컨테이너가 동일한 시스템에서 실행될 수 있으며 각각 사용자 공간에서 격리된 프로세스로 실행되는 다른 컨테이너와 OS 커널을 공유할 수 있다.
  • 컨테이너는 VM보다 더 적은 리소스를 차지한다.(저장 공간, CPU 자원 등)

https://www.docker.com/resources/what-container/

가상머신은 운영체제 위에 또 다른 운영체제를 설치하기 때문에 운영체제가 기본적으로 가진 애플리케이션, 필수 바이너리 및 라이브러리 등이 중복되어 리소스를 소비한다. 

컴퓨터 전체를 캡슐화 한 것과 같아 도커보다 무겁고 느리다.

 

 

 

 

 

 

+ Recent posts