컨테이너 인프라 환경(2) - 도커

InSeok·2023년 3월 4일
0

컨테이너

  • 파드는 쿠버네티스로부터 IP를 받아 컨테이너가 외부와 통신할 수 있는 경로를 제공하며, 컨테이너들이 정상적으로 작동하는지 확인하고 네트워크나 저장 공간을 서로 공유하게 한다.
  • 컨테이너들이 마치 하나의 호스트에 존재하는 것처럼 작동할 수 있다.
  • 컨테이너는 하나의 운영체제 안에서 커널을 공유하며 개별적인 실행 환경을 제공하는 격리된 공간이다.
    • 개별적 실행환경이란 CPU, 네트워크, 메모리와 같은 시스템 자원을 독자적으로 사용하도록 할당된 환경이다.
    • 각 컨테이너 내부에서 실행되는 애플리케이션들은 서로 영향을 미치지않고 독립적으로 작동할 수 있다.
  • 도커를 사용하면 사용자가 따로 신경 쓰지 않아도 컨테이너를 생성할 때 개별적인 실행 환경을 분리하고 자원을 할당한다.
  • 컨테이너 관리 기능 외에도 컨테이너를 실행하는 데 필요한 이미지를 만들거나 공유하는 등의 다양한 기능을 제공한다.
  • 사용자가 명령어를 입력하는 명령어 도구와 명령어를 받아들이는 도커 데몬으로 구성되있다.

컨테이너 이미지

  • 컨테이너 이미지는 이미지 자체로는 사용할 수 없고 도커로 불러들어야 실제로 작동한다.
  • 컨테이너를 삭제할 때는 내려받은 이미지와 이미 실행된 컨테이너를 모두 삭제해야만 디스크의 용량을 온전히 확보할 수 있다.

이미지 검색하고 내려받기

  • 이미지는 레지스트리라고 하는 저장소에 모여있다.
  • 레지스트리는 도커허브처럼 공개된 레지스트리 일수도있고, 내부에 구축한 레지스트리 일수도있다.
  • 레지스트리 웹사이트에서 직접검색하거나 쿠버네티스 마스터노드에 접속해서 검색할 수 도 있다.
    • docker search nginx
  • 하나의 이미지는 여러개의 레이어로 이루어져있다.
  • 다이제스트
    • 이미지의 고유 식별자로 이미지에 포함된 내용과 이미지의 생성환경을 식별할 수 있다.
    • 식별자는 해시 함수로 생성되며 이미지가 동일한지 검증하는데 사용

이미지 태그

  • 태그는 이름이 동일한 이미지에 추가하는 식별자이다.
    • 도커 이미지의 버전이나 플래폼등을 구분
  • 이미지를 내려받거나 이미지를 기반으로 컨테이너를 구동할 때는 이미지 이름만 사용하고 태그를 명시하지 않으면 latest 태그를 기본으로 사용한다.

이미지 레이어 구조

  • 이미지는 애플리케이션과 각종파일을 담고 있다는 점에서 ZIP 같은 압축파일과 비슷한 역할
  • 이미지는 같은 내용일 경우 여러 이미지에 동일한 레이어를 공유하므로 전체 용량이 감소한다.
  • docker images nginx : 이미지 조회
  • docker history를 통해 이미지를 만드는 명령들을 확인가능

컨테이너 생성(실행)

  • docker run [옵션] <사용할 이미지 이름>[:태그 | @다이제스트]를 통해 새로운 컨테이너를 생성하여 실행하면 결과값으로 16진수 문자열의 고유한 ID가 생성된다.
    • 옵션
      • -d(—detatch)
        • 컨테이너를 백그라운드에서 구동
        • 옵션을 생략하면 컨테이너 내부에서 실행되는 애플리케이션 상태가 화면에 계속 표시된다.
        • 상태를 빠져나오기 위해 crtl+c를 누르면 애플리케이션뿐만아니라 컨테이너도 같이 중단됨
      • —restart always
        • 컨테이너의 재시작과 관련된 정책을 의미
        • 프로그램에 예상치 못한 오류가 발생하거나 도커서비스가 중지되는경우 컨테이너도 작동이 중지 되는데, 이때 컨테이너를 즉시 재시작하거나 리눅스 시스템에서 도커 서비스가 작동할때 컨테이너를 자동으로 시작하도록 설정 가능
  • docker ps 생성한 컨테이너 상태 확인(process status)
  • ps -f <필터링 대상> 검색결과 필터링
    • key = value 형태로 입력
    • 주로 id, name, label 등사용
  • ps 에 표시되는 port와 프로토콜은 컨테이너 내부에서 TCP 프로토콜의 80번 포트를 사용한다는 의미이다.
  • 요청이 호스트에 도달한 후 컨테이너로 도달하기 위해 추가경로 설정이 필요하다.
  • 컨테이너는 변경 불가능한 인프라를 지향한다.
  • docker run -p docker run의 p 옵션은 외부에서 호스트로 보낸 요청을 컨테이너 내부로 전달하는 옵션으로 , -p <요청 받을 호스트 포트>:<연결할 컨테이너 포트>형식으로 사용

