도커와 쿠버네티스 4: 도커 기초
도커 기초 개념
도커 작동 방식
- 도커의 전체 구조는 도커 클라이언트, 도카 호스트, 도커 레지스트리로 구성된다.
- 도커 클라이언트: 도커에 명령을 내릴 수 있는 CLI 도구를 의미하는데 이를 이용하여 컨테이너, 이미지, 볼륨 등을 관리할 수 있다는 것
- 도커 호스트: 도커를 설치한 서버 혹은 가상머신인데 이는 물리 서버가 될 수도 있고, 가상 서버가 될 수도 있다는 것
- 도커 레지스트리: 도커 이미지를 저장하거나 배포하는 시스템인데 크게 공개와 개인 레지스트리로 나눌 수 있다는 것
- 도커 허브: 가장 유명한 공개 레즈스트리인데 도커를 사용하는 사람이라면 누구나 도커 허브에서 이미지를 다운로드하거나 업로드할 수 있다
- 도커 클라이언트에서 명령어를 입력 → 호스트의 도커 데몬이 명령을 받음 → 도커 호스트에 이미지가 존재하지 않는다면 도커 레지스트리에서 다운로드
- 도커 데몬: 도커와 관현된 리소스를 관리하는 백그라운드 프소레스이다
도커 이미지
- 도커 이미지: 컨테이너 형태로 소프트웨어를 배포하기 위하여 필요한 모든 요소를 실행할 수 있는 포맷으로 컴파일 및 빌드한 패키지
- 독립적 → 의존성을 고려할 필요가 없다 ⇒ 경량화된 패키지이므로 비교적 작은 용량으로도 제 역할을 수행할 수 있다
- 도커 이미지를 통해 동일한 환경을 가진 여러 개의 컨테이너를 손쉽게 생성할 수 있다
- 여러 개의 레이어로 구성되어 있고 도커 허브와 같은 중앙 저장소에 저장되어 관리된다 → 도커 허브에 업로드하거나 다운로드할 수 있다
도커 컨테이너
- 도커 이미지를 실행할 수 있는 인스턴스 → 도커 이미지로부터 생성되며 도커 컨테이너에 대해 실행, 중지, 재실행, 삭제 등의 명령을 내릴 수 있다
- 컨테이너는 자체적으로 파일 시스템을 가지고 있으며, 각 컨테이너는 독립적으로 실행된다 → 자체적으로 파일 시스템을 포함한다
- 운영체제를 포함해야 되는데 컨테이너 내부에는 자체적으로 운영체제 전부를 포함하지는 않음 ⇒ 가볍다
- 도커 엔진과 운영체제를 공유한다 → 컨테이너는 도커 엔진이 설치되어 있는 호스트 운영체제를 이용한다는 뜻 ⇒ 컨테이너 내부는 프로그램을 실행시키기 위해 최소한으로 필요한 바이너리, 라이브러리와 같은 구성 요소로 이루어져 있다
hello world 실행 과정
- 3장에서
docker run hello-world
실행해봤는데 입력했을 때 어떤 일이 일어났는지를 자세히 살펴보겠다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 {이미지 이름:태그 이름}
을 입력하면 도커 이미지를 다운로드하게 되는데, 도커 데몬은 도커 호스트에 해당 이미지가 있는지 확인하고 이미지가 없을 경우 도커 레지스트리에서 해당 이미지를 다운로드한다docker image pull [이미지 이름@DIGEST]
를 입력하면 Digest 값을 이용하여 이미지를 다운로드하게 된다- 레이어로 구성된 도커 이미지를 다운로드하는 경우, 각 레이어의 해시값을 확인할 수 있고 모든 레이어를 포함하는 Digest 값을 확인할 수 있다
도커 이미지 상세 구조
- 도커 이미지는 크게 이미지 인덱스, 이미지 매니페스트, 레이어라는 세 가지 구조로 이루어져 있다
- 이미지 인덱스: digest는 이미지 인덱스 해당하는데 다수의 이미지 매니페스트로 구성되어 있다
- 이미지 매니페스트: 다양한 운영체제 및 아키텍처에서 해당 이미지를 활용할 수 있도록 설정값과 다양한 레이어들을 제공한다
도커 이미지 목록 확인
docker image ls
명령어를 이용하여 다운로드한 도커 이미지 목록을 확인할 수 있다- Repository: 이미지 이름
- Tag: 이미지 태그
- Image ID: 다운로그한 이미지의 ID → 다운로드한 후에 로컬에서 할당받은 ID값 (Digest과 다르다)
- Created: 이미지가 만들어진 시간
- Size: 이미키 크기
도커 컨테이너 실행
도커 컨테이너 목록 확인
컨테이너 내부 접속
-it
옵션을 활용하면 컨테이너 내부에 접속할 수 있다[Duplicate Session]
을 통해 새로운 터미널을 만들기 되는데, 이 터미널에서 실행 중인 컨테니러 목록을 확인해보면 우분투 컨테이너가 나온다- 종료된 컨테이너에 다시 접속하고 싶으면 아래 명령어와 같이 입력하면 된다
start
: 컨테이너 실행attach
: 컨테이너 내부 접속
도커 컨테이너 삭제
도커 이미지 삭제
도커 이미지 변경
도커 이미지를 수정한 후 새로운 이미지를 만들어보겠다. 기준 우분투 이미지를 컨테이너로 실행하고 네트워크 도구를 설치한 후 나만의 도커 이미지를 생성해보겠다 (터미널 두 개 사용)
- 먼저 도커 이미지 목록을 확인하고,
-it
옵션을 이용하여 우분투 컨테이너를 실행하겠다 ifconfig
명령어를 찾을 수 없다고 해서 net-tools를 설치해야 겠다ifconfig
명령어를 이용하여 IP 주소를 확인할 수 있다- 지금 net-tools가 설치된 컨테이너를 새로운 이미지로 만들어보겠다. 터미널2에서 컨테이너 목록을 출력하여 우분투 이미지에 해당하는 컨테이너 ID를 확인한다
commit
명령어를 이용하여 실행 중인 컨테이너를 my-ubuntu:0.1이라는 새로운 이미지로 생성해보겠다- 터미널1에서
exit
을 이용하여 우분투룰 나간 후 도커 컨테이너 목록을 출력하여 컨테이너 ID를 확인하고 실행했던 우분투 컨테이너를 삭제한다 - 다음에는 my-ubuntu:0.1 성공적으로 만든 것을 확인하도록 도커 이미지 목록을 출력하고 my-ubuntu:0.1을 실행하여
ifconfig
을 입력해본다- 아싸
도커 이미지 명령어 모음
- 도커 이미지 관련 명령어들은 다
docker image
를 이용한다
명령어 | 설명 |
---|---|
build | Dockerfile로부터 이미지 빌드 |
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 정보 확인한다- 컨테이너 내부의 IP 주소는 172.17.0.2인 걸 확인할 수 있다
- 터미널1에서 컨테이너가 실행 중인 상태를 시키면서 터미널2에서
ifconfig
명령어를 이용하여 도커 호스트의 네트워크 정보를 확인한다 - 컨테이너 내부에는 자체적으로 eth0 인터페이스를 가지고 있는데 도커 호스트에는 docker0, enp0s3, vethe0871f3이라는 인테페이스를 가지고 있다
- docker0: 도커를 설치할 때 함께 설치괴는 인터페이스로, 도커 호스트와 컨테이너를 연결하는 다리 역할을 한다
- veth: 가상 인터페이스인데 이가 컨테이너 내부의 eth0과 도커 호스트의 docker0를 연결시져 준다
- enp0s3: 도커 호스트 자체적으로 보유한 네트워크 인터페이스
도커 네트워크 확인
호스트에서 컨테이너로 파일 전송
호스트에서 컨테이너로 파일을 전송하는 실습을 해보겠다. 터미널 두개가 필요하는데 터미널1은 호스트를 담당하고 터미널2는 컨테이너 내부를 담당한다고 했다.
- 터미널1에서 work 디렉터리로 이동하고 4장 실습 파일을 저장할 디렉터리를 만들어주고, 이 폴더로 이동하고 이번 실습에 사용할 파일을 저장할 ex01이라는 디렉터리를 만든다.
- 터미널2에서 우분투 컨테이너를 실행하고 home 디렉터리로 이동한다
docker container cp [출발 결로/보내고 싶은 파일명] [도착 컨테이너:파일 저장 경로]
명령어를 이용하여 도커 호스트에 존재하는 text01.txt를 컨테이너 내부로 복사한다- 터미널2에서 컨테이너 내부로 잘 이동되는지 확인한다
컨테이너에서 호스트로 파일 전송
이제 반대로 컨테이너에서 호스트로 파일을 전송해보겠다
- 터미널2에서
cp
명령어를 이용하여 test01.txt를 복사하여 test02.txt를 생성한다 - 터미널 2의 컨테이너 내부에는 도커가 설치되어 있지 않아서 컨테이너 내부에서는 도커 명령어를 실행할 수 없으므로 대신에 터미널1을 이용하겠는데 이전 실습과 비슷하게
docker cp
명령어를 이용한다
도커 스토리지
- 도커 컨테이너는 언젠가는 삭제되기 때문에 도커 컨테이너의 파일을 보존하기 위해서는 도커 스스초리지 필요
도커 스토리지의 개념
- 도커 스터리지: 도커 컨테이너에서 생성되는 데이터를 보존하기 위해 사용한다
- 도커 스토리지의 3가지의 종료:
- bind mount: 도커 호스트 디렉터리를 직접 공유하는 방식
- volume: 도커를 활용하여 볼륨을 생성한 후 컨테이너의 디렉터리와 공유하는 방식
- tmpfs: 도커 호스트 메모리에 파일이 저장되는 방식인데 컨테이너를 삭제하면 해당 파일도 함께 삭제된다
도커 스토리지의 필요성
PostgreSQL을 이용하여 도커 스토리지가 왜 필요하는지 알아보겠다
docker image pull
명령어를 이용하여 PostgreSQL의 이미지를 다운로드한다ls
명령어를 이용하여 이미지 목록을 확인한다docker container run
이용하여 postgres 이미지를 컨테이너로 실행한다--name
옵션: 컨테이너 이름-e
옵션: 환경 변수를 설정-d
옵션: 백그라운드 실행
docker container exec -it
명령어를 이용하여 컨테이너 내부에 접속한다- SUPERUSER 권한을 부여한 user01이라는 사용자 생성 → test01라는 데이터베이스를 생성하고 소유자는 user1이라고 설정 → user1로 test01에 접속 → test01에 table1라는 테이블 생성
- table1을 생성한 후 지금 table1을 수정하겠다
SELECT
을 이용하여 table01의 목록을 확인한다INSERT
을 이용하여 table01에 데이터를 삽입한다
docker container stop
명령어를 이용하여 컨테이너 정지한다- 그리고
docker container start
명령어를 이용하여 컨테이너를 다시 실행할 수 있다- 오류… 무시해주시면 감사드리겠습니다…
- 컨테이너를 삭제하고 재생성해보면 user01가 존재하지 않는다는 오류가 나오는 걸 확인한다
volume
- volume은 도커 컨테이너에서 생성되는 데이터가 컨테이너를 삭제한 후에도 유지될 수 있도록 도와주는 저장소이다
docker volume ls
명령어를 이용하여 도커 볼륨 목록을 확인한다docker volume create
명령어를 이용하여 myvolume01라는 볼륨을 생성해본다- 아래 명령어를 이용하여 도커 컨테이너를 생성해본다
--mount
옵션을 활용하여source=[도커 볼륨명],target=[컨테이너 내부 경로]
형태로 사용한다- 명령어 중 쉬표를 사용할 때 띄어쓰기를 하지 않는다는 점에 주의해야 된다
- 이전 실습과 마찬가지로
docker container exec
명령어를 이용하여 컨테이너에 접속하고 나서 PostgreSQL에 접속한다 - 새로운 사용자를 생성해본다
- 파일 목록을 확인한다
- 위 출력 결과로 나오는 파일들이 도커 볼륨에 저장될 예정이다
- 컨테이너 삭제
- 도커 컨테이너를 생성하여 접속하고 나서 PostgreSQL에 접속하면 user01가 존재한다는 걸 확인할 수 있다
inspect
명령어를 이용해 볼륨의 정보를 확인할 수 있다- Mountpoint: 컨테이너 데이터를 보관하는 로컬 호스트 경로이다
- 루트 권한으로 접속한 후 Mountpoint 경로로 이동하여 파일 목록을 확인해본다
- 컨테이너에서 확인했던 데이터가 모두 저장되어 있는 걸 확인했다
bind mount
도커 호스트 디렉너리와 컨테이너 디렉터리를 연결시켜 데이터를 보관하는 방식이다
- ex01 경로로 이동한다
--mount type=bind
옵션을 이용하여 컨테이너를 생성하여 실행한다--mount
통해서 도커 호스트의 ex01 경로와 컨테이너 내부의 work 경로를 연결시켜 준다
- 컨테이너에 접속하고 나서 컨테이너 내부 work 디렉터리의 파일 목록을 확인한다
- 컨테이너 내부의 /work 결로에서
mkdir
명령어를 이용하여 test_dir라는 디렉터리를 생성한다 - 터미널2에서 도커 호스트에 있는 ex01 디렉터리의 파일 목록을 확인한다
- test_dir도 나오는 것 확인
- 도커 호스트에서 test_dir를 삭제한다
- 컨테이너 내부에서도 삭제되어 있는지를 확인해본다
tmpfs mount
중요한 데이터를 일시적으로 도커 호스트 메모리에 저장하고 싶을 때 사용하며 컨테이너 간 데이터 공유를 지원하지 않는다 → 실행 중인 컨테이너를 정지시키면 tmpfs mount도 삭제된다
This post is licensed under CC BY 4.0 by the author.