ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 02. (쿠버네티스 들어가기 앞서) 왕초보도 따라하는 도커 기초 (1)
    개발 스터디/데브옵스(DevOps)를 위한 쿠버네티스 마스터 2021. 6. 28. 20:50
    반응형

    이 문서는 인프런 강의 "데브옵스를 위한 쿠버네티스 마스터"을 듣고 작성되었습니다. 최대한 요약해서 강의 내용을 최소로 하는데 목표를 두고 있어서, 더 친절하고 정확한 내용을 원하신다면 강의를 구매하시는 것을 추천드립니다. => 강의 링크

    도커를 왜 써야 하는가?

    강의에서는 왜 써야 하는지에 대한 내용은 다음 유튜브 영상 링크를 확인하라고 알려준다. 역시 나도 링크로 ^^

    도커란 무엇인가

    Docker를 알기 전에 먼저 컨테이너가 무엇인지 알아야 한다. 다음은 도커 컨테이너가 실행되는 구조이다.

    쉽게 생각해서 컨테이너는 격리된 환경에서 실행되는 애플리케이션이라고 생각하면 된다. 보통 하드웨어 위에 운영체제 그 위에 컨테이너 런타임(Docker에서는 Docker Engine)을 설치한다.

     

    컨테이너 런타임이 컨테이너를 실행하기 위해서는 먼저 "이미지"가 필요하다. 이미지란 필요한 프로그램, 라이브러리, 소스를 설치한 뒤 만든 하나의 템플릿 파일이다. 컨테이너는 결국 그 이미지를 독립적으로 격리된 공간에서 실행한 가상 환경이라고 보면 된다.

     

    정리하면 다음과 같다.

    • 이미지 : 필요한 프로그램, 라이브러리, 소스를 설치한 뒤 만든 하나의 파일
    • 컨테이너 : 이미지를 독립적으로 격리된 공간에서 실행한 가상 환경

     

    Docker는 이런 컨테이너들을 관리하는 기술을 지원하는 다양한 프로젝트 중 하나이면서 사실 상 표준이다. Docker는 대표적으로 리눅스의 namespacecgroup을 활용하여 만들어졌다. 먼저 리눅스 namespace는 프로세스 별로 파일 시스템, 네트워크, 유저 등 시스템에 독립적인 뷰를 제공하는 기술이다.

    리눅스 cgroup은 각 프로세스 별로 소비할 수 있는 리소스 양을 제한하는 기술이다.

    이런 기술들을 토대로 Docker의 장점은 오버헤드가 매우 적다는 것이다. 또한 격리된 환경이기에 라이브러리 충돌 같은 개발하면서 나타나는 골치 아픈 문제들을 상당 수 제거해준다. 하지만 서비스가 많아질수록 컨테이너 수가 많아지고, Docker 1개로는 수 많은 컨테이너를 관리하는 것이 매우 어렵다는 한계가 있다. (이를 해결하는 것이 Kubernetes 같은 컨테이너 오케스트레이션 도구들이다.)

    도커 설치

    Docker 설치는 VM 환경에서 우분투 18.04에서 진행되었다. 터미널에 다음을 입력한다.

    # sudo -i 해서 수도 권한 획득
    > apt install docker.io -y

     

    위 명령어 실행 시, 다음과 같은 문제가 발생할 수 있다.

    터미널에 재부팅 명령어를 입력한다.

    > reboot

     

    그 후 다시 명령어를 입력한다.

    # sudo -i 해서 수도 권한 획득
    > apt install docker.io -y

     

    설치가 완료되면, 다음을 입력한다.

    > docker -version
    Docker version 20.10.2, build 20.10.2-0ubuntu1~18.04.2

    도커 라이프 사이클

    도커 라이프 사이클은 다음과 같다.

    • pull : 레지스트리에서 이미지를 설치한다.
    • create : 이미지에서 컨테이너를 생성한다.
    • start : 생성한 컨테이너를 실행한다.
    • run : create + start (만약 이미지 없으면 + pull 까지)
    • commit : 컨테이너 변경 사항을 이미지에 업데이트 한다.
    • push : 업데이트된 이미지를 레지스트리에 저장한다.

     

    참고! 레지스트리란?
    도커 이미지를 저장하는 저장소입니다. 공개적으로는 Docker Hub가 있으며, private한 docker registry도 만들 수 있습니다.

    도커 명령어

    이미지 다운로드

    > docker pull nginx

    이미지 삭제 (생성된 컨테이너가 없어야 한다.)

    > docker rmi nginx

    컨테이너 실행1

    # 컨테이너 생성
    > docker create nginx
    d86afd8f4c391a553fca213a84fa4908ebf30727f7a24bb8f4dd05e4d7684d35
    
    # 컨테이너 실행
    > docker start d86afd8f4c391a553fca213a84fa4908ebf30727f7a24bb8f4dd05e4d7684d35

    컨테이너 실행2

    # 컨테이너 생성과 실행
    > docker run nginx

    컨테이너 중지

    # 컨테이너 실행
    > docker stop d86afd8f4c391a553fca213a84fa4908ebf30727f7a24bb8f4dd05e4d7684d35

    컨테이너 삭제

    # 컨테이너 삭제
    > docker rm d86afd8f4c391a553fca213a84fa4908ebf30727f7a24bb8f4dd05e4d7684d35

    실행 중인 컨테이너 확인

    # 컨테이너 확인
    > docker ps

    모든 컨테이너 확인

    # 컨테이너 확인
    > docker ps -a

    포트 포워딩

    # -p <host port>:<container port>
    > docker run -d --name ng -p 80:80 nginx

    컨테이너 셸 실행

    # docker exec -it <contianer name or id> /bin/bash
    > docker exec -it ng /bin/bash

    컨테이너 로그 실행

    # docker logs <contianer name or id>
    > docker logs ng 

    임시 컨테이너 생성 및 실행

    > docker run -d --name ng -p 80:80 --rm nginx 

    모든 컨테이너 중지

    > docker stop 'docker ps -a -q'

    모든 컨테이너 삭제

    > docker stop 'docker ps -a -q'

    모든 컨테이너 중지

    > docker rm 'docker ps -a -q'

    모든 이미지 삭제

    > docker rmi 'docker images -q'

    이미지 비밀 레이어

    Docker는 레이어라는 것을 이용해서 이미지를 저장하게 된다.

    위에처럼 만약 설치된 이미지가 A, B가 있다고 하자. 그럼 머신에는 Layer A, B, C, D가 설치되어 있다. 이 때 이미지 C, D를 설치했을 때 새로운 레이어가 설치될까? 정답은 레이어가 설치되지 않는다. 이미 이미지를 구성하는데 필요한 Layer들이 모두 설치되어 있기 때문이다.

    이와 관련된 자세한 내용은 다음 명령어로 확인할 수 있다.

    > docker inspect nginx
    ...

     

    여기서 출력되는 문구 중요한것만 살펴보자. 먼저 ContainerConfig에서 노출되는 포트 번호, 환경 변수, 실행되는 커맨드를 확인할 수 있다.

    "ContainerConfig": {
        # ...
        "ExposedPorts": {
            "80/tcp": {}
        },
        # ...
        "Env": [
            "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
            "NGINX_VERSION=1.21.0",
            "NJS_VERSION=0.5.3",
            "PKG_RELEASE=1~buster"
        ],
        "Cmd": [
            "/bin/sh",
            "-c",
            "#(nop) ",
            "CMD [\"nginx\" \"-g\" \"daemon off;\"]"
        ],
        # ...
    }

    그리고 RootFS에 저장된 레이어 정보를 확인할 수 있다.

    "RootFS": {
        "Type": "layers",
        "Layers": [
            "sha256:764055ebc9a7a290b64d17cf9ea550f1099c202d83795aa967428ebdf335c9f7",
            "sha256:2418679ca01f484b28bdcd8606d1d5313013cccfbd395123716000c2a25eec09",
            "sha256:cf388fcf3527352baa4ee5bedafd223b2224b13aac5f2df1ea0be47422789892",
            "sha256:165eb6c3c0d39f8c99de581f1bf9cc094e7823a838fbe5c51574c7beb3f6c4ee",
            "sha256:b50a193ebf2e2579b49d30beb9798078e22db0d4490bf51b9b3bb0d8bb7a3833",
            "sha256:c6d74dcb7fe747fac8e74e9453156380ea3ffddf97ed0e6c71e75400d938216e"
        ]
    },

    이 레이어들이 저장되는 곳은 GraphDriver > Data > LowerDir에서 확인할 수 있다.

    "GraphDriver": {
        "Data": {
            "LowerDir": "/var/lib/docker/overlay2/edd7ef5ffb98ae60becd13495f8730594f67d7ccffb206181ac9a7ec42b05bc3/diff:/var/lib/docker/overlay2/3b988cee951a8fb3709d4d5987db269cd7f9cde32009044b3fcea4653a81971a/diff:/var/lib/docker/overlay2/b6e21cc6eb4977a5d86f1e0c8bae4cca5f5c1931e5630c67fca50a6cb3733994/diff:/var/lib/docker/overlay2/d4ca5424cfd2bf95ecfb18c6f998b4514d6101e79bccb75cdcaa980aacfb309a/diff:/var/lib/docker/overlay2/29ae1499d295a892c4334d02db234b6d621f8866d91f21c0d19cc4c1c398d5cd/diff",
            "MergedDir": "/var/lib/docker/overlay2/c8ffb36d5b2a7f0a4efd54ad2b6ea766df62914696016f0cbd855ceafabb2369/merged",
            "UpperDir": "/var/lib/docker/overlay2/c8ffb36d5b2a7f0a4efd54ad2b6ea766df62914696016f0cbd855ceafabb2369/diff",
            "WorkDir": "/var/lib/docker/overlay2/c8ffb36d5b2a7f0a4efd54ad2b6ea766df62914696016f0cbd855ceafabb2369/work"
        },
        "Name": "overlay2"
    },

    이런 도커에 대한 데이터를 저장하는 경로를 알고 싶다면, 다음 명령어로 알 수 있다.

    > docker info
    ...
    Docker Root Dir: /var/lib/docker
    ...

     

    이제 위 경로로 가보자.

    > cd /var/lib/docker/
    > ll
    drwx--x--x 13 root root 4096  6월 28 20:15 ./
    drwxr-xr-x 66 root root 4096  6월 28 19:32 ../
    drwx--x--x  4 root root 4096  6월 28 19:32 buildkit/
    drwx------  2 root root 4096  6월 28 20:03 containers/
    drwx------  3 root root 4096  6월 28 19:32 image/
    drwxr-x---  3 root root 4096  6월 28 19:32 network/
    drwx------  9 root root 4096  6월 28 20:15 overlay2/
    drwx------  4 root root 4096  6월 28 19:32 plugins/
    drwx------  2 root root 4096  6월 28 20:15 runtimes/
    drwx------  2 root root 4096  6월 28 19:32 swarm/
    drwx------  2 root root 4096  6월 28 20:15 tmp/
    drwx------  2 root root 4096  6월 28 19:32 trust/
    drwx------  2 root root 4096  6월 28 20:15 volumes/

     

    여기서 이미지들에 대한 정보는 image 컨테이너에 대한 정보는 containers, 레이어에 대한 정보는 overlay2에 저장된다. 한 번 image디렉토리를 살펴보자.

    > cd /var/lib/docker/image/
    > ll
    합계 12
    drwx------  3 root root 4096  6월 28 19:32 ./
    drwx--x--x 13 root root 4096  6월 28 20:15 ../
    drwx------  5 root root 4096  6월 28 20:36 overlay2/

     

    이제 overlay2(/var/lib/docker/image/overlay2)를 들어가보자

    > cd overlay2
    > ll
    합계 24
    drwx------ 5 root root 4096  6월 28 20:37 ./
    drwx------ 3 root root 4096  6월 28 19:32 ../
    drwx------ 4 root root 4096  6월 28 20:00 distribution/
    drwx------ 4 root root 4096  6월 28 19:32 imagedb/
    drwx------ 5 root root 4096  6월 28 20:01 layerdb/

     

    여기서 layerdb는 결국 /var/lib/docker/overlay2를 참조하게 된다. 이 경로로 가보자.

    > cd /var/lib/docker/overlay2/
    > ll
    합계 36
    drwx------  9 root root 4096  6월 28 20:29 ./
    drwx--x--x 13 root root 4096  6월 28 20:15 ../
    drwx------  3 root root 4096  6월 28 20:00 29ae1499d295a892c4334d02db234b6d621f8866d91f21c0d19cc4c1c398d5cd/
    drwx------  4 root root 4096  6월 28 20:00 3b988cee951a8fb3709d4d5987db269cd7f9cde32009044b3fcea4653a81971a/
    drwx------  4 root root 4096  6월 28 20:00 b6e21cc6eb4977a5d86f1e0c8bae4cca5f5c1931e5630c67fca50a6cb3733994/
    drwx------  4 root root 4096  6월 28 20:01 c8ffb36d5b2a7f0a4efd54ad2b6ea766df62914696016f0cbd855ceafabb2369/
    drwx------  4 root root 4096  6월 28 20:00 d4ca5424cfd2bf95ecfb18c6f998b4514d6101e79bccb75cdcaa980aacfb309a/
    drwx------  4 root root 4096  6월 28 20:00 edd7ef5ffb98ae60becd13495f8730594f67d7ccffb206181ac9a7ec42b05bc3/
    drwx------  2 root root 4096  6월 28 20:03 l/

     

    이름의 의미를 알 수 없는 디렉토리들이 쭉 나열되어 있는다. 위는 모두 레이어 정보이다. 이들은 각 레이어들의 변경 사항을 저장하고 있다. 그리고 l 디렉토리가 있는데 들어가보면 같은 이름의 디렉토리들이 쭉 나열되어 있다. 실제적으로 레이어가 저장하는 FileSystem 정보가 들어있다. 즉 다음과 같이 정리할 수 있다.

     

    위와 같이 /var/lib/docker/images/overlay2/layerdb는 실제적으로 /var/lib/docker/overlay2/를 참조하고 있고 여기는 실제 레이어들의 구성 정보가 들어있는 것이다. 참고적으로 컨테이너가 많아져서 레이어 저장소의 크기를 업데이트해야 하는 경우 /var/lib/docker/overlay2/에 새로운 디스크를 마운트하면 된다.

Designed by Tistory.