컨테이너 내부 파일 변경하기

  • 컨테이너 내부에서 컨테이너 외부의 파일을 사용할 수 있는 방법
    • docker cp
      • docker cp <호스트 경로> <컨테이너 이름>:<컨테이너 내부 경로> 형식으로 호스트에 위치한 파일을 구동중인 컨테이너 내부에 복사한다.
      • 컨테이너에 임시로 필요한 파일이 있는 경우 단편적으로 전송하기 위해 사용
      • 컨테이너에 저장돼 있는 설정 및 로그를 추출해 확인하는 목적으로 사용
    • Dockerfile ADD
      • 이미지는 Dockerfile을 기반으로 만들어지는데, Dockerfile에 ADD라는 구문으로 컨테이너 내부로 복사할 파일을 지정하면 이미지를 빌드할 때 지정한 파일이 이미지 내부로 복사된다.
      • 이후 컨테이너에서 복사한 파일을 사용할 수 있지만, 사용자가 원하는 파일을 선택해 사용할 수 없다는 약점이 있다.
    • 바인드 마운트
      • 호스트의 파일 시스템과 컨테이너 내부를 연결해 어느 한쪽에서 작업한 내용이 양쪽에 동시에 반영되는 방법
      • 새로운 컨테이너를 구동할 때도 호스트와 연결할 파일이나 디렉터리의 경로만 지정하면 다른 컨테이너에 있는 파일을 새로 생성한 컨테이너와 연결할 수 있다.
    • 볼륨
      • 호스트의 파일 시스템과 컨테이너 내부를 연결하는 것은 바인드 마운트와 동일하지만,

        호스트의 특정 디렉터리가 아닌 도커가 관리하는 볼륨을 컨테이너와 연결한다.

      • 도커가 관리하는 볼륨 공간을 NFS와 같은 공유 디렉터리에 생성한다면 다른 호스트에서도 도커가 관리하는 볼륨을 함께 사용할 수 있다.

바인드 마운트로 호스트 와 컨테이너 연결

  1. 컨테이너 내부에 연결할 디렉터리를 호스트에 생성
  2. 컨테이너를 구동하고 컨테이너의 디렉터리와 호스트의 디렉터리를 연결한다.
    • -v <호스트 디렉터리 경로>:[컨테이너 디렉터리 경로] 호스트 디렉터리와 컨테이너 디렉터리를 연결
    • 바인드 마운트는 호스트 디렉터리의 내용을 그대로 컨테이너 디렉터리에 덮어 쓰는데, 컨테이너 디렉터리에 어떠한 내용이 있더라도 해당 내용은 삭제된다.
  • exec 명령어
    • 컨테이너에 접속하거나 내부에 명령을 전달하고 결괏값을 반환하는 명령어
    • docker exec <컨테이너의 ID | 이름> <명령어> 형식으로 실행하면 컨테이너에서 명령을 실행하고 결과를 보여준다.

볼륨으로 호스트와 컨테이너 연결

  • 볼륨: 도커가 직접 관리하며 컨테이너에 제공하는 호스트 공간
  • docker volume create 볼륨이름 명령으로 볼륨을 생성
  • docker volume inspect nginx-volume 명령으로 생성된 볼륨을 조회
  • -v [볼륨이름]:[컨테이너 디렉터리] 로 볼륨 연결
  • 볼륨은 바인드마운트와 달리 호스트 디렉터리를 컨테이너 디렉터리에 덮어쓴느 구조가 아니라 양쪽을 서로 동기화 시키는 구조라 컨테이너 디렉터리에 있는 파일이 보존된다.
  • 하지만 볼륨에 디렉터리와 동일한 파일이 존재한 상태로 연결하는 경우 덮어쓰기가 된다.
  • docker volume ls 사용중인 볼륨을 조회
  • docker volume rm 볼륨 삭제

컨테이너 정리

  • 사용이 끝나고 더이상 사용하지 않을 컨테이너라면 공간 확보를 위해 삭제하는 것이 좋다.
  • 컨테이너 정지
    • 컨테이너나 이미지를 삭제하기 전에 먼저 컨테이너를 정지해야 한다.
    • 동일한 호스트의 포트를 사용하는 컨테이너를 배포하거나 작동중인 컨테이너의 사용자체를 종료할때도 먼저 컨테이너를 정지해야한다.
    • docker ps -f ancestor=
      • 컨테이너를 생성하는데 사용한 이미지를 기준으로 필터링
    • docker stop <컨테이너 이름 | ID> :컨테이너 중지
    • docker start <컨테이너 이름 | ID> : 컨테이너 구동

컨테이너와 이미지 삭제

  • docker rm <컨테이너 이름 | ID> : 컨테이너 삭제
  • docker rom -f : 컨테이너 강제 삭제
  • 컨테이너 삭제후 내려받은 이미지는 아직 남아서 공간을 차지하므로 용량확보를 위해 이미지도 삭제하자.
    • docker rmi <이미지 ID>

