Docker란?

Docker는 컨테이너기반의 가상화 플랫폼으로 애플리케이션을 신속하게 구축, 테스트 배포할 수 있다.

컨테이너란? 컨테이너란 이미지의 목적에 따라 생성되는 프로세스 단위의 격리 환경이며 프로세스의 생명 주기를 관리한다. 컨테이너는 호스트와의 격리를 통해 독립된 개발 환경을 보장한다.

이미지란? 컨테이너를 실행할 수 있는 실행파일, 설정 값들을 가지고 있는 것.

가상 머신 (VM)의 경우에는 사진과 같이 Host OS 위에 가상화를 위한 Hypervisor 엔진, 그리고 각 앱 마다 Guest OS가 따로 올라간다. 그러나 Docker는 Guest OS를 깔고 그 위에 올라가기 때문에 각 컨테이너가 OS를 공유할 수 있다. 도커는 프로세스 단위의 격리 환경을 만든다. 따라서 VM에 비해서 가볍게 리소스를 적게 사용한다. VM의 경우에는 하드웨어 쪽에서 isolation이 일어나기 때문에 보안적인 측면에선 더 좋을 수 있다 (OS 쪽에서 isolation이 일어나는 VM과 달리).

가상화는 HW 장치를 추상화하여 하나의 HW를 여러 개 같이 쓰거나 여러 개의 장치를 하나의 장치인 것 처럼 사용가능하다.

크게 오늘날 도커를 사용하는 이유는 다음과 같다.

  • 도커는 전체 OS가 아닌 애플리케이션 구동을 위해 필요한 라이브러리 및 실행 파일만 필요함으로 가볍고 빠르다 (성능 하락도 없다).
  • 도커가 설치 되어 있으면 어디서든 컨테이너를 실행할 수 있어서 이식성이 좋다.
  • 설정관리가 쉽다. (환경 변수로 가능)
  • 자원관리가 쉽다. 컨테이너를 삭제하고 다시 만들면 초기화된다.
  • Scale-out이 되어 유연성이 좋다. –replica 명령어를 통하여 scale-out할 수 있다. 이는 도커 스웜에서 좀 더 설명하겠다.

Docker Engine

도커 엔진은 컨테이너 관리, 이미지 관리, 볼륨 관리, 네트워크 관리 등을 한다. 사용자가 docker 명령어를 날리면, 도커 클라이언트를 이를 받고 /var/run/docker.sock를 통해 도커 데몬 (dockerd)에게 준다. 도커 데몬은 컨테이너 관리 주체인데, 이것이 실제 명령을 수행하고 결과를 도커 클라이언트를 통해 전달한다.

Docker Swarm

도커 스웜이란 클러스터링을 위해 사용되는 오케스트레이션 툴이다 (그러나 사실 이건 거의 쓰지 않고 쿠버네티스를 쓴다.. 쿠버네티스 짱짱). 간단하게 설명하면 Worker Node (실제 컨테이너가 생성되고 관린되는 도커 서버)와 Manager Node (워커 노드 역할 포함, 워커 노드 관리)로 나눌 수 있다. 이러한 전체를 서비스라 하며, 도커 스웜의 제어 단위가 된다.

서비스란? 같은 이미지에서 생성된 컨테이너의 집합

Docker Compose (이론)

Docker Compose는 여러개의 컨테이너를 하나의 서비스로 정의하고 실행한다! 도커 컴포즈는 도커 밖에 있어 따로 설치 해야한다. docker-compose.yml로 작성한뒤 실행할 수 있다 (물론 다른 파일명도 가능). 필자는 로컬에서 띄워볼 때 도커 컴포즈를 애용하는 편이다.

Dockerfile

Dockerfile은 Docker Image를 생성하기 위한 Script라 생각하면 편하다. 간단하게는 이렇게 가능하다.

FROM python:3.8-slim

WORKDIR /scripts

COPY . /scripts/

RUN pip install -r requirements.txt

EXPOSE 5000

CMD ["python", "api.py"]

위 코드는 Python flask를 간단하게 띄우는 Dockerfile이다.
간단하게 설명하면, FROM은 베이스 이미지를 선택한다.
WORKDIR는 작업 디렉토리를 지정한다.
COPY나 ADD는 호스트의 파일이나 폴더를 이미지로 가져온다.
여기는 없지만 USER는 어떤 계정으로 실행할지 정해준다.
마찬가지로 여긴 없지만 ENV는 환경변수 값을 정해준다.
RUN은 명령어를 실행하는데 쓰인다. 이는 새 layer를 만들어주고 새 이미지를 만든다. CMD와 ENTRYPOINT라는게 있는데, ENTRYPOINT는 지정된 명령어로 무조건 실행이 되는 반면, CMD는 컨테이너 실행시 지정한 인자 값을 쓰게 할 수 있다. 설명을 좀 하자면, docker run으로 실행시 커맨드를 추가적으로 주면, CMD는 무시되는 반면 ENTRYPOINT는 무조건 실행된다.

Dockerfile은 docker build -t [image:image_version] [Dockerfile location]을 통해 이미지를 빌드하고 생성 할 수 있다. 빌드 된 이후 docker run [option] [name] [command] [arg]로 구동할 수 있다.

꿀팁 flag

-d option을 통해 백그라운드에서 구동할 수 있다! 이후 docker ps를 통해 백그라운드에서 실행되는 친구를 볼 수 있다.
-it option을 도커 컨테이너 안에서 명령어를 날릴 수 있다.
–name option을 통해 컨테이너에 이름 부여가 가능하다.

Docker Compose (사용)

version: '3'

services:
  frontend:
    build:
      context: .
      dockerfile: Dockerfile.frontend
    ports :
      - "3000:3000"
    environment :
      - some=environment

  backend:
    build:
      context: .
      dockerfile: Dockerfile.api
    ports:
      - "5000:5000"

다음과 같은 예시를 보면 프런트엔드와 백엔드 두개의 컨테이너를 하나의 서비스를 띄운다는 것을 어렴풋이 알 수 있다. 여기서 포트 번호와 build할 context와 dockerfile, 그리고 환경변수도 지정해 줄 수 있다. 이 외에도 volumes를 통해 컨테이너에 volume을 mount할 수 있다.

docker-compose up을 통해 실행할 수 있고, -d flag를 통해 백그라운드 실행, –force-recreate을 통해 컨테이너 새로 만들기, –build를 통해 도커 이미지를 다시 빌드하고 compose할 수 있다 (docker compose build를 먼저 하기도 한다)

Reference

https://www.youtube.com/watch?v=IiNI6XAYtrs
https://wooono.tistory.com/12d
https://geekflare.com/docker-vs-virtual-machine/