IT/기초 지식

[Docker] Docker 기초(1)

개발자 두더지 2021. 4. 4. 23:18
728x90

일본의 포스팅을 번역한 것입니다. 오역 및 직역이 있을 수 있으며 내용에 오류가 있다면용에 오류가 있다면 지적해주심 감사하겠습니다.

 

이번 포스팅을 통해 알 수 있는 것


 이미지나 컨테이너 등의 기본 지식부터 docker-compose, docker-machine, docker swarm등의 Docker과 관련된 다양한 개념의 전체적인 정리하여 Docker의 구조를 이해하기 위한 포스트입니다.

 

 

Docker이란?


 Docker사가 제공하는 "컨테이너형 가상화 기술"을 실현한 제품이다.

 

 

"가상화"란?


 PC나 서버등 머신에 설치되어 있는 OS(호스트 OS) 상에 다른 머신을 가상으로 구축하는 것을 의미한다. 간단하게 말하하자면, "컴퓨터 속에 가상 컴퓨터를 작동시키는 것"이 가상화이다.

 본래의 가상화(호스트형 가상화)는 아래와 같은 그림과 같이 호스트OS상에 가상화 소프트웨어/하이퍼바이저를 사용하여 가상 머신/게스트 OS를 세워 그 가상 머신 속에 미들웨어의 환경을 구축하고, 프로그램을 실행하여 어플리케이션을 작동하는 등의 구조로 되어있다. 

 

 

"컨테이너형 가상화"란?


 한편으로, Docker가 제공하는 것은 컨테이너형 가상화이다. 컨테이너형 가상화는 아래의 그림과 같은 구성으로 되어 있다.

기존의 호스트형 가상화와 달리, 게스트 OS를 작동시키지 않고, 호스트 OS의 위에 동작하고 있는 Docker Engine으로부터 컨테이너라고 불리는 미들웨어의 환경이 구축된 실행환경을 작성하고, 그 안에 어플리케이션을 동작시키는 것이다.

 이 방법을 통해 기존의 호스트형 가상화보다 더 가볍게 작동시킬 수 있도록 한 것이 컨테이너형 가상화의 특징이다.

 

 

Docker의 장점


 소프트웨어를1명의 프로그래머의 힘으로 개발하는 경우는 거의 없다. 여러 명의 개발자가 협력하여 작성한다. 이 때 어떻게 개발을 진행하면 좋을까에 대한 생각에서 부터 시작된다. 프로젝트 코드의 경우 Git을 통해서 원활히 공유할 수 있지만, 프로그램의 실행 환경이 동일하지 않을 경우 프로그램이 정상적으로 움직이지 않는 경우가 많았다.

 따라서 가상화로 플랫한 가상 머신을 만들고 그 가상 머신을 만드는 설정 등을 공유하여 실행 환경을 공유하자는 아이디어가 있었다. 그러나 앞서 말했듯 기존의 호스트형 가상화에서는 무겁기 때문에 경량할 필요성이 있었다. 정리하자면, 프로그램의 실행환경을 관리하기 위한 구조로써 Docker이 있고, 그걸 공유하기 위해 DockerHub등의 서비스가 있는 것이다.

 Docekr을 사용하는 가장 좋은 메리트는 "여러개의 아키텍처가 있어도 소프트웨어의 실행환경을 Docker을 사용해 관리하여 간단히 어떤 머신에서도 공유할 수 있다 "는 점이다. 이제부터 Docker의 각 요소에 대해 살펴보자. 

 

 

Docker 요소


1) Docker Engine

 Docker을 사용하기 위해 계속 설치되어 있는 프로그램으로 Docker for mac, Docekr for Windows, Docekr Toolbox등의 소프트웨어를 PC에 설치하는 것으로 Docker Engine이 작동하고 Docker을 이용할 수 있게 된다.

 

2) 이미지(Image)

 컨테이너(= 어플리케이션의 실행환경)을 작동시키기 위해서 필요한 설정 파일을 모은 것으로 "Image는 컨테이너의 원천이며 Image로부터 컨테이너가 작동한다"고 이해하는 것이 좋을 것이라고 생각한다. 

 Docker에서는 이 Image를 공유하는 것으로 다양한 머신을 같은 컨테이너(실행환경)을 작동시키는 것이 가능하다.

(1) Tag

 Docker의 Image에는 tag라는 개념이 있다. tag란 "image의 version"이다. 예를 들어 아래의 Docker Hub의 이미지와 같이 nginx이미지에는 [1.14-perl]이나 [alpine]과 같이 다양한 tag가 존재하고 어떤 version을 사용할지를 선택할 수 있다.

 tag명으로 아무것도 지정하지 않으면 자동적으로 "latest" 태그가 사용된다.

 image명과 태그명을 ":"으로 구분한다. 예를 들면 아래와 같이 작성할 수 있다.

