인프라

도커란?

포포015 2021. 11. 7. 15:27

1. 도커란 ?

2. 도커의 핵심용어 

  • 1. 컨테이너
  • 2. 이미지

3. 도커의 필요성과 장단점

4. 도커 레이어

5. 도커 아키텍처

6. 도커 허브

7. Dockerfile

  • FROM
  • RUN
  • CMD
  • ENTRYPOINT
  • EXPOSE
  • ENV
  • ADD , COPY

8. 데이터 관리

  • VOLUME (레퍼런스에서 권장하는 방법)
  • BIND MOUNT
  • TMPFS MOUNT

9. 네트워크 

  • bridge
  • host
  • overlay  

 

 



1. 도커란?

- 도커는 컨테이너 기반의 오픈소스 가상화 플랫폼이다.
컨테이너라고 하는 느슨하게 격리된 환경에서 애플리케이션을 패키징하고 실행할 수 있는 기능을 제공한다.
(도커는 컨테이너를 관리하는 플랫폼이다.)

2. 도커의 핵심용어

 

1. 컨테이너

- 서버에서 이야기하는 컨테이너는 다양한 프로그램,
실행환경을 컨테이너로 추상화하고 동일하게 인터페이스를 제공해 프로그램 배포 및 관리를 단순하게 해준다.

 

예를 들어, Software A와 B가 동일한 Library를 사용하지만 서로 다른 버전을 필요로 하는 경우라던지 두 software의 운영 체제가 다를 경우 등 다양한 경우에서 문제가 발생할 수 있습니다. 이런 상황에서가장 간단한 해결책은 두 Software를 위한 시스템을 각각 준비하는 것인데, 시스템을 각각 준비할 경우 비용의 문제가 발생하게 된다(10개의 software일 경우 10개의 시스템이 필요) 이러한 문제를 해결하기 위해 나온 개념이 컨테이너 이다


( 호스트에 설치된 것에 의존할 필요가 없음 )
( 작업하는 동안 컨테이너를 쉽게 공유할 수 있으며
공유하는 모든 사람이 동일한 방식으로 작동하는 동일한 컨테이너를 갖는다.)
* 조립PC, AWS, Azure, Google cloud등 어디에서든 실행할 수 있다 *

2. 이미지

- 이미지는 컨테이너 실행에 필요한 파일과 설정값 등을 포함하고 있는것으로 상태 값을 가지지않고 변하지않는다.
1개의 이미지로 여러 컨테이너 생성 가능 , 이미지로 컨테이너를 생성하고 컨테이너에 변화가 있어도
기존 이미지에는 영향이 없음.
( 윈도우의 알집과 비슷한 개념이라고 생각하면 될거같다.)

장점

  1. 하나의 서버에 여러개의 컨테이너를 실행하면 서로 영향을 미치지않고 독립적으로 실행되어 (의존성 down)
  2.   마치 가벼운 VM을 사용하는 느낌을 준다.
  3. 어플리케이션을 설치하고 사용하는 것에 최소의 시간과 용량을 소비한다.

3. 도커의 필요성과 장단점

- 기존있던 서버를 구축할땐 가상화 방식은 OS를 가상화했다
(vmware나 virtualbox)같은 호스트os위에 게스트 os 전체를 가상화 하여 사용하는 방식
(비교적 사용법이 간단하지만 무겁고 느려서 운영환경에서 사용하기 힘들었다.)
이러한상황을 개선하기위해 Cpu의 가상화기술 KVM, 반가상화(Xen) 같은 가상화 기술이 등장함.
하지만 개선을하려해도 가상화 방식은 어쨋든 성능이슈가 있어서 *프로세스를 격리* 하는 방식이 등장함.
리눅스 에서는 이방식은 *리눅스 컨테이너* 라고 하고 프로세스를 격리 시키기 때문에 가볍고 빠르게 동작한다.
(CPU나 메모리는 프로세스가 필요한만큼만 추가로 사용하고 성능적으로 손실이없다)


