Post

도커와 쿠버네티스 4: 도커 기초

도커 기초 개념

도커 작동 방식

  • 도커의 전체 구조는 도커 클라이언트, 도카 호스트, 도커 레지스트리로 구성된다.
    • 도커 클라이언트: 도커에 명령을 내릴 수 있는 CLI 도구를 의미하는데 이를 이용하여 컨테이너, 이미지, 볼륨 등을 관리할 수 있다는 것
    • 도커 호스트: 도커를 설치한 서버 혹은 가상머신인데 이는 물리 서버가 될 수도 있고, 가상 서버가 될 수도 있다는 것
    • 도커 레지스트리: 도커 이미지를 저장하거나 배포하는 시스템인데 크게 공개와 개인 레지스트리로 나눌 수 있다는 것
      • 도커 허브: 가장 유명한 공개 레즈스트리인데 도커를 사용하는 사람이라면 누구나 도커 허브에서 이미지를 다운로드하거나 업로드할 수 있다
  • 도커 클라이언트에서 명령어를 입력 → 호스트의 도커 데몬이 명령을 받음 → 도커 호스트에 이미지가 존재하지 않는다면 도커 레지스트리에서 다운로드
    • 도커 데몬: 도커와 관현된 리소스를 관리하는 백그라운드 프소레스이다

도커 이미지

  • 도커 이미지: 컨테이너 형태로 소프트웨어를 배포하기 위하여 필요한 모든 요소를 실행할 수 있는 포맷으로 컴파일 및 빌드한 패키지
  • 독립적 → 의존성을 고려할 필요가 없다 ⇒ 경량화된 패키지이므로 비교적 작은 용량으로도 제 역할을 수행할 수 있다
  • 도커 이미지를 통해 동일한 환경을 가진 여러 개의 컨테이너를 손쉽게 생성할 수 있다
  • 여러 개의 레이어로 구성되어 있고 도커 허브와 같은 중앙 저장소에 저장되어 관리된다 → 도커 허브에 업로드하거나 다운로드할 수 있다

도커 컨테이너

  • 도커 이미지를 실행할 수 있는 인스턴스 → 도커 이미지로부터 생성되며 도커 컨테이너에 대해 실행, 중지, 재실행, 삭제 등의 명령을 내릴 수 있다
  • 컨테이너는 자체적으로 파일 시스템을 가지고 있으며, 각 컨테이너는 독립적으로 실행된다 → 자체적으로 파일 시스템을 포함한다
    • 운영체제를 포함해야 되는데 컨테이너 내부에는 자체적으로 운영체제 전부를 포함하지는 않음 ⇒ 가볍다
  • 도커 엔진과 운영체제를 공유한다 → 컨테이너는 도커 엔진이 설치되어 있는 호스트 운영체제를 이용한다는 뜻 ⇒ 컨테이너 내부는 프로그램을 실행시키기 위해 최소한으로 필요한 바이너리, 라이브러리와 같은 구성 요소로 이루어져 있다

hello world 실행 과정

  • 3장에서 docker run hello-world 실행해봤는데 입력했을 때 어떤 일이 일어났는지를 자세히 살펴보겠다 photo 1
    • docker run hello-world: docker는 도커 관련 명령어를 입력하겠다는 의미인데, run은 컨테이너를 실행하겠다는 뜻이고 hello-world는 컨테이너 이름이다
    • Unable to find image 'hello-world:latest locally: 이미지를 찾을 수 없다는 뜻인데 ‘hello-world:latest’라는 이미지를 다운로드한 적 없어서 나온다
    • latest: Pulling from library/hello-world: 로컬에 ‘hello-world:latest’라는 이미지가 없으므로 library/hello-world에서 pull을 받겠다는 의미인데, pull은 도커 이미지를 원격 저장소에서 로컬로 다운로드하는 것으로 도커 허브에서 hello-world 이미지를 다운로드한다는 뜻이다
    • c1ec31eb5944: Pull complete: pull이 완료되었다는 뜻
    • Digest: sha256:XXXXXXXXXXX: 도커 이미지들은 식별값으로 해시값을 갖게 되는데 참고로 Digest한 해시 함수를 거쳐 나온 후의 데이터이다
    • Status: Downloaded newer image for hello-world:latest: 도커 이미지 ‘hello-world:latest’의 다운로드가 완료되었다는 것