nginx:latest
nginx:1.14-perl

(2) Image의 구조

이미지는 아래와 같이 두 가지 특징이 있다.

① layer구조로 되어 있다.

② 한 번 작성된 image는 편집이 불가능하다 ( 읽기 전용)

 

 이미지는 레이어 구조로 되어 있어, 1개의 미들웨어를 설치하면 1개 레이어가 중첩되는 느낌(하나의 설치 커맨드로 1개의 레이어가 한 층 쌓이는 인식)이다. 

 또한 image의 레이어는 Read only이므로 편집할 수 없고, image로 부터 컨테이터를 작동시켰을 때에 만들어지는 컨테이너 레이어만을 편집할 수 있도록 되어있다.

 이것은 image로부터 작동된 컨테이너 내에 어떠한 미들웨어가 설치되어 있는 경우, 미들웨어가 컨테이너 레이어에 저장돼있어 그 컨테이너로부터 다시 image를 생성(commit)하는 형식이기 때문이다. 

(3) Image를 준비하는 과정

 로컬 머신에 있는 Image의 목록은 아래의 커맨드로 확인이 가능하다.

docker images

 그럼, 컨테이너를 실행하기 위해서는 이 컨테이터의 원천이 되는 image를 준비해야할 필요가 있다.

 image를 준비하기 위한 방법에는 크게 두 가지가 있다.

- 다른 사람이 만든 image를 얻어낸다 ( 주로 Docker Hub로 부터)

- Dockerfile을 이용해 자신이 이미지를 직접 작성한다(다른 사람의 image를 수정)

 각각의 방법에 대해 알아보자.

① Docker Hub로 부터 image를 얻어낸다.

Docker Hub에 다양한 미들웨어가 들어있는 Image가 공개되어 있기 때문에 자신이 사용하고 싶은 환경을 아래의 커맨드로 지정하여 취득해낼 수 있다.

docker pull 이미지명     #Docker Hub등으로 부터 이미지를 취득

② Dockerfile을 이용해 자신이 이미지를 직접 작성한다.

 Dockerfile이라는 이름으로 확장자가 없는 파일을 만들어 그 안에 image build(image 작성)에 관련된 설정을 기재하고 그 Dockerfile을 빌드한다.

 다양한 기재방법이 있으나, 간단한 작성법에 대해 소개하자면 다음과 같다.

FROM 이미지명:태그명     # 어떤image를 원천으로 image를 작성할 것인가
RUN 패키지등 설치 커맨드     # 여기에 작성한 커맨드를 실행하여 미들웨어를 설치하고,image의 레이어를 쌓는다
CMD 커맨드 지정        # 컨테이너가 작성된 후에 실행될 커맨드를 지정한다.
docker build -t 빌드하고싶은 이미지가 있는 이미지명

 -t 옵션 뒤에 작성한 image명을 붙여서 커맨드를 실행시키면 된다.

 또한 이미지를 작성할 때는 docker daemon에 전송되는 파일의 범위를 빌드 컨텍스트라고 말하며, 이미지명 뒤에 지정한다(여기서는 .[현재 디렉터리]).

 build커맨드를 실행할 때에 설정으로써 읽어들인 Dockerfile은 기본적으로 빌드 컨텍스트상의 Dockerfile가 로드되도록 되어 있기 때문에 빌드 컨텍스트에 Dockerfile을 둘 필요가 있다.

※ 별도로 -f Dockerfile명 으로 지정할 수 있다. 

 한 번 build한 image를 Dockerfile의 변경없이 다시 build할 때는 build cache가 이전에 빌드한 정보를 보러 가도록 되어있기 때문에 RUN에 update 커맨드 등이 기재되어 있어도 다시 build하면  이 커맨드는 실행되지 않도록 되어 있다는 점을 주의하자. 따라서 cache를 무효로 하여 build하고 싶은 경우는 아래와 같이 --no-cache 커맨드를 추가해야한다.  

 docker build —no-cache -t docker-whale

 

3) 컨테이너

 이미지 준비가 끝나면 이 이미지를 이용해 컨테이너(=어플리케이션의 실행환경)을 작동시킬 수 있다.

(1) 이미지로부터 컨테이너를 작동시키는 방법

docker create --name 신규컨테이너이름 이미지명

위의 커맨드로 컨테이너를 작성한다. 그리고 아래의 커맨드로 컨테이너를 작동시킨다.

docker start 컨테이너명

여기까지 지정한 이미지를 DockerHub으로부터 취득하고 컨테이너를 작성하고 작동시키는 것까지 살펴보았다. 정리하자면 다음과 같다.

docker pull : DockerHub로부터 이미지를 취득

docer create : 얻은 이미지로부터 컨테이너를 작성

docekr start : 작성한 컨테이너를 작동

이 모든 것을 한 번에 할 수 있는 커맨드도 있는데 그것은 바로 docker run이다.

