ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 6월 1일 TIL - docker 알아보기
    TIL(Today I Learned) 2023. 6. 1. 20:50

    ▷ 오늘의 일정

    09:10 ~ 10:10 DevOps란,,,?
    10:10 ~ 12:00 문제 풀자~
    12:00 ~ 13:00 점 심 식 사
    13:00 ~ 18:00 도커 실무 2주차
    18:00 ~ 19:00 저 녁 식 사
    19:00 ~ 20:40 하루 공부 내용 정리 및 TIL
    20:40 ~ 21:00 하루 공부 내용 공유

     

    ▷ 오늘의 배움

    📖 docker란?

    • django, db, web server 등 다양한 어플리케이션을 컨테이너 환경에서 테스트 및 배포할 수 있는 소프트웨어 플랫폼이다.
    • 💬 컨테이너란? 실행에 필요한 모든 파일을 포함하여 전체 실행(runtime) 환경에서 애플리케이션을 패키지화하고 분리하는 기술. 이를 통해 전체 기능을 유지하면서 컨테이너화된 애플리케이션을 환경(개발, 테스트, 생산 등) 간에 쉽게 이동
    • Docker를 사용하면 컨테이너를 매우 가벼운 모듈식 가상 머신처럼 다룰 수 있습니다. 또한 컨테이너를 구축, 배포, 복사하고 한 환경에서 다른 환경으로 이동하는 등 유연하게 사용할 수 있다.
      더보기
      🧐 가상 머신과 컨테이너 환경의 차이는?
      가상 머신은 os까지 설치해야 하고, docker는 os는 배제하고 필요한 서비스들만 설치해서 운영할 수 있다. 그래서 docker는 가상 머신에 비해 가볍고 빠르게 서비스를 운영할 수 있다.
    • Docker를 포함한 컨테이너 툴은 이미지 기반 배포 모델을 제공한다. 따라서 동일한 환경을 가진 컨테이너를 쉽게 생성하고 관리할 수 있다.
    • 💬 docker 이미지란? docker 컨테이너는 docker 이미지를 기반으로 생성된다. 이미지는 docker 컨테이너가 생성될 때 실행되는 실행파일, 설정 등을 가지고 있다. 예를 들어, docker postgresql 이미지는 컨테이너가 실행됐을 때 postgresql을 실행시키기 위한 패키지들이 기본적으로 설치되어 있다. ...(snapshot 같은 개념일까? 그 프로그램을 실행시키기 위한 패키지들이 이미 담겨있는 종합선물세트?)

     

    📖 docker 사용하기

    ❗️docker는 기본적으로 관리자 권한으로 동작하기 때문에 sudo 꼭 붙여주기❗️

    • docker 패키지 설치 -> 설치 후 버전 확인으로 설치 확인하기
    sudo apt install docker.io -y # -y는 설치중에 뜨는 질문들의 대답을 yes로 하겠다는 것
    # 만약 아래와 같은 에러가 발생한다면
    # E: Package 'docker.io' has no installation candidate
    # sudo apt update 명령어 실행 후 docker 패키지를 다시 설치
    • docker 컨테이너 생성하기
    sudo docker run -d -p 80:80 httpd:latest
    # run : docker 이미지를 사용해 컨테이너를 실행
    # -d : 컨테이너를 데몬(백그라운드)으로 실행
    # 80:80 : 80번 포트로 컨테이너에 접근할 수 있도록 포트포워딩 설정
    # httpd:latest : httpd의 가장 최신 이미지를 사용해 컨테이너를 생성
    • 컨테이너 확인하기
    sudo docker ps # 실행중인 컨테이너 목록 확인하기
    # CONTAINER ID : 컨테이너가 가지고 있는 고유한 id
    # IMAGE : 컨테이너가 생성될 때 사용된 이미지
    # COMMAND : 컨테이너가 생성될 때 실행되는 명령어
    # CREATED : 생성 후 경과 시간
    # STATUS : 컨테이너 상태
    # PORTS : 사용중인 포트
    
    sudo docker ps -a
    # -a : 중지된 컨테이너 목록까지 포함해서 모두 확인하기
    • 컨테이너 내부로 들어가보기
    sudo docker exec -it {container_id} /bin/bash
    # containser_id : sudo docker ps를 쳤을 때 확인되는 container_id
    # /bin/bash : 컨테이너에 접속할 때 사용되는 쉘을 입력
    # 이미지에 따라 /bin/bash라는 쉘이 존재하지 않을 수 있는데, 이 경우에는 /bin/sh를 사용해 접속

     

    📖 docker-compose란?

    • docker에서 두개 이상의 컨테이너를 간편하게 관리하기 위해 사용되는 툴이다.
    • docker-compose를 사용할 때에는 docker-compose.yml (혹은 .yaml)이라는 파일에 컨테이너에서 사용 될 이미지, 옵션 등을 작성한 후 사용하게되기 때문에 docker 명령어만 사용할 때보다 여러 컨테이너를 더 간편하고 직관적으로 컨테이너를 관리할 수 있다.

     

    📖 docker-compose 사용하기

     

    ✏️ docker-compose 설치하기

    sudo mkdir -p /usr/lib/docker/cli-plugins
    # /usr/lib/docker 경로에 cli-plugins라는 디렉토리를 생성합니다.
    # -p : 만약 상위 디렉토리가 없다면 함께 생성합니다.
    
    sudo curl -SL https://github.com/docker/compose/releases/download/v2.11.2/docker-compose-linux-x86_64 -o /usr/lib/docker/cli-plugins/docker-compose
    # github에 release 된 docker-compose 파일을 /usr/lib/docker/cli-plugins/ 경로에 다운로드 받습니다.
    # v2.11.2는 docker-compose의 버전이며, 최신 버전은 여기서 확인 가능합니다.
    
    sudo chmod +x /usr/lib/docker/cli-plugins/docker-compose
    # 다운받은 docker-compose 파일에 실행 권한을 부여해 줍니다.
    
    sudo docker compose version
    # docker-compose가 정상적으로 설치되었는지 확인합니다.
    # Docker Compose version v2.11.2 정상적으로 설치 된 경우 버전이 출력됩니다.

    ❗️docker-compose는 실행할 때 사용자가 작성한 docker-compose.yml 파일의 내용에 맞게 컨테이너를 설정하고 실행하게 된다. 그렇기 때문에 docker-compose.yml 파일이 존재하는 경로에서 docker compose 명령어를 실행시켜야 한다.❗️

     

    ✏️ docker-compose로 컨테이너 생성하기

    # docker-compose.yml 파일 만들기
    vi docker-compose.yml
    
    # docker-compose.yml 작성하기
    version: '3.8' # docker-compose.yml에 사용될 문법 버전을 정의합니다.
    
    services:
      example: # 서비스 이름을 지정합니다. 서비스 이름은 컨테이너끼리 통신할 때 사용됩니다.
        container_name: example # 컨테이너 이름을 지정합니다.
        image: 'httpd:latest' # 컨테이너를 생성할 때 사용될 이미지를 지정합니다.
        restart: always # 컨테이너가 종료됐을 때 다시 실행시켜 줍니다.
    • 컨데이너 실행시키기
    sudo docker compose up -d
    # up : docker-compose.yml 파일을 읽어 정의된 서비스들을 실행시킵니다.
    # -d : 컨테이너를 데몬(백그라운드)으로 실행시킵니다.
    • 컨테이너 중지시키기
    # docker에서 컨테이너를 중지시킬 때 stop혹은 down 옵션을 사용할 수 있다.
    
    sudo docker compose stop # 실행을 멈춘다. 재시작이 가능한 상태
    
    sudo docker compose down # 실행을 멈추고 컨테이너를 삭제한다. 재시작 불가능, 다시 실행시키려면 새로 생성해야 한다.

     

    📖 컨테이너 포트 포워딩이란?

    • db, web, ssh 등 다양한 서비스는 기본적으로 가지고 있는 포트 번호가 있다. 포트 포워딩은 외부에서 서버의 특정 포트에 접근했을 때 지정한 서비스로 전달해 주는 것을 말한다. 예를 들어 특정 컨테이너의 포트포워딩 설정을 80:8000과 같이 해줬다면, 외부에서 80 포트로 접속했을 때 해당 컨테이너의 8000번 포트로 접속하겠다는 의미이다.

    📖 컨테이너 포트 포워딩 설정하기

    ✏️  docker-compose.yml 수정

    # 기존 docker-compose.yml에서 ports 추가해주기
    version: '3.8'
    
    services:
      example:
        container_name: example
        image: 'httpd:latest'
        ports: # 포트포워딩을 설정
         - 80:80 # 외부에서 80 포트로 접속했을 때 컨테이너의 80 포트로 연결해달라
        restart: always

    ❗️ 수정후 다시 시작해주기❗️

    sudo docker compose up -d

    💬 컨테이너가 정상적으로 동작하는지 확인하기

    sudo docker compose logs
    
    # 실시간 확인하기
    sudo docker compose logs -f

     

    📖 volume 사용하기

    • docker 컨테이너는 컨테이너가 종료될 때 변경된 데이터는 모두 초기화 된다는 특징을 갖고 있다. 컨테이너에 접속한 후 문구를 추가하거나 무언가 변경된 사항이 있어도 컨테이너를 나가서 컨테이너 down 후 다시 실행시키면 수정되거나 추가된 사항들이 사라진다.
    •  volume은 컨테이너에 저장되는 데이터의 일부를 host와 공유하여 host에도 저장될 수 있게 해준다. host에 저장 된 데이터는 사용자가 직접 삭제하지 않는 이상 계속해서 유지되기 때문에 컨테이너가 종료된다 하더라도 데이터는 유실되지 않는다.

    ✏️  docker volume 종류

         💬 docker volume의 종류는 docker volume, bind mount, tmpfs mount방식이 있으며 docker volume 방식이 주로 사용된다.

    • docker volume
      •  docker에서 가장 권장하는 방식으로 docker 엔진이 관리하는 volume을 생성하는 방식이다. docker volume 방식을 사용해 생성된 volume은 host의 /var/lib/docker/volumes/ 경로에 저장된다.
      • docker volume은 주로 컨테이너간 파일을 공유하거나 중요도가 높은 파일들을 사용자가 쉽게 수정/삭제 하지 못하도록 할 때 주로 사용된다.
    • bind mount
      • docker volume 방식과 매우 유사하지만 bind mount는 docker container를 생성할 때 사용자가 지정한 경로에 데이터가 저장된다. 
      • docker 엔진의 관리를 받지 않는 영역이기 때문에 사용자가 직접 파일을 추가/수정/삭제 할 수 있다는 특징이 있다. docker 공식 문서에서는 이러한 특징으로 인해 운영에 영향을 미칠 수 있기 때문에 유사한 기능인 docker volume 방식을 사용하는 것을 권장하고 있다.
      • bind mount는 설정파일 혹은 소스코드를 프로젝트와 서버가 공유할 때 주로 사용된다.
    • tmpfs mount
      • 기존의 방식들이 ssd 혹은 hdd와 같은 저장장치에 데이터를 저장한다면, tmpfs mount 방식은 휘발성 메모리인 RAM에 데이터를 저장하기 때문에 파일로 저장하면 안 되는 민감한 정보를 다룰 때 사용한다.
      • tmpfs mount는 많은 양의 데이터를 임시로 저장할 때, 혹은 보안적으로 중요한 데이터를 저장할 때 주로 사용된다.

    ✏️  volume 사용하기(bind mount)

    # docker-compose.yml 수정
    version: '3.8'
    
    services:
      example:
        container_name: example
        image: 'httpd:latest'
        ports:
         - 80:80
        volumes: # volume을 성정해줍니다.
         - ./example_http_code/:/usr/local/apache2/htdocs/ # # 생성한 volume:컨테이너 내부의 디렉토리를 mount
        restart: always

     

    ✏️  volume 사용하기(docker volume)

    # docker-compose.yml 수정
    version: '3.8'
    
    volumes:
      example_http_code: {} # docker volume을 정의합니다.
    
    services:
      example:
        container_name: example
        image: 'httpd:latest'
        ports:
         - 80:80
        volumes: # volume을 성정해줍니다.
         - example_http_code/:/usr/local/apache2/htdocs/ # 생성한 volume:컨테이너 내부의 디렉토리를 mount
        restart: always

    ❗️ 수정하고 나서는 꼭 다시 시작해주기❗️

    sudo docker compose up -d

     

    ✏️  volume 설정 확인하기

    # volume 목록 보기
    sudo docker volume ls
    
    # volume의 이름으로 설정 정보 확인하기
    sudo docker volume inspect {volume_name}

    ✏️  volume 삭제하기

    # 사용되지 않는 docker volume들 삭제하기
    sudo docker volume prune

     

    📖 이미지 빌드하기

         💬 Dockerfile을 활용해 직접 이미지를 빌드할 수 있다.

    • Dockerfile은 docker 의 이미지를 직접 생성하기 위한 용도로 작성하는 파일로 기본이 되는 이미지를 지정한 후, 특정 패키지를 설치하거나 파일을 추가하는 등의 작업을 통해 사용자가 직접 이미지를 빌드하고 사용할 수 있다. 예를 들어 docker에서 django를 배포한다고 가정 했을 때, 기본 python 이미지를 불러온 후 django 패키지를 pip install 한 후 이미지를 생성할 수 있다.

    ✏️ Dockerfile 작성하기

    # 빌드할 때 사용할 이미지를 지정
    FROM httpd:latest
    
    # 현재 경로에 존재하는 index.html 파일을 컨테이너 내부로 복사
    COPY ./index.html /usr/local/apache2/htdocs/index.html

    🧐 Dockerfile에서 자주 사용되는 문법

    # 빌드할 때 사용할 이미지 지정
    FROM {이미지}
    
    # 지정한 명령어를 실행
    RUN {명령어}
    
    # docker 이미지에서 사용될 기본 경로를 지정
    WORKDIR {경로}
    
    # 지정한 파일을 컨테이너 내부로 복사
    COPY {복사할 파일경로(host)} {복사할 곳의 경로(컨테이너)}
    
    # 이미지에서 사용될 환경변수 지정
    ENV {옵션}

     

    ✏️ 이미지 생성하기

    # docker-compose.yml 수정
    version: '3.8'
    
    services:
      example:
        container_name: example
        build: . # 현재 경로에 있는 Dockerfile을 사용해 이미지를 생성
        ports:
         - 80:80
        restart: always

    ✏️ docker 실행하기

    sudo docker compose up -d
    
    sudo docker compose up --build -d
    # Dockerfile로 빌드된 이미지가 없을 경우, --build 옵션을 추가하지 않더라도 이미지를 빌드 하게된다.
    # 하지만 기존에 빌드된 이미지가 있다면 새로운 이미지가 아닌 기존에 빌드된 이미지를 사용한다.
    # 그렇기 때문에 Dockerfile이 수정되고 새로 빌드해야할 대는 꼭 --build 옵션을 추가해서 사용해야 한다.

     

    📖 entrypoint란?

         💬 docker 컨테이너가 생성될 때 기본적으로 실행 할 명령어를 지정해 주는 옵션이다.

    • entrypoint는 Dockerfile과 docker-compose.yml 모두 작성할 수 있다. 만약 둘 모두에 entrypoint가 작성되어 있다면 docker-compose.yml에 작성된 entrypoint가 우선시 된다.

    ✏️ entrypoint 활용하기

    # Dockerfile
    
    FROM python:3.9.15
    
    # .pyc 파일을 생성하지 않도록 설정합니다.
    ENV PYTHONDONTWRITEBYTECODE 1
    
    # 파이썬 로그가 버퍼링 없이 즉각적으로 출력하도록 설정합니다.
    ENV PYTHONUNBUFFERED 1
    
    # /app/ 디렉토리를 생성합니다.
    RUN mkdir /app/
    
    # /app/ 경로를 작업 디렉토리로 설정합니다.
    WORKDIR /app/
    
    # main.py 파일을 /app/ 경로로 복사합니다.
    COPY ./main.py /app/
    # docker-compose.yml
    
    version: '3.8' # docker-compose.yml에 사용될 문법 버전을 정의합니다.
    
    services:
      example: # 서비스 이름을 지정합니다. 서비스 이름은 컨테이너끼리 통신할 때 사용됩니다.
        container_name: example # 컨테이너 이름을 지정합니다.
        build: . # 현재 경로에 있는 Dockerfile을 사용해 이미지를 생성합니다.
        entrypoint: sh -c "python3 main.py" # 작업 디렉토리에 존재하는 main.py 파일을 실행시킵니다.
        restart: always # 컨테이너가 종료됐을 때 다시 실행시켜 줍니다.

     

    📖 컨테이너 두개 이상 생성하기

         💬 컨테이너가 1개일 때와 2개일 때 docker-compose.yml을 작성하는 방법은 크게 다르지 않다. 하지만 ports, 서비스 이름 등 중복되면 안되는 몇가지 옵션이 있기 때문에 작성할 때 중복되어 들어가지 않도록 주의해야한다.

    ✏️  docker-compose.yml 작성하기

    version: '3.8'
    
    services:
      example1:
        container_name: example1
        image: 'httpd:latest'
        ports:
          - 80:80 # 뒷포트 번호는 같아도 되지만 앞 포트번호는 절대 같으면 안된다.
        restart: always
        
      example2: # 서비스 이름이 동일하면 컨테이너가 정상적으로 생성되지 않을 수 있다.
        container_name: example2 # 컨테이너 이름이 동일하면 컨테이너 생성 시 에러가 발생한다.
        build: .
        entrypoint: sh -c "python3 main.py"
        restart: always

    ❗️ 수정하고 나서는 꼭 다시 실행❗️

    sudo docker compose up -d

    ✏️ 컨테이너 실행 순서 바꾸기

         💬 보통 docker-compose.yml에 작성한 순서대로 컨테이너가 실행된다. 하지만 경우에 따라 특정 컨테이너가 먼저 실행되어야 할 때가 있는데 그 때 depends_on을 사용해 지정해줄 수 있다. depense_on은 지정된 컨테이너가 먼저 생성될때까지 기다린 다음 해당 컨테이너를 생성시켜준다.

    # docker-compose.yml
    version: '3.8'
    
    services:
      example1:
        container_name: example1
        image: 'httpd:latest'
        ports:
          - 80:80
        depends_on:
          - example2 # 해당 컨테이너보다 먼저 실행되어야 하는 컨테이너를 지정
        restart: always
        
      example2:
        container_name: example2
        build: .
        entrypoint: sh -c "python3 main.py"
        
        restart: always

     

    댓글

Designed by Tistory.