장점

  1. 실행속도가 빠르다. OS를 실행하지않고 모든프로세스에 대한 컨테이너를 실행할수있음.
  2. 안전하다. container들끼리는 분리되어 있기때문에 보안상 이점이 있다
  3. 실행환경 구성이 빠르고 간단하다. 프로젝트 개발 및 실행환경을 강제화 가능
  4. 비용절감 효과 컨테이너의 크기가 매우 작고, 하나의 물리적 서버에 다수의 컨테이너를 가동시킬 수 있다.


단점

  1. Docker는 플랫폼 의존적이다. Docker는 실제로 Windows와 Mac에서는 linux 가상머신위에서 동작한다. 결국 Docker는 linux에서만 실행가능하다.
  2. Docker위에서 GUI 앱을 돌리기가 불편하다. 도커 컨테이너 내에서 GUI앱을 실행하는 것은 가능하지만(X11 forwarding을 이용) 불편하다. 도커는 command line에서 동작하는 앱을 호스팅하기 위해 디자인되었다.

4. Docker Layer

- 도커 이미지는 컨테이너를 실행하기 위해 모든 정보를 가지고 있기때문에, 보통 용량이 크다.
기존 이미지에 파일 하나 추가 했다고, 모든걸 다시 다운받으면 비효율적이다.
그래서 나온 개념이 '레이어' 라는 개념이다. 이미지는 여러개의 읽기 전용 레이어(read only)로 구성되고 파일이
추가되거나, 수정되면 새로운 레이어가 생성되서 추가된다.
컨테이너를 생성할때도 레이어 방식을 사용하는데 기존 이미지 레이어 위에 읽기/쓰기 레이어를 추가해서 사용한다.

5. Docker Architecture


Client : 도커 Container를 관리하고 실행하기 위해서 Docker사용자가 Docker와 상호 작용 하는 기본 방법이다. ( 네트워크 인터페이스를 통해 REST API를 사용하여 통신한다. )

Registry : 도커 Image가 저장되어 있는 저장소이다. 대표적으로 Docker Hub가 있다. Registry는 Public Registry(무료)와 Private Registry(유료)가 있다.

Daemon : Host에 설치되어 도커 Container를 관리하는 daemon 프로세스이다. Client와 상호작용한다.

Image : 도커 Daemon을 통해 Container로 실행 가능하도록 필요한 프로그램, 라이브러리, 소스 등이 설치된 파일이다.

Container : Image를 실행한 상태

6. Docker Hub

Docker는 만들어진 이미지를 저장하고, 검색하고, 받아올 수 있는 저장소인
Docker Hub를 이용해 repository를 구성할 수 있다.
사용자는 자신이 만든 image를 repository에 올려 관리하거나 다른 사람들과 공유할 수 있다.
( 깃 허브와 비슷한 개념으로 생각하면 편하다. )

 

7. Dockerfile

코드 형태의 텍스트 문서이며, 여러가지 지시어를 사용하여 이미지를 제작할수 있다.

이미지를 생성할때 commit이나 import등 다른방법도 있지만 일반적으로 Dockerfile을 사용한다.

이유로는 아래와 같은장점이 있다.

  • 코드 형태로 되어있어 버전 관리가 용이
  • 이미지의 기능을 파악하기 쉬움
  • commit 이나 import 로 지정하기 어려운 CMD ENTRYPOIN 등의 유용한 기능

 

Dockerfile 사용법

Dockerfile이 있다는가정하에, 이미지를 만드려면 dockerfile이 있는경로로 이동해

docker build -t <태그이름> . 를 사용

FROM

- 베이스 이미지를 지정.

아래의 명령어는 JDK 8을 사용할 컨테이너 이미지를 설정한다.

FROM <image>:<tag>
FROM openjdk:8-jdk-alpine

---- FROM 에는 3가지의 문법이 있다. ----
FROM <image>
FROM <image>:<tag>
FROM <image>@<digest> #digest는 각각의 이미지의 해시 값

RUN

- DockerFile이 이미지를 생성하는 과정에서 실행될 명령어를 지칭

