Docker 학습 내용 정리

Seondo Choi·2023년 1월 24일
0

[출처] 유데미 - Docker & Kubernetes : 실전가이드

Docker 란?

  • 컨테이너를 생성하고 관리하기 위한 도구

Docker의 장점

  • Docker만 설치하면 로컬에 별도의 프로그램 설치가 필요하지 않다.
    • Docker 이미지에 파이썬이 포함되어 있는 경우 로컬 환경에 파이썬을 설치하지 않고 파이썬을 사용할 수 있다.
  • 개발 환경에 포함된 모든 설정을 프로덕트 환경에 동일하게 적용 할 수 있다.
  • 개발 환경을 공유하고 설치하기 쉬워진다.

이미지 & 컨테이너

  • 이미지
    • 컨테이너의 설계도(=설치 CD의 개념과 유사)
    • 코드와 코드를 실행하는데 필요한 도구를 포함
    • 읽기 전용이다.
  • 컨테이너
    • APP, 웹 사이트, 환경(소프트웨어 유닛) 등을 포함하는 작은 패키지

Dockerfile 세팅

  • FROM : Dockerhub에서 다운로드할 이미지 이름과 버전(=태그)
  • WORKDIR : 컨테이너가 생성될 떄 설정되는 작업 폴더
  • COPY : 호스트 OS의 파일을 컨테이너의 작업 폴더로 복사
    • Host = Docker가 실행되고 있는 OS(내 컴퓨터)
  • RUN : 이미지가 빌드되는 순간 실행되는 명령어
  • EXPOSE : 오픈할 포트를 명시 (실제 오픈되지는 않음)
    • docker run 시 -p 옵션을 주면 Host의 랜덤 포트와 컨테이너의 EXPOSE 포트가 매핑되어 동작한다.
  • CMD : 컨테이너가 실행(run)할 때 최초로 동작하는 명령어

Attached(연결) & Detached(분리) & Interactive(상호작용) 모드

  • Attached
    • docker run을 통해 컨테이너를 생성할 때 attached가 기본값
    • 컨테이너의 출력 결과를 수신할 수 있는 모드(입력은 불가)
  • Detached
    • 컨테이너가 백그라운드에서 돌아가고 있는 중이며 터미널을 통해 응답을 받을 수 없는 상태
    • docker start로 실행하는 경우 detached가 기본값
  • Interactive
    • 컨테이너에 입출력 상태를 열어 놓는 모드
    • docker run 시 -i(=interactive) 옵션을 통해 활성화가 가능하며 -t(=tty) 옵션을 같이 줘서 터미널로 컨테이너와 상호작용 할 수 있으며 -it 로 합쳐서 옵션을 입력한다.
    • docker start 시 -a(=attach), -i(=interactive) 옵션을 통해 터미널로 컨테이너와 상호작용 할 수 있다.

로컬 → 컨테이너, 컨테이너 → 로컬 데이터 복사

  • docker cp를 이용
  • 로컬 → 컨테이너 : docker cp <host path>:<container path>
  • 컨테이너 → 로컬 : docker cp <container path> : <host path>

이미지의 고유식별자

  • name : 이미지의 고유 식별자 (=프로그램 이름)

  • tag : name 안에서 사용되는 고유 식별자 (=버전)

  • 이미지 태그 부여 방법

    • docker build -t : .
  • Docker Image의 tag 변경 방법

    # 변경할 태그는 생략할 경우 자동으로 lastest로 설정
    docker tag <기존 리포지토리 이름>:<기존 태그> <변경할 리포지토리 이름>:<변경할 태그>
    
    # tag 변경 후 Docker Hub에 업로드(Docker id 로그인 필요)
    docker tag <기존 리포지토리 이름>:<기존 태그> <Docker id/리포지토리 이름>:<변경할 태그>
    docker push <Docker id/리포지토리 이름>