docker run 이미지명

 

(2) 컨테이너의 조작 커맨드

① 컨테이너의 목록을 확인

docker ps

 docker ps 커맨드로는 현재 실행중인 컨테이너를 확인할 수 있으며, 아래와 같이 -a 옵션을 붙임으로써 현재 작동하지 않는 컨테이너를 확인할 수 있다.

docker ps -a

 

② 컨테이너의 상세 정보 확인

docker inspect 컨테이너명

이 커맨드로 지정한 컨테이너의 상세 정보를 확인할 수 있다.

③ 컨테이너의 작성

docker create —name 컨테이너에붙일이름 -it 이미지명 /bin/bash

 -i 옵션은 쌍방향으로 컨테이너의 표준 입력을 받을 수 있도록 연결하는 옵션이다.

 -t 옵션은 컨테이너내에 TTY를 할당하는 옵션이다. 컨테이너에서 쉘을 실행시켜, 화면에 쉘 실행 상태를 표시하고 싶은 경우 -it로 붙여서 사용할 수 있다. 이 옵션을 사용하지 않으면 쉘이 금방 쉘이 바로 종료되고 컨테이너가 정지된다.

④ 컨테이너의 기동

 앞서 설명했듯 컨테이너는 다음과 같이 docker start로 컨테이너를 기동시킨다.

docker start 컨테이너명

⑤ 컨테이너의 정지

docker pause 컨테이너명

⑥ 컨테이너의 재개

docker unpause 컨테이너명

일시정지했던 컨테이너를 다시 동작시키는 커맨드이다.

⑦ 컨테이너의 정지

docker stop 컨테이너명

 컨테이너가 종료한 후에 그대로 로컬에 남아있는 상태에서는 Exit이 된다는 것을 주의할 필요가 있다. 사용하지 않는 컨테이너를 삭제하지 않는다면 하드 디스크 용량에 영향을 미친다.

⑧ 컨테이너의 삭제

docker rm 컨테이너명

-f 옵션으로는 강제삭제할 수 있다.

docker rm -f 컨테이너명

⑨ 작동중인 컨테이너의 쉘에 연결

 접속방법으로는 attach와 exec의 두 가지가 있다.

docker attach 작동중인컨테이너명

 작동중인 컨테이너 쉘을 실행하고 있는 경우에는 쉘에 연결할 수 있지만, Deamon만 작동하고 있는 경우에는 Deamon의 표준 입력에 접속되어 버린다는 것을 주의하자.

 attach로 접속하여 exit로 빠져나오면 작동중인 컨테이너가 종료되는 것이 특징이다. 작동시에 -it 플래그를 붙인 경우네는 control + p, control + q로 빠져나오면 컨테이너가 종료되지 않는다.

docker exec -it 작동중의컨테이너명 /bin/bash

 exit로 빠져나온 경우, 빠져나와도 컨테이너가 정지되는 것이 아니라는게 특징이다.

⑩ 컨테이너로부터 이미지를 작성

docker commit 컨테이너명 image명:태그명

 컨테이너의 상황을 "image명:태그명"으로 지정하여 이미지로써 저장하는 커맨드이다.

docker history 이미지명

 이 이미지의 변경이력을 확인할 수 있지만, docker commit으로 이미지를 작성하면 컨테이너 내부에 어떠한 변화를 주었는지 어디에 대해 기록이 남지않아 매우 쓰기 힘든 image가 되어버린다는 점을 주의하자.

 그러므로 기본적으로 Dockerfile을 이용해서 image를 변경하는 것을 추천한다.

번외) 지금까지의 설명을 바탕으로 살펴보는 전체적인 그림

 

4) Docker Hub(Container Registry)

(1) Docker Hub에 image 공유하기

Github와 거의 비슷하다. Dockerhub의 아이디를 소유하고 있을 필요가 있다. 순서는 다음과 같다.

① Docker hub상에 리포지터리를 작성한다.

② 로컬에 image를 만든다.

③ 로컬의 커맨드라인에 아래와 같이 커맨드를 작성하여 docker hub에 로그인한다.

docker login

④ 아래의 커맨드로 push하고 싶은 image에 태그를 붙인다.

docker tag <push하고싶은image명> <docker hub ID>/<신규image명>:<태그명>

⑤ 아래의 커맨드로 로컬의 image를 리모트 리포지터리에 push한다.

docker push <docker hub ID> / <image명>:<태그명>

 

 

지금까지의 전체적인 그림


 이번 포스팅을 통해 가상화에 대한 설명부터 Docekr Engine, Image, 컨테이너, Container Registry(DockerHub등)이라는 네 가지 요소를 살펴보았다. 이 내용을 바탕으로 전체적인 그림으로 나타내자면 아래의 그림과 같다. 


참고자료

qiita.com/etaroid/items/b1024c7d200a75b992fc

728x90