컨테이너 이미지 만들기

기본 방법

  • Dockerfile
    • 컨테이너 이미지를 빌드하기 위한 정보를 담고 있다.
    • 빌드용 DSL(Domain-Specific Language, 도메인 특화 언어)로 작성된 파일
    • 도커파일 내용
      • FROM <이미지 이름>:[태그]
        • 이미지를 가져온다.
        • 가져온 이미지 내부에서 컨테이너 이미지를 빌드
      • LABEL <레이블이름>=<값>
        • 이미지에 부가적인 설명을 위한 레이블을 추가
      • EXPOSE <숫자>
        • 생성된 이미지로 컨테이너를 구동할 때 어떤 포트를 사용하는지 알려준다.( 알려주기만 할뿐, 직접 연결하지는 않음)
        • docker run -p 옵션으로 이미지를 컨테이너로 빌드할 때 포트를 연결해야한다.
      • COPY <호스트 경로> <컨테이너 경로>
        • 호스트에서 새로 생성하는 컨테이너 이미지로 필요한 파일을 복사한다.
      • WORKDIR 경로
        • 이미지의 현재 작업 위치를 변경
      • ENTRYPOINT ["명령어", "옵션" …]
        • 컨테이너 구동시 대괄호 안에 든 명령을 실행(첫번째로)
  • docker build : 컨테이너 이미지를 빌드
    • docker build -t basic-img .
      • -t 만들어질 이미지를 의
      • . 은 이미지에 원하는 내용을 추가하거나 변경하는 데 필요한 작업 공간을 현재 디렉터리로 지정한다는 의미

컨테이너 용량 줄이기

  • 기본방법에서 openjdk → GCR에서 제공하는 distroless 로변경
  • distroless는 자바 실행을 위해 경량화된 이미지

컨테이너 내부에서 빌드

  • 빌드 중간에 생성한 파일들과 내려받은 라이브러리 캐시들이 이미지에 그대로 남아 컨테이너 이미지가 가장크다.
  • 컨테이너 이미지는 커지면 커질수록 비효율적으로 작동한다.
  • 하지만 Dockerfile 하나만 빌드하면 컨테이너가 생성되어 편리하다.

최적화해 컨테이너 빌드

  • 멀티 스테이지 빌드
  • 멀티 스테이지는 docker-ce 17.06 버전 부터 지원된다.
  • 멀티스테이지로 빌드후에 으로 표시되는 이미지가 있다.
    • 이름이없는 이런 이미지를 댕글링 이미지라고 하며, 멀티 스테이지 과정에서 자바소스를 빌드하는 과정에 생성된 이미지로 보면된다.
    • docker rmi $(docker images -f dangling=true -q) 명령어로 댕글링 이미지를 삭제해 주자.

쿠버네티스에서 직접 만든 컨테이너 사용

쿠버네티스에서 도커 이미지 구동

  • kubectl create delpoyment <이름> --imgae=이미지 로 디플로이 먼트를 생성하면 오류가난다.
    • 이유는 이미지가 호스트에 존재하는데 기본설정에 따라 이미지를 외부에서 받으려고 시도하기 때문
  • 내부에 존재하는 컨테이너 이미지를 사용하도록 설정해서 디플로이먼트 생성하기
    • 현재 수행되는 구문을 yaml형태로 뽑아내 원하는형태의 디플로이 먼트 만들기
      • --dry-run=client 옵션은 해당 내용을 실제로 적용하지 않은 채 명령을 수행
      • -o yaml 은 현재 수행되는 명령을 야믈 형태로 바꾼다.
      • 현재 수행되는 명령을 야믈형태로 출력해 사용자가 원하는 형태로 변경 가능

레지스트리 구성

  • 호스트에서 생성한 이미지를 쿠버네티스에서 사용하려면 모든 노드에서 공통으로 접근하는 레지스트리가 필요하다.
  • 도커나 쿠버네티스는 도커 허브(레지스트리)에서 이미지를 내려받을 수 있다.
  • 도커 레지스트리 이미지를 사용한 사설 도커 레지스트리 만들기
    • 인증서를 생성하려면 서명 요청서(CSR, Certificate signing request)를 작성해야 한다.
  • 이미지를 레지스트리에서 읽으려면 레지스트리가 서비스되는 주소와 제공되는 이미지 이름을 레지스트리에 등록될 이름으로 지정해야한다.
  • docker tag 명령으로 이미지 레이어를 공유하는 사본을 만들수있다. 윈도우 바로가기와 비슷
  • docker push로 사설 도커 레지스트리에 등록
  • curl <레지스트리 주소>/v2/_catalog-k 명령으로 등록된 이미지 목록 조회 가능
  • 이미지를 삭제하려면 이미지의 ID를 알아야한다.
    • docker images | grep multi 로 이미지 ID 조회
profile
백엔드 개발자

0개의 댓글