Docker pull 없이 run을 통해 컨테이너를 만들 수 있다.

  • 단, 이전에 이미지를 실행한 이력이 있으면 이미지의 업데이트 여부를 확인하지 않고 당시 이미지를 기준으로 컨테이너가 실행되기 때문에 업데이트가 있는지 확인이 필요한 경우 pull을 한 뒤 run을 해야한다.

  • Docker 이미지 → 컨테이너 생성 예제

    # f-node 이미지로 컨테이너를 생성하며 포트는 외부 3000번 포트를 통해
    # 내부 80포트로 연결될 수 있도록 설정하고 detach 모드로 실행
    # 생성되는 컨테이너의 이름은 f-app이며 컨테이너가 중지됨과 동시에 컨테이너는 사라진다.
    docker run -p 3000:80 --rm -d --name f-app f-node

볼륨(Volume)

  • 컨테이너의 폴더/파일과 호스트의 폴더/파일의 연결
    • 볼륨이 설정된 경우 컨테이너가 삭제되어도 내부에 있던 데이터들은 호스트의 연결된 폴더에 남아있는다.
  • 이미지 = 읽기 전용
  • 컨테이너 = 읽기, 쓰기 전용
    • 컨테이너가 삭제(Remove)되는 경우 내부 데이터도 함께 사라진다.
  • 익명 볼륨
    • -v VOL_NAME
    • 도커가 자동으로 설정하는 볼륨으로 컨테이너가 중지되면 볼륨도 같이 사라진다.
    • 실제 호스트 폴더 중 어딘가에 저장이 되지만 접속해 사용은 불가하다.
    • 주로 컨테이너가 동작 중에 임시로 사용해야하는 경우 사용
    • 익명 볼륨을 사용하는 경우 컨테이너가 생성될 때 —rm 옵션을 준 상태에서는 익명 볼륨이 자동으로 사라지지만 아닌 경우에는 볼륨이 그대로 남아있는 상태로 계속 생기기 때문에 docker volume rm VOL_NAME 또는 docker volume prune 을 통해 익명 볼륨을 삭제 해야한다.
  • 네임드 볼륨
    • -v HOST_NAME:VOL_NAME
    • 컨테이너 종료 후에도 유지 가능한 볼륨
    • 이미지 → 컨테이너 생성 시 -v 옵션을 통해 사용하며 ‘호스트 경로’:’컨테이너 경로’ 를 입력해야 한다.
  • 바인드 마운트
    • -v HOST_ABS_PATH:VOL_NAME
    • -v HOST_ABS_PATH:VOL_NAME:ro : read only 읽기 전용 모드
    • 호스트 머신 상에 매핑될 컨테이너의 경로를 사용자가 직접 지정
    • 네임드 볼륨과 마찬가지로 -v를 통해 옵션을 주지만 호스트 경로를 부여할 때 절대경로 형태로만 부여가 가능하다
      • 전체 경로 복사가 불편할 경우 아래처럼 대체할 수 있다.
      • Mac/Linux : -v $(pwd):/app
      • Windows : -v "%cd%":/app
    • 호스트에서 수정한 코드나 파일들이 이미지 빌드 필요 없이즉시 컨테이너에 반영
    • 네임드 볼륨과 바인드 마운트가 같이 사용되는 경우 -v 옵션이 2번 들어간다.
    • 파일 하나만 공유하는 것이 아닌 프로젝트 폴더 전체를 공유할 때 주로 사용하며 경로의 특수문자나 공백이 깨지지 않도록 따옴표로 호스트 경로와 컨테이너 경로까지를 묶어주는 것이 좋다.
  • 볼륨 설정이 여러개인 경우 도커는 더 상세하고 긴 경로를 우선으로 동작한다.

.dockerignore 를 생성해 파일/폴더를 이미지 생성 시 제외시킬 수 있다.

  • .git, Dockerfile 등 이미지에 필요 없는 파일을 제외