1. 일반적으로 shell 커맨드처럼 사용하는방법
RUN <command>

2. exec 
RUN ["executable", "param1", "param2", ...]  # 사용하려면 PATH가 확정되어야 한다

CMD

- Dockerfile이 이미지로 생성된이후, 컨테이너로 만들어지며 실행되는 '첫 명령어를' 지칭한다.

 * Dockerfile 내부에 단하나의 CMD 명령어만 존재

  (만일 여러개의 CMD명령어를 사용하면, 맨 마지막에 있는 CMD만 동작.)

# 1. 일반적으로 선호되는 방법: exec 사용하듯 사용하는 방법
CMD ["executable", "param1", "param2", ...]

# 2.ENTRYPOINT 명령어의 기본 파라미터로 넘겨주는 방법
CMD ["param1", "param2", ...]

# 3.Shell 커맨드 처럼 사용하는 방법
CMD <command> <param1> <param2> ...

ENTRYPOINT

- 컨테이너를 실행시킬때, 어떤 프로그램이 실행되야 하는지 부분을 조정할수 있다.

( 리눅스라는 프로그램/운영체제 자체 안에서, 여러개의 프로그램을 실행시킬수 있듯이, 그것을 조정할수있는 명령어)

# 1.일반적으로 선호되는 방법: exec 사용하듯 사용하는 방법
ENTRYPOINT ["executable", "param1", "param2", ...]

# 2. Shell 커맨드 처럼 사용하는 방법
ENTRYPOINT <command> <param1> <param2> ...

EXPOSE

- 컨테이너가 됬을때, 접근가능한 포트를 지정할수 있다. UDP로도 지정할수 있으나, 기본으로 TCP로 설정되어있다.

# TCP와 UDP 모두에 노출할경우
EXPOSE 80/tcp
EXPOSE 80/udp

# 호스트 시스템에서 포트 리다이렉션을 설정할경우 -p 옵션으로 연결한다.
docker run -p 80:80/tcp -p 80:80/udp ...

ENV

- 이미지를통해 컨테이너를 실행할때 유지할 환경 변수 설정