도커 기초 명령어

도커 이미지 다운로드

  • docker image pull {이미지 이름:태그 이름}을 입력하면 도커 이미지를 다운로드하게 되는데, 도커 데몬은 도커 호스트에 해당 이미지가 있는지 확인하고 이미지가 없을 경우 도커 레지스트리에서 해당 이미지를 다운로드한다
    • 태그 이름 없이 입력하면 자동으로 latest 태그가 적용된다
      • 우분투 이미지 다운로드 photo 2
  • docker image pull [이미지 이름@DIGEST]를 입력하면 Digest 값을 이용하여 이미지를 다운로드하게 된다
  • 레이어로 구성된 도커 이미지를 다운로드하는 경우, 각 레이어의 해시값을 확인할 수 있고 모든 레이어를 포함하는 Digest 값을 확인할 수 있다
    • 파이썬 이미지 다운로드 photo 3

도커 이미지 상세 구조

  • 도커 이미지는 크게 이미지 인덱스, 이미지 매니페스트, 레이어라는 세 가지 구조로 이루어져 있다
    • 이미지 인덱스: digest는 이미지 인덱스 해당하는데 다수의 이미지 매니페스트로 구성되어 있다
    • 이미지 매니페스트: 다양한 운영체제 및 아키텍처에서 해당 이미지를 활용할 수 있도록 설정값과 다양한 레이어들을 제공한다

도커 이미지 목록 확인

  • docker image ls 명령어를 이용하여 다운로드한 도커 이미지 목록을 확인할 수 있다 photo 4
    • Repository: 이미지 이름
    • Tag: 이미지 태그
    • Image ID: 다운로그한 이미지의 ID → 다운로드한 후에 로컬에서 할당받은 ID값 (Digest과 다르다)
    • Created: 이미지가 만들어진 시간
    • Size: 이미키 크기

도커 컨테이너 실행

  • docker container run [이미지명]을 입력하면 도커 호스트의 도커 데몬이 실행 명령을 요청박도 도커 호스트에 있는 이미지를 컨테이너 형태로 실행한다 photo 5
    • 출력값이 없음

도커 컨테이너 목록 확인

  • docker container ls를 이용하여 실행 중인 도커 컨테이너를 확인할 수 있다. photo 6
    • 실행했던 우분투와 파이썬 컨테이너는 실행 중인 컨테이너가 아니라서 목록에 뜨지 않는다 → -a 옵션을 추가하면 출력할 수 있다 photo 7

컨테이너 내부 접속

  • -it 옵션을 활용하면 컨테이너 내부에 접속할 수 있다 photo 8
  • [Duplicate Session]을 통해 새로운 터미널을 만들기 되는데, 이 터미널에서 실행 중인 컨테니러 목록을 확인해보면 우분투 컨테이너가 나온다 photo 9
    • 터미널1에서 exit 명령어를 통해 컨테이너 밖으로 나가면 되고, 터미널2에서 docker container stop [컨테이너 ID]를 통해 컨테이너를 종료시켜도 된다 photo 10
      • docker container kill라는 컨테이너를 즉시 종료시키는 명령어가 있긴 하지만 stopkill보다 안정성 면에서 효율적이므로 stop 명령어를 사용하기 권장
  • 종료된 컨테이너에 다시 접속하고 싶으면 아래 명령어와 같이 입력하면 된다 photo 11
    • start: 컨테이너 실행
    • attach: 컨테이너 내부 접속

도커 컨테이너 삭제

  • docker container rm [컨테이너 ID]를 이용하여 컨테이너를 삭제할 수 있다 photo 12

도커 이미지 삭제

  • 비슷하게도 docker image rm [이미지 ID]을 입력하면 이미지를 삭제할 수 있다 photo 13

도커 이미지 변경

