[0711] Docker

nikevapormax·2022년 7월 11일
0

TIL

목록 보기
68/116

Docker

bind mount

정의

  • 내가 원하는 volume을 docker container 내의 volume에 연결하는 기능
  • 코드가 수정될 때마다 이미지를 수정하지 않아도 됨!

문법

$ docker run -v {host_path}:{container_path} <docker_image>
  • host_path 알아내는 법
    • 현재 작업중인 파일의 내부로 들어와 templates 안에 들어가 아래와 같이 진행하면 된다.
  • container_path 알아내는 법
    • 이전에 작성했던 dockerfile로 가보면, templates 앞에 점이 찍혀있다. 이 점은 최상단, 즉 root를 뜻하며 path를 입력할 때 /templates를 입력해주면 된다.

bind mount를 통해 application 실행

$ docker run -v "$(pwd):/templates" -p 80:5000 wellshs/docker-memo:version2
  • 위의 것을 바탕으로 아래와 같이 입력하였다.
$ docker run -v "/Users/jeongdaegeun/Desktop/my_refer/스파르타/docker/templates:/templates" -p 80:5000 wjdeorms27/docker-practice:2.0.0
  • 이렇게 마운트를 하게 되면, 로컬에 있는 코드를 수정할 시 브라우저에서도 곧바로 확인이 가능하다. 즉 image를 새로 만드는 작업이 없이도 변경 사항이 실시간으로 반영되게 된다.
  • $(pwd)를 사용하게 되면 내가 아래에 작성했던 내용이 전부 자동으로 들어오게 된다.

Docker에서 여러 개의 container 연결

Docker Network

  • Docker container는 분리된 filesystem과 네트워크를 가진다.
    • 따로 설정을 하지 않으면 filesystem과 network 통신이 불가능하다.
  • 따라서 network를 통해서 docker container끼리 통신을 하게 만들 수 있어요

문법

$ docker network create {네트워크이름}
$ docker run -d -p 27017:27017 --network {네트워크이름} --network-alias mongo mongo
  • 네트워크를 연결하고 나서 dig mongo라는 명령어를 통해 연결이 잘 되었는지 확인할 수 있다.
    • 어디에 연결되었는지 포트 번호가 나오니 확인해야 함!

Docker network로 메모 앱에 DB연결하기

  • 연결 순서는 아래와 같다.
    1) 네트워크 생성
    2) 네트워크 연결
    3) 어플리케이션 코드에서 DB 링크를 변경
  • 코드
$ docker network create memo
$ docker run -d -p 27017:27017 --network memo --network-alias mongo mongo
  • 위와 같이 네트워크를 연결한 뒤, 로컬 app.py로 가서 아래와 같이 변경해준다.
client = MongoClient('mongo', 27017) # localhost -> mongo로 변경
  • 그리고 새로운 이미지를 생성해준다.
$ docker build -t wjdeorms27/docker-practice:3.0.0 .
  • flask app을 network에 연결해준다.
$ docker run -p 80:5000 --network memo wjdeorms27/docker-practice:3.0.0
  • 잘 연결되어 데이터가 저장되었는지 robo 3T로 가서 데이터를 확인해주면 된다.

Docker container 리소스 사용량 제한

  • docker가 host의 리소스를 많이 쓰면 문제가 발생할 수 있다.

cpu, memory 리소스 제한

  • docker에서는 host의 disk와 memory를 같이 사용하고 있다.
  • cpu와 memory, disk의 경우에 최악의 경우 다른 프로세스에도 영향을 줄 수 있는데,
    • memory가 부족할 경우, host의 kernel에서 OOME(Out Of Memory Exception)을 일으켜서 여유 memory를 생성하기 위해서 process를 삭제한다.
    • cpu를 한 container가 다 사용하게 되는 경우 다른 container에 cpu가 할당되지 않아 동작하지 않을 수 있다.
    • disk가 부족할 경우에는 데이터를 disk에 저장하지 못하거나, 새로운 프로세스를 사용하지 못할 수 있다.
  • 따라서 아래의 코드를 통해 제한해보도록 하자.
    • memory 제한하기
      • m말고 g를 주면 10g를 사용할 수 있다.
      $ docker run -i -m 10m python:3.8
    • cpu 제한하기
      • 0.5를 부여한 이유는 python의 경우 1정도의 cpu를 사용하기 때문에 애초에 적게 부여해 많이 사용해도 1정도를 쓸 수 있게 하기 위함이다.
      $ docker run -i --cpus=0.5 python:3.8
    • 사용하고 있는 리소스 확인하기
      $ docker stats
  • 추가 제한 옵션