( docker run -e 

# 기본 설정 방법
ENV <key>=<value> ...
ENV MY_NAME="John Doe"

# 컨테이너가 실행중일땐 아래의 옵션으로 변경가능 *하지만 실행중인 컨테이너에서 강제로 설정을 변경하는건 위험하다
docker inspect

ADD , COPY

- 로컬의 특정 위치에서 도커 이미지로 파일이나 디렉토리를 복사하는 역할

(로컬에 있는 압축 파일을 Docker 이미지의 특정 디렉토리에 추출하려는 경우 

또는 원격지의 파일을 Docker 이미지로 복사하려는 경우  ADD를 사용하고,

단순히 로컬 파일 또는 디렉토리를 Docker 이미지로 복사하려는 경우에는 COPY를 사용하는 것이 적절하다)

 

 * ADD

  • 로컬 파일 또는 디렉토리
  • URL 가능
  • tar 파일 자동으로 압축해제 및 추출가능
# <src> 경로에 있는 이미지의 파일 시스템 에서 복사 하고 추가

# 1.ADD의 첫번째 형식
ADD <src>... <dest>

# 2. ADD의 두번째 형식
ADD ["<src>",... "<dest>"]

* COPY

  • 로컬 파일 또는 디렉토리
# 단순히 로컬 파일 또는 디렉토리를 Docker 이미지로 복사하려는 경우에는 COPY를 사용하는 것이 적절

1. COPY의 첫번째 형식
COPY <src>... <dest>

2. COPY의 두번째 형식
COPY ["<src>",... "<dest>"]

더 많은 명령어는 https://docs.docker.com/develop/develop-images/dockerfile_best-practices/ 레퍼런스를 참조하자

 

8. 데이터 관리

Docker 컨테이너에 쓰여진 데이터는 기본적으로 컨테이너가 삭제될 때 함께 사라지게 됩니다.

( 사실은 안사라지고 컨테이너를 생성하면, 랜덤한 볼륨이 할당되는데 새로운 컨테이너를 생성하면

또 랜덤한 새로운 볼륨을 바라보고있어서, 데이터가 날라간다고 생각하게 된다. 랜덤이름이라 찾기도 힘들고..)

이런식으로 랜덤한 볼륨을 생성하고 그 컨테이너는 이 볼륨을 바라보게된다.

 

1. 커스텀한 볼륨을 생성한다.

docker volume create [OPTIONS] [VOLUME]

2. 컨테이너를 구동할때 미리 생성해둔 볼륨을 연결해 구동한다. 그럼 컨테이너는 미리 생성된 볼륨에

데이터를 쌓게된다.

* 예시
sudo docker run -d -p 3303:3306 --name docker-test -e MYSQL_ROOT_PASSWORD=root -v plea-test:/var/lib/mysql mysql

 

 
컨테이너에서 관리되는 내부 데이터가 날라가는걸 방지하기위해 Docker는 크게 3가지로 옵션을 제공한다.

1. VOLUME (레퍼런스에서 권장하는 방법)

- Docker의 volume을 생성하여 volume을 마운트 하는방법.
- Docker 에 의해 관리

장점

  • 볼륨은 바인드 마운트보다 백업 또는 마이그레이션이 더 쉽습니다.
  • Docker CLI 명령 또는 Docker API를 사용하여 볼륨을 관리할 수 있습니다.
  • 볼륨은 Linux 및 Windows 컨테이너 모두에서 작동합니다.
  • 여러 컨테이너 간에 볼륨을 더 안전하게 공유할 수 있습니다.
  • 볼륨 드라이버를 사용하면 원격 호스트 또는 클라우드 공급자에 볼륨을 저장하여 볼륨의 내용을 암호화하거나 다른 기능을 추가할 수 있습니다.
  • 새 볼륨의 콘텐츠는 컨테이너에 의해 미리 채워질 수 있습니다.
  • Docker Desktop의 볼륨은 Mac 및 Windows 호스트의 바인드 마운트보다 성능이 훨씬 높습니다.

 

2. BIND MOUNT

- 호스트 파일 시스템의 파일 경로를 마운트 하는 방법.
( 볼륨에 비해 기능이 제한적.)
( 호스트 시스템의 디렉토리 구조와 OS에 의존 )

3. TMPFS MOUNT

- 리눅스의 tmpfs를 이용한 마운팅 방법
- 호스트 메모리에서만 지속됨
- 컨테이너간에 마운트를 공유 불가능
- 리눅스에서 Docker를 실행한 환경에서만 사용가능
( 컨테이너를 생성할 때 컨테이너는 컨테이너의 쓰기 가능 계층 외부에 파일을 생성해서 사용하는방법 )
( 컨테이너가 중지되면 tmpfs마운트가 제거되고 거기에 기록된 파일은 유지되지 않음 )

9. Network

Docker 컨테이너는 격리된 환경에서 동작하기때문에 기본적으로 다른컨테이너와 통신이 불가능하다.
개발을 하다보면 하나의 컨테이너가 다른 컨테이너의 정보가 필요하거나 연동시켜 사용해야할때가 많다.
그럴땐 하나의 Docker 네트워크(network)에 연결시키면 서로 통신이 가능하다.

네트워크 종류

Docker 네트워크는 bridge, host, overlay 등 목적에 따라 다양한 종류의 네트워크 드라이버를 지원한다.

  • bridge 네트워크는 하나의 호스트 컴퓨터 내에서 여러 컨테이너들이 서로 소통할 수 있도록 해줍니다.
  • host 네트워크는 컨터이너를 호스트 컴퓨터와 동일한 네트워크에서 컨테이너를 돌리기 위해서 사용됩니다.
  • overlay 네트워크는 여러 호스트에 분산되어 돌아가는 컨테이너들 간에 네트워킹을 위해서 사용됩니다.




참조 - https://subicura.com/2017/01/19/docker-guide-for-beginners-1.html