도커 이미지를 수정한 후 새로운 이미지를 만들어보겠다. 기준 우분투 이미지를 컨테이너로 실행하고 네트워크 도구를 설치한 후 나만의 도커 이미지를 생성해보겠다 (터미널 두 개 사용)

  • 먼저 도커 이미지 목록을 확인하고, -it 옵션을 이용하여 우분투 컨테이너를 실행하겠다 photo 14
  • ifconfig 명령어를 찾을 수 없다고 해서 net-tools를 설치해야 겠다 photo 15
  • ifconfig 명령어를 이용하여 IP 주소를 확인할 수 있다 photo 16
  • 지금 net-tools가 설치된 컨테이너를 새로운 이미지로 만들어보겠다. 터미널2에서 컨테이너 목록을 출력하여 우분투 이미지에 해당하는 컨테이너 ID를 확인한다 photo 17
  • commit 명령어를 이용하여 실행 중인 컨테이너를 my-ubuntu:0.1이라는 새로운 이미지로 생성해보겠다 photo 18
  • 터미널1에서 exit을 이용하여 우분투룰 나간 후 도커 컨테이너 목록을 출력하여 컨테이너 ID를 확인하고 실행했던 우분투 컨테이너를 삭제한다 photo 19
  • 다음에는 my-ubuntu:0.1 성공적으로 만든 것을 확인하도록 도커 이미지 목록을 출력하고 my-ubuntu:0.1을 실행하여 ifconfig을 입력해본다 photo 20
    • 아싸

도커 이미지 명령어 모음

  • 도커 이미지 관련 명령어들은 다 docker image를 이용한다
명령어설명
buildDockerfile로부터 이미지 빌드
history이미지 히스토리 확인
import파일 시스템 이미지 생성을 위한 타볼 콘텐츠 임포트
inspect이미지 정보 표시
load타볼로 묶인 이미지 로드
ls이미지 목록 확인
prune사용하지 않는 이미지 삭제
pull레지스트리로부터 이미지 다운로드
push레지스트리로 이미지 업로드
rm하나 이상의 이미지 삭제
save이미지 타볼로 저장
tag이미지 태그 생성

도커 컨테이너 명령어 모음

  • 도커 컨티이너 관련 모든 명령어들은 docker container를 이용한다
명령어설명
attach실행 중인 컨테이너의 표준 입출력 스트림에 붙는 것
commit변경된 컨테이너에 대한 새로운 이미지 생성
cp컨테이너와 로컬 파일 시스템 간 파일/폴더를 복사
create새로운 컨테이너를 생성
diff컨테이너 파일 시스템의 변경 내용 검사
exec실행 중인 컨테이너에 명령어 실행
export컨테이너 파일 시스템 타볼로 추출
inspect하나 이상의 컨테이너의 자세한 정보 표시
kill하나 이상의 실행 중인 컨테이너를 kill한다
logs컨테이너 로그를 불러오기
ls컨테이너 목록 확인
pause하나 이상의 컨테이너 내부의 모든 프로세스 정지
port특정 컨테이너의 매핑된 포스 리스트 확인
prune멈춰 있는 모든 컨테이너 삭제
rename컨테이너 이름을 다시 짓기
restart하나 이상의 컨테이너 재실행
rm하나 이상의 컨테이너 삭제
run이미지로부터 컨테이러를 생성하고 실행 (create + start 합치는 것으로 생각해보면 됨)
start멈춰 있는 하나 이상의 컨테이너 실행
stats컨테이너 리소스 사용 통계 표시
stop하나 이상의 실행 중인 컨테이너 정지
top컨테이너의 실행 중인 프로세스 표시
unpause컨테이너 내주의 멈춰 있는 프로세스 재실행
update하나 이상의 컨테이너 설정 업데이트
wait컨테이너 종료될 때까지 기다린 후 exit code 표시
  • exec 명령어는 새로운 프로세스를 시작해서 컨테이너 내에서 작업을 수행하는 것인데 attach 명령어는 기준에 실행 중인 프로세스에 연결하는 것이다

도커 컨테이너 네트워크

도커 컨테이너 네트워크 구조

  • 우분투 컨테이너를 실행하고 ifconfig 명령어를 이용하여 IP 정보 확인한다 photo 21
    • 컨테이너 내부의 IP 주소는 172.17.0.2인 걸 확인할 수 있다
  • 터미널1에서 컨테이너가 실행 중인 상태를 시키면서 터미널2에서 ifconfig 명령어를 이용하여 도커 호스트의 네트워크 정보를 확인한다 photo 22
  • 컨테이너 내부에는 자체적으로 eth0 인터페이스를 가지고 있는데 도커 호스트에는 docker0, enp0s3, vethe0871f3이라는 인테페이스를 가지고 있다
    • docker0: 도커를 설치할 때 함께 설치괴는 인터페이스로, 도커 호스트와 컨테이너를 연결하는 다리 역할을 한다
    • veth: 가상 인터페이스인데 이가 컨테이너 내부의 eth0과 도커 호스트의 docker0를 연결시져 준다
    • enp0s3: 도커 호스트 자체적으로 보유한 네트워크 인터페이스