빌드 인수(Arg)와 런타임 환경변수(Env)

  • 빌드 인수(Build Arguments)
    • 이미지와 컨테이너를 동적으로 빌드할 수 있게 만드는 요소
  • 런타임 환경변수(Runtime Environment)
    • 이미지를 빌드하거나 컨테이너 실행 시 외부에서 특정 데이터를 전달

컨테이너와 로컬호스트가 통신하는 방법

  • Docker 컨테이너와 호스트 pc의 통신이 필요할 때 주소에localhosthost.docker.internal 로 대체하면 컨테이너와 호스트의 통신이 가능하다.

컨테이너끼리 통신하는 방법

  • docker container inspect <CONT_NAME> 을 입력 후 NetworkSettings를 참조하면 해당 컨테이너의 IP를 알 수 있으며 이를 이용해 컨테이너끼리 통신할 수 있다.
  • 단, 해당 IP는 시스템에 따라 달라 질 수 있다.

컨테이너들의 네트워크를 하나로 묶어 통신하는 방법

  • 컨테이너 생성 시 --network <NET_NAME> 옵션을 통해 여러 컨테이너를 하나의 네트워크로 묶을 수 있다.
  • 단, 네트워크는 컨테이너 생성 전 미리 docker network create <NET_NAME> 을 통해 도커 내부 네트워크를 만들어 둔 상태로 생성해야 사용이 가능하다.
  • 같은 네트워크로 연결된 컨테이너와 통신 하고 싶을 때에는 localhost(=127.0.0.1) -> <CONT_NAME> 처럼 IP 대신 컨테이너 이름을 넣어주면 네트워크 내부 컨테이너 사이의 통신이 가능하다.

Docker-Compose

  • 여러 컨테이너의 Image 생성과 컨테이너 생성 시 복잡한 명령어를 여러번 입력하는 것을 편하게 하기 위해 나온 아이디어
  • 하나의 호스트에서 관리하는 컨테이너가 여러개일 때 유용
    • 다수의 호스트에서 다수의 컨테이너를 관리에는 장점 X
  • Services(=Containers)
  • docker-compose를 사용해 서비스가 시작되면 기본적으로 detach 모드로 실행되고 서비스가 종료되면 자동으로 서비스가 사라진다.
  • Linux의 경우 Docker-Compose를 별도로 설치해야한다. (https://docs.docker.com/compose/install/)
  • docker-compose.yaml 설정 예시
    version: "3.8"
    services:
    	<SERVICE1>:
    		image: <IMG_NAME>
    		volumes:
    			- <SERVICE_PATH> # Anonymous volume
    			- <HOST_PATH>:<SERVICE_PATH> # Named volume
    		environment:
    			- <ENV_NAME1>:<VAR1>
    			- <ENV_NAME2>:<VAR2>
    		env_file:
    			- <RELATIVE PATH> # docker-compose.yaml 기준의 상대 경로
    		ports:
    			- '80:80'
    		depends_on:
    			# 해당 서비스가 다른 서비스에 의존성을 가질 경우 표기
    			- <SERVICE_NAME>
    			- ...
    		# -i
    		stdin_open: true 
    		# -t
    		tty: true
    		# 컨테이너의 이름을 직접 짓고 싶을 떄 사용
    		container_name: <VAR_NAME> 
    
    	<SERVICE2>:
    		build:<REALTIVE PATH> #이미지를 빌드하기 위한 Dockerfile의 경로
    		...
    volumes:
    	<VOL_NAME>: # Named volume만 기재
  • Docker-Compose 실행/종료
    • docker-compose.yaml 이 있는 경로에서 터미널을 이용해 docker-compose up 을 입력하면 서비스가 실행되며 docker-compose up -d 를 하면 서비스를 백그라운드에서 실행할 수 있다.
    • docker-compose down 을 입력하면 서비스가 종료되며 docker-compose down -v 를 입력하면 서비스에서 생성됐던 볼륨까지 같이 삭제가 된다.
profile
기초가 튼튼한 엔지니어를 목표로 달리는 중

0개의 댓글