docker 이해해보기

docker를 이해해보자

프로젝트를 제대로 배포해보지 않은 입장에서 docker는 뭔가 개념자체가 잘 와닿지 않았다. 그래서 직접 정리를 하며 docker, k8s, jenkins에 대해 각각 한페이지짜리 정리를 해보려한다.

개요

일단 내가 어떤 Web Service를 개발했는데, 이것이 누군가의 환경에서는 동작하지 않을 수가 있다. 이는 여러 이유가 있겠지만, 한마디로 dependencies가 달라서라고 할 수 있다.

매우 쉬운 예시로, 파이썬으로 Hello world를 출력하는 프로그램을 만들었는데 다른 컴퓨터에서 실행하려니 파이썬이 안깔려있는 상황인 것이다.

  1. 개발환경과 운영환경의 불일치가 있고
  2. 매우 가벼운 실행 패키지가 필요해졌다.

그래서 등장한 것이 Containerization이다.

Docker

Docker는 Docker사의 Container engine을 뜻한다. Container engine이라는 것은 OS level에서 virtualization을 해서 software package를 deliver하는 것을 뜻한다.

각 환경에 따른 가상머신에 앱을 설치하고 실행하는 것이 아닌 OS와 interface한 container라는 곳에서 앱을 실행시킨다.

VM은 메모리 점유가 심하고, 부팅 시간이 느리며 성능저하도 있다. 또한 VM사이에서 데이터 공유도 힘들다. 반면 container를 사용하면 이 모든 단점이 해결된다.

  1. 다양한 화물들을 일정한 규격의 컨테이너에 적재한다. (interface)
  2. 컨테이너를 항구에 내린다. (VM에 container 데려와서)
  3. 컨테이너를 부리고 원하는 작업을 수행한다. (app 실행)

도커 이미지 container engine에는 OS kernel같은게 있는 것이 아니다. 저런 image를 가지고 어디든 가서 앱을 실행시킬 수 있게 된다.

그럼 여기까지 보면 image와 container의 차이가 헷갈리게 된다.

image vs Container

도커 전체 구조 이 그림을 보면 image와 container의 차이를 잘 느낄 수 있다. image는 정적인 파일이다. 그러니깐 정적인 코드를 지니고 있다. image를 가지고 containerization platform에 가면 run시킬 수 있는 것이다. 즉, template의 역할을 한다. (app code, sw system, os)

container = running instance of an image

image는 레시피, container는 만들어진 요리가 된다.

container는 stop, delete할 수 있는데 stop하면 먹다가 냉장고에 넣는 것이고 delete면 다 먹었거나 버린 것이 되겠다.

Docker hub에는 매우 많은 image들이 떠돌아 댕기고 있다. 가져와서 나의 컴퓨터에 컨테이너를 내리고 앱을 실행시킬 수 있다.

예시 코드

docker pull ubuntu
docker images # 내게 있는 이미지들을 볼 수 있다.
docker run -it -d ubuntu 
#1. `-i` (interactive): 컨테이너가 실행되는 동안 입력을 받을 수 있게 합니다.  
# 2. `-t` (tty): 이 옵션은 가상 터미널을 할당합니다. 이것은 `-i` 옵션과 함께 사용되어야 하며, 인터랙티브 쉘 세션을 가지기 위해 필요합니다. 
# 3. `-d` (detached): 이 옵션은 컨테이너를 백그라운드에서 실행하도록 합니다.

docker ps # 실행되고 있는 컨테이너들을 확인할 수 있다.

# exec
docker exec -it <container id> <prompt in the container> 
# container에 있는 bash shell을 실행할 때 쓴다.

# stop
docker stop <container id>
docker kill <container id>
docker ps -a

# remove (container와 image 지우기)
docker rm -f <container id>
docker rmi -f <image id>

docker file

위의 그림에서 docker file만 다루지 않았다. docker hub에서 가져올 수만 있다면 내가 원하는 기능을 찾지 못할 수도 있다. docker file은 docker image를 만들기 위해 실행하는 command 들을 모아 둔 text 파일이다.

  • docker image를 만드는 방법
    1. docker hub에서 가져와서 내 맘대로 바꾸는 명령을 실행한다음 push한다.
    2. dockerfile을 작성하고 build한다. dockerfile은 단순한 text파일로서 크기가 작다.

예시에 주석을 달아서 설명하겠다.

# base이미지로 ubuntu를 사용
FROM ubuntu 

# Update package lists
RUN apt-get update 
#이는 docker run과는 전혀다른 RUN이다. 명령어를 보면 알 수 있다.

# intall Apache2
RUN apt-get install -y apache2

# Add files 현재 디렉토리에서 <dest in container>로 파일 복사 (Copy)
ADD . /var/www/html

# Expose port 80 for HTTP traffic
EXPOSE 80

# Start Apache2 in the foreground
ENTRYPOINT ["apache2ctl", "-D", "FOREGROUND"]

마지막 ENTRYPOINT를 조금 설명해보겠다. CMD라는 명령으로 container 안에서 실행하려는 command를 써둘 수 있는데 ENTRYPOINT를 쓰면 이와 유사하지만 다른 command를 입력해서 docker file의 CMD에 지정된 명령을 생략할 수 없게 할 때 사용한다.

위 dockerfile을 image로 만드는 것은 어떻게 하는가?

vi dockerfile #이름은 반드시 dockerfile이여야한다.

docker rm -f <existing container>
docker build -t <image name> # 이 과정이 image를 dockerfile로부터 만드는것이다.

docker run -it -p <hostport:containerport> -d <image>