Docker-compose

정의

  • 여러 컨테이너를 편리하게 실행하기 위해서 만들어둔 도구
  • YAML 파일을 통해 container를 실행하는데 필요한 옵션을 정의할 수 있다.
    • 더 편리하게 실행하는 방법 관리, 버전 관리 등등
    • 일반적으로 docker를 깔 때 compose는 자동적으로 깔리므로, 우리는 YAML 파일을 생성해주면 된다.
    • YAML : YAML Ain't Markup Language
      • 데이터를 저장하는 파일 포맷
      • 비슷한 형식으로 XML과 JSON이 존재하지만, 사람이 읽기가 더 편하다는 장점이 있다.

docker container 정의를 적어둔 yaml 생성

  • 로컬 파일로 flask 프로젝트 안에 생성해주면 된다.
version: "3.9"

services:
  flask:		 # flask를 사용함
    build:
      context: . # 이미지가 빌드될 때의 위치는 도커 컴포즈 파일이 있는 위치
    ports:
      - "5000:5000"
  • yaml을 생성한 뒤 아래의 명령어를 통해 실행한다.
    • docker-compose.yaml 파일이 있는 곳에서 실행해야 함!
$ docker-compose up

  • 브라우저로 가 잘 작동이 되는지 확인한다.
  • docker-compose도 백그라운드로 실행 가능하다.
$ docker-compose up -d   <<<  백그라운드 실행
$ docker-compose down    <<< 백그라운드 실행 시 작동 종료
  • 하지만 현재는 앱이 작동하지 않는다. 이유는 당연하게도 db가 없기 때문이다. 이제 docker-compose로 mongodb를 연결해보자.

docker-compose로 DB가 있는 application 연결

  • docker-compose는 여러 개의 application을 지원하기 위해서 만들어 둔 것이기 때문에 따로 한 파일에 정의를 한다면 기본적으로 같은 network를 사용한다.
  • docker-compose.yaml 파일 수정
version: "3.9"

services:
  flask:
    build:
      context: .
    ports:
      - "5000:5000"
  mongo:
    image: mongo:latest
    ports:
      - "27017:27017"
  • 실행해보도록 하겠다.
  • 현재 나는 mongo 이미지를 생성하는 부분에서 에러가 나 실습을 제대로 진행하지 못해 결과가 나오지 않지만, 이렇게 하면 내가 쓴 게시글이 저장되어야 한다.

docker-compose로 volume으로 유지되는 appilcation 실행

  • docker-compose에서는 bind mount, named volume을 모두 지원한다.
  • 아래와 같이 docker-compose.yaml을 수정해주면 된다.
version: "3.9"
services:
  flask:
    build:
      context: .
    volumes:
      - ./templates:/templates
    ports:
      - "5000:5000"
  mongo:
    image: mongo:latest
    volumes:
      - mongo:/data/db/
    ports:
      - "27017:27017"

volumes:
  mongo:
  • 세팅이 되었으니, 이전 것을 꺼주고 다시 띄워보도록 하자.
$ docker-compose down
$ docker-compose up -d
  • 이렇게 해서 데이터를 저장하고, 다시 끄고 킨 다음 데이터가 유지되는지 확인해보면, 데이터가 유지되고 있는 것을 볼 수 있다.

사용하지 않는 docker 리소스 정리

  • 현재 내가 가진 리소스들은 아래의 코드들을 통해 확인할 수 있다.
  • container 확인
$ docker ps -a
  • image 확인
$ docker images
  • network 확인
    • docker-compose의 경우도 네트워크가 생성되지만, docker-compose down을 하게 되면 자동으로 삭제되어 나오지 않는다.
$ docker network ls
  • volume 확인