도커 네트워크 확인

  • docker network ls 명령어를 이용하여 도커 네트워크를 확인한다 photo 23
    • bridge 드라이버: 컨테이너를 생성할 때 제공하는 기본 드라이버이며 각 컨테이너는 각자의 네트워크 인터페이스를 가진다 → 도커 호스트의 docker0과 바인딩된다
    • host 드라이버: 컨테이너를 생성할 때 컨테이너 자체적으로 네트워크 인터페이스를 가지지 않고 호스트 네트워크 인터페이스를 공유한다
      • 이를 사용하려면 실행 시 --network=host 옵션을 사용한다 photo 24
    • none 드라이버: 실행한 컨테이너가 네트워크 인터페이서를 가지지 않아 컨테이너 외부와의 통신이 불가능한다
      • 이를 사용하려면 실행 시 --network=none 옵션을 사용한다 photo 25

호스트에서 컨테이너로 파일 전송

호스트에서 컨테이너로 파일을 전송하는 실습을 해보겠다. 터미널 두개가 필요하는데 터미널1은 호스트를 담당하고 터미널2는 컨테이너 내부를 담당한다고 했다.

  • 터미널1에서 work 디렉터리로 이동하고 4장 실습 파일을 저장할 디렉터리를 만들어주고, 이 폴더로 이동하고 이번 실습에 사용할 파일을 저장할 ex01이라는 디렉터리를 만든다.
    • 여기서 vim 명령어를 이용하여 test01.txt라는 파일을 만들고 이 텍스트 파일을 채워 저장한 후 cat 명령어를 이용하여 test01.txt의 내용을 확인하고 pwd 명령어를 이용하여 현재 위치를 확인한다 photo 26
  • 터미널2에서 우분투 컨테이너를 실행하고 home 디렉터리로 이동한다 photo 27
  • docker container cp [출발 결로/보내고 싶은 파일명] [도착 컨테이너:파일 저장 경로] 명령어를 이용하여 도커 호스트에 존재하는 text01.txt를 컨테이너 내부로 복사한다 photo 28
  • 터미널2에서 컨테이너 내부로 잘 이동되는지 확인한다 photo 29

컨테이너에서 호스트로 파일 전송

이제 반대로 컨테이너에서 호스트로 파일을 전송해보겠다

  • 터미널2에서 cp 명령어를 이용하여 test01.txt를 복사하여 test02.txt를 생성한다 photo 30
  • 터미널 2의 컨테이너 내부에는 도커가 설치되어 있지 않아서 컨테이너 내부에서는 도커 명령어를 실행할 수 없으므로 대신에 터미널1을 이용하겠는데 이전 실습과 비슷하게 docker cp 명령어를 이용한다 photo 31

도커 스토리지

  • 도커 컨테이너는 언젠가는 삭제되기 때문에 도커 컨테이너의 파일을 보존하기 위해서는 도커 스스초리지 필요

    도커 스토리지의 개념

  • 도커 스터리지: 도커 컨테이너에서 생성되는 데이터를 보존하기 위해 사용한다
  • 도커 스토리지의 3가지의 종료:
    • bind mount: 도커 호스트 디렉터리를 직접 공유하는 방식
    • volume: 도커를 활용하여 볼륨을 생성한 후 컨테이너의 디렉터리와 공유하는 방식
    • tmpfs: 도커 호스트 메모리에 파일이 저장되는 방식인데 컨테이너를 삭제하면 해당 파일도 함께 삭제된다

도커 스토리지의 필요성