docker rm -f <exeisting container>
# port 80에 충돌이 생기지 않게 하기 위해서

p는 published로 호스트 port와 container port를 mapping할 때 쓴다. 외부에서 컨테이너에 접근할 수 있게 된다.

docker volume

여기까지 어찌저찌 이해했다. 근데 만약에 앱을 실행할 때 변경사항을 저장할 필요가 있다면 어떨까? 특히 DB를 사용하는 컨테이너라면 저장이 필수일것이다.

컨테이너는 read-only app으로 사용하는게 기본이다. 왜냐면 컨테이너 각자가 자신만의 OS자원, DRAM영역, cpu시간을 가지고 있고 디스크 같은 persistent storage를 사용하지 않기 때문이다.

여기서 persistent storage를 사용하기 위해 이를 host machine에서 mount해온다. 이것이 docker volume이다.

하지만 이 행위는 보안의 입장에서는 안 좋을 수 있다.

Three types of docker volumes

  1. Host volume - docker run -v /home/mount/data:/var/lib/mysql/data 처럼 사용
  2. anonymous volume - host를 지정하지 않으면 알아서 정해진 폴더에 생성(random hash)
  3. named volume - 생성된 볼륨에 이름을 붙여서 여러 컨테이너가 이름을 통해 공유

docker compose

docker container는 하나의 image만을 실행하는 것이 원칙? 권장된다. 따라서 container들을 여러개가 같이 실행되는 때가 더 많을 것이다. 여기서 docker compose가 등장한다. 이 것은 docker-compose.yml 파일을 실행, 중지, 제거 하는 도구다. docker-compose.yml에는 한 개 이상의 container를 규정하고 run하는 내용이 담겨있다.

  1. docker-compose.yml 파일을 만든다.
version: '3'
services:
  web:
    image: nginx
    ports:
      - "80:80"
  db:
    image: mysql
    environment:
      MYSQL_ROOT_PASSWORD: example

위와 같은 파일을 만들고

  1. inbound rule을 변경해서 외부에서 접근할 수 있게 한다.
  2. docker-compose up -d
    1. build하고 run
    2. 새로운 설정이 있으면 container를 재시작하지 않고 적용시킨다.
    3. -d하면 log를 안 볼 수 있음
  3. docker-compose stop
  4. docker-compose down (–volumes)
    1. 이건 stop과 달리 리소스까지 다 제거하는 것이다.
  5. docker volume ls
  6. docker volume inspect <volume name>
  7. docker volume rm <volume name>

yml파일에 volume 적용되어 있으면 알아서 잘 저장 될 것이다.

docker network

compose를 하려면 docker container들 사이에 연결이 있어야한다. 즉, 서로 네트워크로 연결되어 통신해야한다는 것이다.

도커가 해준다.

1) bridge– default– virtual L2 switch - each container has its own private IP address
2) host– host의 네트워크와 동일한 네트워크 사용
3) overlay– docker swarm service 네트워크 – conventional overlay network (i.e., conventional virtual network)
4) macvlan– MAC 주소에 대한 완전한 제어 제공 – each container has its own MAC address+IP address
5) ipvlan– IP 주소 사용에 대한 완전한 제어를 제공 – each container has its own IP address sharing MAC with others
6) none– no network interface provided for full customization

namespace & cgroup

컨테이너의 목적을 생각해보자. “단일 호스트 (VM 포함) 에서 서로 독립적으로 분리 운영되는 프로세스 그룹을 만드는 것 (VM을 만드는 것이 아님)” 이를 위해서 namespace와 cgroup 위에 docker container가 만들어진다.

namespace

process trees, network interfaces, user IDs, filesystem mounts 등 시스템 요소들의 경계를 긋고 제한하는 mechanism이다.

Cgroup

 Cgroups는 각 프로세스 그룹에 OS 자원을 배정하고 측정하는 커널 장치 Cgroups를 사용하여 CPU time, network, memory, block io 같은 자원을배정 namespaces에 cgroups를 적용하여 일단의 프로세스들을 container로 구성하여 해당 프로세스들만의 virtual 시스템 구현

Leave a comment

2024

D&C Optimization

8 minute read

분할정복을 이용한 다이나믹 프로그래밍 최적화

Back to top ↑

2023

Back to top ↑

2022

Greedy

2 minute read

백준 18186번 라면사기(large) 문제풀이

SCC

2 minute read

백준 4196번 도미노 문제풀이

LCA

2 minute read

백준 3176번 도로 네트워크 문제풀이

2-SAT

2 minute read

백준 16367번 TV Show Game 문제풀이

Hashing

2 minute read

백준 21162번 뒤집기 K 문제풀이

Tree DP

1 minute read

백준 1949번 우수 마을 문제풀이

Trie

1 minute read

Trie 자료구조 이해하기

Merge Sort

1 minute read

merge sort를 이용하여 inversion 개수세기

Segment Tree

2 minute read

백준 11505 구간 곱 구하기 문제풀이

BFS

1 minute read

백준 2206 벽 부수고 이동하기 문제풀이

기하

1 minute read

백준 2166 다각형의 면적 문제풀이

이분탐색

1 minute read

백준 12015 가장 긴 증가하는 부분 수열2 문제풀이

누적 합

1 minute read

백준 10986 나머지합 문제풀이

Stack

1 minute read

스택 구현하기 ========== 자료구조의 기본이라고 하면 스택 과 큐가 있다 백준 10828번에서 마주친 스택

정렬1

1 minute read

매우매우 많은 정렬이 있지만 그중 가장 안 어려운 3가지를 공부해보았다.

Back to top ↑