$ docker volume ls
  • 리소스 삭제하기
$ docker rm container_id
$ docker rmi image_id
$ docker network rm network_id
$ docker volume rm volume id
$ docker system prune      <<< 다 삭제하지만, 사용하거나 사용가능성이 있으면 남김
$ docker system prune -a   <<< 얘는 진짜 다 삭제


docker image 빌드 속도 빠르게 하기

Docker layer caching 활용

  • docker는 명령어 하나가 실행될 때마다 layer가 새로 생기는 방식으로 이미지를 빌드한다.
  • 만약 자주 변경되는 부분이 dockerfile의 위쪽에 있게 된다면 layer caching을 활용하지 못한다.
  • 그러므로 자주 변경이 되는 파일들이 아래 쪽에 위치해야 한다.
  • 좋은 예
    • ADD requirements.txt .RUN pip install -r requirements.txt는 빌드를 할 때 시간이 많이 걸리는 코드들이다. 얘네가 아래에 있으면 이미지를 여러 번 생성할 때에도 어떤 것이 깔려있는지 확인을 바로 하지 못해 시간이 더 걸릴 수 있다.
    • 반면 아래 코드와 같이 위에 있다면 cached 데이터를 통해 변경이 없다면 해당 부분은 바로 넘어가 시간이 많이 단축되게 된다.
FROM python:3.8

ADD requirements.txt .

RUN pip install -r requirements.txt

ADD templates ./templates/

ADD app.py .

CMD ["python", "app.py"]

dockerignore 활용하기

  • .dockerignore 파일 추가하기
/venv
  • docker는 image를 빌드할 때의 작업 디렉토리를 build context라고 하는데, 가상환경 같은 것이 끼어들 수 있어 파일 크기가 엄청 커질 수 있다.
  • ADD . . 과 같은 command를 사용할 경우, 의도하지 않은 파일이 image가 커질 수 있다.

Docker image 축소하기 - 작은 base image 사용

  • Docker image의 크기를 줄이는 것의 장점

    • docker pull을 할 때 속도가 줄어든다.
    • 따라서, 더 빠르게 docker container를 실행할 수 있다.
  • 여태껏 사용한 base image는 python:3.8인데, 300m가 넘는다.

  • 다양한 종류의 tag가 존재하는데 대표적으로

    • alpine

      • 작고, 보안에 집중한 alpine-linux를 기반으로 만들어진 image
      • 보통 모든 이미지들중에서 가장 작음 (python:3.8-alpine기준 16.05MB)
      • python기준으로 봤을 때, pip install을 할 때 불리한 점이 있음
      • 추천하지는 않음. 이미 생성되어 있는 빌드 파일을 사용할 수 없음
    • buster, jessie, stretch

      • debian에서 만든 linux를 기반으로 만들어진 image
      • buster, jessie, stretch는 os의 codename입니다. (링크)
      • python:3.8과 python:3.8-buster는 동일합니다. (python:3.8기준 332.17MB)
      • buster가 가장 최신 버전
    • slim

      • 실행에 필요한 환경만 만들어둔 image

      • 이미지가 기본이미지에 비해서는 작음 (python:3.8 기준 41.11MB)

      • 보통 python 실행환경에서 가장 많이 쓰이는 이미지

        			FROM python:3.8-slim
        
        			ADD requirements.txt .
        
        			RUN pip install -r requirements.txt
        
        			ADD templates templates
        
        			ADD app.py .
        
        			CMD ["python", "app.py"]

Docker image 축소하기 - multistage build 활용

  • Dockerfile 한 개에 여러개의 FROM 구문을 두는 방식으로, 각 command를 실행하는 과정에서 생성된 것 중 필요한 것만 가져와서 새 이미지를 생성하게 할 수 있다.
FROM python:3.8-slim AS builder

ADD requirements.txt requirements.txt

RUN pip install -r requirements.txt

FROM python:3.8-slim-buster
COPY --from=builder /usr/local/lib/python3.8/site-packages /usr/local/lib/python3.8/site-packages

ADD templates templates

ADD app.py .

CMD ["python", "app.py"]
profile
https://github.com/nikevapormax

0개의 댓글