PostgreSQL을 이용하여 도커 스토리지가 왜 필요하는지 알아보겠다

  • docker image pull 명령어를 이용하여 PostgreSQL의 이미지를 다운로드한다 photo 32
  • ls 명령어를 이용하여 이미지 목록을 확인한다 photo 33
  • docker container run 이용하여 postgres 이미지를 컨테이너로 실행한다 photo 34
    • --name 옵션: 컨테이너 이름
    • -e 옵션: 환경 변수를 설정
    • -d 옵션: 백그라운드 실행
  • docker container exec -it 명령어를 이용하여 컨테이너 내부에 접속한다 photo 35
  • SUPERUSER 권한을 부여한 user01이라는 사용자 생성 → test01라는 데이터베이스를 생성하고 소유자는 user1이라고 설정 → user1로 test01에 접속 → test01에 table1라는 테이블 생성 photo 36
  • table1을 생성한 후 지금 table1을 수정하겠다 photo 37
    • SELECT을 이용하여 table01의 목록을 확인한다
    • INSERT을 이용하여 table01에 데이터를 삽입한다
  • docker container stop 명령어를 이용하여 컨테이너 정지한다 photo 38
  • 그리고 docker container start 명령어를 이용하여 컨테이너를 다시 실행할 수 있다 photo 39
    • 오류… 무시해주시면 감사드리겠습니다…
  • 컨테이너를 삭제하고 재생성해보면 user01가 존재하지 않는다는 오류가 나오는 걸 확인한다 photo 40

volume

  • volume은 도커 컨테이너에서 생성되는 데이터가 컨테이너를 삭제한 후에도 유지될 수 있도록 도와주는 저장소이다
  • docker volume ls 명령어를 이용하여 도커 볼륨 목록을 확인한다 photo 41
  • docker volume create 명령어를 이용하여 myvolume01라는 볼륨을 생성해본다 photo 42
  • 아래 명령어를 이용하여 도커 컨테이너를 생성해본다 photo 43
    • --mount 옵션을 활용하여 source=[도커 볼륨명],target=[컨테이너 내부 경로] 형태로 사용한다
      • 명령어 중 쉬표를 사용할 때 띄어쓰기를 하지 않는다는 점에 주의해야 된다
  • 이전 실습과 마찬가지로 docker container exec 명령어를 이용하여 컨테이너에 접속하고 나서 PostgreSQL에 접속한다 photo 44
  • 새로운 사용자를 생성해본다 photo 45
  • 파일 목록을 확인한다 photo 46
    • 위 출력 결과로 나오는 파일들이 도커 볼륨에 저장될 예정이다
  • 컨테이너 삭제 photo 47
  • 도커 컨테이너를 생성하여 접속하고 나서 PostgreSQL에 접속하면 user01가 존재한다는 걸 확인할 수 있다 photo 48
  • inspect 명령어를 이용해 볼륨의 정보를 확인할 수 있다 photo 49
    • Mountpoint: 컨테이너 데이터를 보관하는 로컬 호스트 경로이다
  • 루트 권한으로 접속한 후 Mountpoint 경로로 이동하여 파일 목록을 확인해본다 photo 50
    • 컨테이너에서 확인했던 데이터가 모두 저장되어 있는 걸 확인했다

bind mount

도커 호스트 디렉너리와 컨테이너 디렉터리를 연결시켜 데이터를 보관하는 방식이다

  • ex01 경로로 이동한다 photo 51
  • --mount type=bind 옵션을 이용하여 컨테이너를 생성하여 실행한다 photo 52
    • --mount 통해서 도커 호스트의 ex01 경로와 컨테이너 내부의 work 경로를 연결시켜 준다
  • 컨테이너에 접속하고 나서 컨테이너 내부 work 디렉터리의 파일 목록을 확인한다 photo 53
  • 컨테이너 내부의 /work 결로에서 mkdir 명령어를 이용하여 test_dir라는 디렉터리를 생성한다 photo 54
  • 터미널2에서 도커 호스트에 있는 ex01 디렉터리의 파일 목록을 확인한다 photo 55
    • test_dir도 나오는 것 확인
  • 도커 호스트에서 test_dir를 삭제한다 photo 56
  • 컨테이너 내부에서도 삭제되어 있는지를 확인해본다 photo 57

tmpfs mount

중요한 데이터를 일시적으로 도커 호스트 메모리에 저장하고 싶을 때 사용하며 컨테이너 간 데이터 공유를 지원하지 않는다 → 실행 중인 컨테이너를 정지시키면 tmpfs mount도 삭제된다

  • docker container run 명령어를 이용하여 컨테이너 생성 photo 58
  • docker container inspect [컨테이너명] --format '' 명령어를 이용하여 볼륨 정보 확인 photo 59
    • tmpfs 타입으로 저장되어 있는 걸 확인할 수 있고, destination도 확인할 수 있다
This post is licensed under CC BY 4.0 by the author.

Trending Tags