Docker 실습

김혁준·2023년 6월 1일
0

05. 파일과 디렉토리 다뤄보기

🔑 파일과 디렉토리를 다룰 때 사용되는 명령어들을 알아보겠습니다.
  • 상대경로와 절대경로란?
    • 리눅스에서는 디렉토리를 이동하거나 파일을 지정할 때, 상대경로 혹은 절대경로를 사용하게 됩니다.
    • 절대경로를 사용할 경우 현재 위치와 관계 없이 절대적인 경로를 입력하여 사용합니다.
      • ex) cd /home/user/example/dir/
    • 상대경로는 내 현재 위치를 기준으로 경로를 지정하게 됩니다.
      • ex) cd ./dir/ 현재 위치에 존재하는 dir 디렉토리로 이동
      • ex) cd ../ 현재 위치를 기준으로 상위 디렉토리로 이동
  • wild card(*)란?
    • 특정 파일이나 디렉토리를 지정할 때, 이름을 지정해 줘야 하는 경우가 있습니다. 이 때 wild card(*)를 사용하면 원하는 파일을 더 빠르게 탐색하거나 실행시킬 수 있습니다.

      ls -l ./*.txt # .txt로 끝나는 모든 파일 목록 출력하기
  • 디렉토리를 생성하고 이동해보기
    • mkdir / 디렉토리 생성하기
      mkdir ./test # 현재 경로에 test 디렉토리 생성하기
      mkdir ./test/test2 # test 디렉토리 안에 test2 디렉토리 생성하기
      mkdir /home/ubuntu/test3 # /home/user 경로에 test3 디렉토리 생성하기
    • pwd / 현재 경로 확인하기
      pwd # 현재 경로 확인
    • cd / 경로 이동하기
      cd ./test # 현재 경로의 test 디렉토리로 이동
      cd ./test/test2 # test 디렉토리 안에 test2 디렉토리로 이동
      cd ../test3 # 상위 디렉토리의 test3 디렉토리로 이동
      cd /home/user/test4 # /home/user/test4 디렉토리로 이동
    • ls / 파일 목록 보기
      ls # 현재 위치에 파일 목록 보기
      ls ./test # test 경로에 파일 목록 보기
      ls -l # 현재 위치에 파일 목록을 더 자세히 보기
      ls -a # 현재 위치에 숨겨짐 파일을 포함해서 보기
      ls -al # 현재 위치에 숨겨진 파일을 포함해서 목록을 더 자세히 보기
      
      # 이외에도 다양한 옵션들이 존재하며, ls --help 명령어로 확인 가능합니다.
  • 파일을 생성하고 삭제해보기
    • touch / 파일 생성하기
      touch test.txt # test.txt 파일 생성하기
    • cp / 파일 복사하기
      cp test.txt test_copy.txt # test.txt 파일을 test_copy.txt라는 이름으로 복사하기
      cp -r directory directory_copy # 폴더를 복사할 경우 -r 옵션 사용
    • mv / 파일 이동하기
      mv ./directory1/test.txt ./ # directory1 경로의 test.txt 파일을 현재 경로로 이동
      
      # mv는 파일의 이름을 변경할 때도 사용됩니다.
      mv test.txt text2.txt # test.txt 파일의 이름을 test2.txt로 변경
    • rm / 파일 삭제하기
      rm test.txt # test.txt 파일 삭제
      rm -r directory # 디렉토리를 삭제하기 위해서는 -r 옵션을 붙여줘야 합니다.
  • 리눅스에서 숨김 파일을 취급하는 방법
    • 리눅스에서는 파일 혹은 디렉토리 이름이 .으로 시작할 경우 숨김 파일로 취급됩니다.
      • ex) touch test : test라는 이름의 파일 생성
        touch .test : .test라는 이름의 숨김 파일 생성
    • 숨김 파일은 ls 명령어의 -a 옵션으로 확인할 수 있습니다.

06. 파일 읽고 쓰기

🔑 파일을 원하는대로 수정하고, 내용을 추가하는 방법을 알아보겠습니다.
  • vi 편집기 활용해보기
    • vi 편집기 mode 종류
      • insert mode : 텍스트를 입력 할 수 있는 상태
      • commend mode : 특수한 commend를 입력 할 수 있는 상태
    • insert mode 진입 방법
      • i : 현재 위치에서 insert mode 진입
      • a : 현재 위치에서 커서를 한 칸 앞으로 이동 후 insert mode 진입
      • A : 현재 위치에서 가장 마지막 텍스트로 이동 한 후 insert mode 진입
      • o : 현재 위치에서 한칸 개행 한 후 insert mode 진입
      • esc : insert mode 나가기
    • commend mode 명령어
      • u : undo (ctrl + z와 동일)
      • ctrl + r : redo
      • gg : 커서를 가장 처음으로 옮김
      • G : 커서를 마지막 줄로 옮김
      • dd : line 잘라내기
      • yy : line 복사
      • p : 붙여넣기
      • :se nu : 라인 줄 표시
      • :숫자 : 숫자 라인으로 이동 (ex - :10 : 10번째 라인으로 이동)
      • 특정 단어 검색
        • /word : word라는 단어를 검색
        • /\cword : 대소문자를 구분하지 않고 word라는 단어를 검색 (ex - /\cword)
        • n : 다음 단어 검색
        • N : 이전 단어 검색
      • 수정한 문서 저장 :w : 저장 :q : 나가기 :wq : 저장 하고 나가기 :q! : 수정내역이 있어도 저장하지 않고 강제로 나가기
  • 파일에 있는 내용 확인하기
    • cat / 파일 내용 보기
      cat test.txt # test.txt 파일의 내용 보기
    • head / 파일의 시작 부분 보기
      head test.txt # test.txt 파일의 첫 10줄 내용 보기
      head -50 test.txt # text.txt 파일의 첫 50줄 내용 보기
    • tail / 파일의 끝 부분 보기

08. 자주 사용되는 명령어

🔑 Linux에서 자주 사용되는 명령어들을 알아보겠습니다
  • tab / 자동완성 시키기
    • 키보드의 tab 버튼을 활용해 파일, 디렉토리 이름 등을 자동완성 시킬 수 있습니다.
  • grep / 특정 문자열이 포함 된 파일 찾기
    grep word ./* # 현재 경로의 모든 파일을 대상으로 word라는 단어가 포함된 파일 찾기
    grep word ./* -r # -r 옵션을 붙이면 디렉토리 내부까지 모두 탐색합니다.
  • find / 특정 조건의 파일 찾기
    find / -name "*.txt" # 최상위 경로에서 .txt로 끝나는 파일 혹은 디렉토리 검색
    find ./ -type d # 현재 경로에서 모든 디렉토리 검색
    find ./ -type f -name "*.txt" # 현재 경로에서 .txt로 끝나는 파일 검색
  • history / 명령어 기록 출력하기
    history # 지금까지 사용한 명령어 출력
  • htop / 리소스 사용량 확인하기
    htop # 현재 사용중인 리소스 확인하기
  • df / 남은 디스크 용량 확인하기
    df -h # 디스크 여유 공간 확인하기
  • du / 특정 파일 혹은 폴더가 사용중인 디스크 용량 확인하기

03. 기초 실습

🔑 docker를 사용해 컨테이너를 생성하고 활용하는 방법을 알아보겠습니다.
  • docker 패키지 설치
    sudo apt install docker.io -y
    # 만약 아래와 같은 에러가 발생한다면
    # E: Package 'docker.io' has no installation candidate
    # sudo apt update 명령어 실행 후 docker 패키지를 다시 설치해주세요
  • docker 설치 확인
    sudo docker --version # 도커 버전이 출력되는지 확인합니다.
    # Docker version 20.10.12, build 20.10.12-0ubuntu2~20.04.1 - 정상
    # command not found: docker 와 같은 문구가 출력될 경우 docker가 설치되었는지 확인해야 합니다.
  • docker 컨테이너 생성하기
    sudo docker run -d -p 80:80 httpd:latest
    # run : 이미지를 사용해 컨테이너를 실행시킵니다.
    # -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 images
    # REPOSITORY : 이미지 저장소 이름
    # TAG : 이미지 버전
    # IMAGE ID : 이미지의 고유한 id
    # CREATED : 이미지 생성일(마지막 업데이트 일)
    # SIZE : 이미지 용량
  • 컨테이너 내부로 들어가보기
    sudo docker exec -it $container_id /bin/bash

    $containser_id : sudo docker ps를 쳤을 때 확인되는 container_id를 입력합니다.

    /bin/bash : 컨테이너에 접속할 때 사용되는 쉘을 입력합니다.

    이미지에 따라 /bin/bash라는 쉘이 존재하지 않을 수 있는데, 이 경우에는 /bin/sh를 사용해 접속합니다.

04. docker-compose란?

🔑 docker 컨테이너를 더 편하게 관리하게 해주는 docker-compose에 대해 알아보겠습니다.
  • docker-compose란? 💡 docker-compose는 docker 2개 이상의 컨테이너를 더욱 간편하게 관리하기 위해 사용되는 툴입니다. docker-compose를 사용할 때에는 docker-compose.yml (혹은 .yaml)이라는 파일에 컨테이너에서 사용 될 이미지, 옵션 등을 작성한 후 사용하게 됩니다. 이를 통해 docker 명령어만 사용할 때보다 여러 컨테이너를 더 간편하고 직관적으로 컨테이너를 관리할 수 있습니다. - docker-compose를 사용할 때 주의해야 할 점 💡 docker-compose는 실행할 때 사용자가 작성한 docker-compose.yml 파일의 내용에 맞게 컨테이너를 설정하고 실행하게 됩니다. 때문에 docker-compose.yml 파일이 존재하지 않는 경로에서 docker compose 명령어를 실행시킬 경우 다음과 같은 에러가 발생할 수 있습니다.

05. docker-compose로 컨테이너 생성하기

🔑 docker 명령어가 아닌 docker-compose를 활용해 컨테이너를 생성하는 방법을 알아보겠습니다.
  • docker 컨테이너 삭제하기
    sudo docker ps -a # docker에 존재하는 컨테이너 목록을 확인합니다.
    # CONTAINER ID   IMAGE          COMMAND              CREATED        STATUS        PORTS                               NAMES
    # 54445308314d   httpd:latest   "httpd-foreground"   23 hours ago   Up 23 hours   0.0.0.0:80->80/tcp, :::80->80/tcp   sweet_engelbart
    
    sudo docker rm -f $container_id # 컨테이너의 실행중 여부와 관계 없이 강제로 삭제합니다.
  • docker-compose.yml 작성해보기
    version: '3.8' # docker-compose.yml에 사용될 문법 버전을 정의합니다.
    
    services:
      example: # 서비스 이름을 지정합니다. 서비스 이름은 컨테이너끼리 통신할 때 사용됩니다.
        container_name: example # 컨테이너 이름을 지정합니다.
        image: 'httpd:latest' # 컨테이너를 생성할 때 사용될 이미지를 지정합니다.
        restart: always # 컨테이너가 종료됐을 때 다시 실행시켜 줍니다.
  • 컨테이너 실행시켜보기
    # docker compose 명령어는 docker-compose.yml 파일이 존재하는 자리에서 실행해야 합니다.
    
    sudo docker compose up -d
    # up : docker-compose.yml 파일을 읽어 정의된 서비스들을 실행시킵니다.
    # -d : 컨테이너를 데몬(백그라운드)으로 실행시킵니다.
  • 컨테이너 중지시키기 💡 docker에서 컨테이너를 중지시킬 때 stop혹은 down 옵션을 사용할 수 있습니다. 두 옵션 모두 컨테이너를 중지할 때 사용되기 때문에 비슷해 보일 수 있지만 다른 용도로 사용되며, 사용 시 주의가 필요합니다. 우선 컨테이너를 stop 명령어를 사용해 중지시켜 보겠습니다. sudo docker compose stop ![Untitled](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/de5d5216-3fa4-4bd1-bc5e-d7f4847f9fb9/Untitled.png) 이후 docker ps 명령어를 쳐보면 컨테이너 목록에 아무것도 보여지지 않습니다. ![Untitled](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/827cd3af-0977-437d-9d7e-ddff0ef0d995/Untitled.png) 하지만 docker ps 명령어에 -a 옵션을 추가해 주면 중지 상태의 컨테이너를 확인할 수 있습니다. sudo docker ps -a ![Untitled](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/ff766550-0232-46e4-9af9-f9d1bd921122/Untitled.png) 이번에는 docker compose down 명령어를 사용해 컨테이너를 중지시켜 보겠습니다. sudo docker compose down ![Untitled](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/adb80f9d-2429-4494-9e75-b7396074656b/Untitled.png) stop과는 다르게 컨테이너가 Removed 됐다는 로그를 확인할 수 있으며, 이와 같이 삭제 된 컨테이너는 docker ps -a 명령어로도 확인되지 않습니다. sudo docker ps -a ![Untitled](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/e26b9c54-ca1c-4368-95ed-a1c94917f3a6/Untitled.png) 즉, stop 명령어는 컨테이너를 완전히 삭제시키는 것이 아닌 중지 상태로 만드는 것이며, 이는 docker compose start 명령어로 다시 실행시킬 수 있습니다. 반면 down 명령어로 컨테이너를 종료시켰을 때에는 해당 컨테이너 자체가 삭제되어 컨테이너를 다시 실행시키기 위해서는 docker compose up 명령어로 컨테이너를 다시 생성해야 합니다. ## 06. 컨테이너 포트 포워딩 설정하기
🔑 직접 생성한 컨테이너를 외부에서 접근할 수 있도록 포트포워딩 설정을 해주는 방법에 대해 알아보겠습니다.
  • 포트 포워딩(port forwarding)이란? 💡 db, web, ssh 등 다양한 서비스는 기본적으로 가지고 있는 포트 번호가 존재합니다. - 포트 번호 예시 - http : 80 - https : 443 - postgresql : 5432 - django : 8000 - ssh : 22 포트 포워딩이라는 이름과 같이, 외부에서 서버의 특정 포트에 접근했을 때 지정한 서비스로 전달해 주는 것을 의미합니다. 예를 들어 특정 컨테이너의 포트포워딩 설정을 80:8000과 같이 해줬다면, 외부에서 80 포트로 접속했을 때 해당 컨테이너의 8000번 포트로 접속하겠다는 의미입니다. ![Untitled](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/b1a78f2e-efec-4a3a-a0c7-4f40454f6b83/Untitled.png) ※ 웹 브라우저에서 naver.com과 같은 사이트에 접근할 때 https://www.naver.com과 같은 주소로 접근하게 되는데, http 프로토콜은 기본적으로 80 포트를 사용하고 https 프로토콜은 443 포트를 사용하게 되며 이는 웹 브라우저에 주소를 입력할 때 생략됩니다.
  • docker-compose.yml
    version: '3.8' # docker-compose.yml에 사용될 문법 버전을 정의합니다.
    
    services:
      example: # 서비스 이름을 지정합니다. 서비스 이름은 컨테이너끼리 통신할 때 사용됩니다.
        container_name: example # 컨테이너 이름을 지정합니다.
        image: 'httpd:latest' # 컨테이너를 생성할 때 사용될 이미지를 지정합니다.
        ports: # 포트포워딩을 설정해줍니다.
         - 80:80 # 외부에서 80 포트로 접속했을 때 컨테이너의 80 포트로 연결해줍니다.
        restart: always # 컨테이너가 종료됐을 때 다시 실행시켜 줍니다.
  • 컨테이너 실행시켜보기
    sudo docker compose up -d
  • 컨테이너 로그 확인하기 💡 docker로 앱을 배포하다 보면 배포가 정상적으로 되고 있는지 정상적으로 확인해야 하는 경우가 있습니다. 이 때, docker compose logs 명령어를 사용해 컨테이너가 정상적으로 동작하는지 확인할 수 있습니다. sudo docker compose logs ![Untitled](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/a16b053c-134c-47a4-b5a7-307160ab1c47/Untitled.png) 이 때, -f 옵션을 추가하면 컨테이너가 동작하며 발생하는 로그를 실시간으로 확인할 수 있습니다. sudo docker compose logs -f ![Untitled](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/7f3dad29-aefd-4fe8-9550-ab2d538a9c41/Untitled.png) ※ -f 옵션을 사용한 경우 ctrl+c를 입력해 탈출할 때까지 해당 컨테이너의 로그를 실시간으로 출력합니다.

07. volume을 사용해 데이터 보존하기

🔑 docker 컨테이너는 컨테이너가 종료될 때 변경된 데이터는 모두 초기화 된다는 특징을 가지고 있습니다. volume 옵션을 사용해 데이터를 보존시키는 방법을 알아보겠습니다.
  • volume을 사용하지 않으면 어떻게 될까? /icons/folder_yellow.svg docker container 내부로 접근해서 테스트용으로 띄운 컨테이너에 접속했을 때 보여지는 문구를 변경해 보도록 하겠습니다. 우선, 컨테이너에 접속합니다. sudo docker exec -it example /bin/bash ※ docker container에 접속할 때 container id 대신 container name을 사용할 수도 있습니다. example이라는 이름은 docker-compose.yml에서 container_name으로 지정한 명칭입니다. 이후 test라는 문구를 추가해보겠습니다. echo "test" >> /usr/local/apache2/htdocs/index.html 컨테이너 안에서 해당 명령어를 실행한 후 웹 브라우저에서 다시 접속해보면 test라는 문구가 추가된 것을 확인할 수 있습니다. ![Untitled](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/2ab0de68-96e7-4ab7-9040-0fb9ead62c42/Untitled.png) exit 명령어를 사용해 컨테이너에서 나간 후 sudo docker compose down sudo docker compose up -d 위 명령어를 사용해 컨테이너를 재시작 시키면, 조금 전 추가한 test라는 문구가 사라지는 것을 확인할 수 있습니다.
  • volume이 해주는 역할 /icons/folder_yellow.svg volume은 컨테이너에 저장되는 데이터의 일부를 host와 공유해 주는 역할을 합니다. host에 저장 된 데이터는 사용자가 직접 삭제하지 않는 이상 계속해서 유지되며, 때문에 컨테이너가 종료된다 하더라도 데이터는 유실되지 않습니다. 이와 같은 특성 덕분에, volume은 컨테이너 내부에서 변경되는 내용들을 유지해야 할 때 주로 사용됩니다.
  • docker volume 종류 /icons/folder_yellow.svg docker volume의 종류는 docker volume, bind mount, tmpfs mount방식이 있으며 docker volume 방식이 주로 사용됩니다. ![Untitled](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/549ddcb9-8495-4e44-809e-4d1cfceb079f/Untitled.png) ### docker volume - docker 엔진이 관리하는 volume을 생성하는 방식입니다. - docker volume 방식을 사용해 생성된 volume은 host의 /var/lib/docker/volumes/ 경로에 저장됩니다. - docker에서 가장 권장하는 방식입니다. ### bind mount - docker volume 방식과 매우 유사합니다. - docker container를 생성할 때 사용자가 지정한 경로에 데이터가 저장됩니다. - docker 엔진의 관리를 받지 않는 영역이기 때문에 사용자가 직접 파일을 추가/수정/삭제 할 수 있다는 특징이 있습니다. docker 공식 문서에서는 이러한 특징으로 인해 운영에 영향을 미칠 수 있기 때문에 유사한 기능인 docker volume 방식을 사용하는 것을 권장하고 있습니다. ### tmpfs mount - 기존의 방식들이 ssd 혹은 hdd와 같은 저장장치에 데이터를 저장한다면, tmpfs mount 방식은 휘발성 메모리인 RAM에 데이터를 저장합니다. - 파일로 저장하면 안 되는 민감한 정보를 다룰 때 사용됩니다. ### 언제 어떤 방식의 volume을 사용해야 할까? - 각각의 방식들은 장/단점이 있기 때문에 필요에 맞게 사용해야 합니다. - **docker volume**은 주로 컨테이너간 파일을 공유하거나 중요도가 높은 파일들을 사용자가 쉽게 수정/삭제 하지 못하도록 할 때 주로 사용합니다. - **bind mount**는 설정파일 혹은 소스코드를 프로젝트와 서버가 공유할 때 주로 사용됩니다. - ******************************tmpfs mount******************************는 많은 양의 데이터를 임시로 저장할 때, 혹은 보안적으로 중요한 데이터를 저장할 때 주로 사용됩니다. - 자세한 내용은 [docker 공식 문서](https://docs.docker.com/storage/#good-use-cases-for-volumes)에서 확인할 수 있습니다.
  • docker-compose.yml (bind mount)
    version: '3.8' # docker-compose.yml에 사용될 문법 버전을 정의합니다.
    
    services:
      example: # 서비스 이름을 지정합니다. 서비스 이름은 컨테이너끼리 통신할 때 사용됩니다.
        container_name: example # 컨테이너 이름을 지정합니다.
        image: 'httpd:latest' # 컨테이너를 생성할 때 사용될 이미지를 지정합니다.
        ports: # 포트포워딩을 설정해줍니다.
          - 80:80 # 외부에서 80 포트로 접속했을 때 컨테이너의 80 포트로 연결해줍니다.
        volumes: # volume을 성정해줍니다.
          - ./example_http_code/:/usr/local/apache2/htdocs/ # 정의한 volume의 mount할 경로를 지정합니다.
        restart: always # 컨테이너가 종료됐을 때 다시 실행시켜 줍니다.
  • docker-compose.yml (docker volume)
    version: '3.8' # docker-compose.yml에 사용될 문법 버전을 정의합니다.
    
    volumes:
      example_http_code: {} # docker volume을 정의합니다.
    
    services:
      example: # 서비스 이름을 지정합니다. 서비스 이름은 컨테이너끼리 통신할 때 사용됩니다.
        container_name: example # 컨테이너 이름을 지정합니다.
        image: 'httpd:latest' # 컨테이너를 생성할 때 사용될 이미지를 지정합니다.
        ports: # 포트포워딩을 설정해줍니다.
          - 80:80 # 외부에서 80 포트로 접속했을 때 컨테이너의 80 포트로 연결해줍니다.
        volumes: # volume을 성정해줍니다.
          - example_http_code:/usr/local/apache2/htdocs/ # 정의한 volume의 mount할 경로를 지정합니다.
        restart: always # 컨테이너가 종료됐을 때 다시 실행시켜 줍니다.
  • volume 설정 확인하기 /icons/cd_yellow.svg docker-compose.yml에서 volume을 정의하고 실행했다면, docker volume 명령어를 사용해 volume의 목록과 설정을 확인할 수 있습니다. volume 목록 보기 sudo docker volume ls volume의 이름으로 설정 정보 확인하기 sudo docker volume inspect $volume_name ex) sudo docker volume inspect ubuntu_example_http_code ![Untitled](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/19511237-04dd-4945-b48e-b5d935b299b2/Untitled.png) 이와 같이 docker volume을 설정해 준다면 해당 경로에서 작업하는 내용은 host의 저장소에 남아 데이터 손실 없이 작업할 수 있습니다.
  • 사용하지 않는 docker volume 삭제하기 /icons/cd_yellow.svg docker compose down 혹은 docker rm 명령어로 컨테이너를 삭제해도, docker volume은 삭제되지 않고 남아있게 됩니다. 이러한 데이터들이 지속적으로 쌓일 경우 불필요한 리소스 낭비가 생길 수 있어 주기적으로 정리해주는 습관을 들이는게 좋습니다. 아래 명령어를 활용해 사용되지 않는 docker volume들을 일괄적으로 삭제할 수 있습니다. sudo docker volume prune

08. 이미지 직접 빌드하기

🔑 Dockerfile을 활용해 직접 이미지를 빌드하는 방법을 알아보겠습니다.
  • Dockerfile 이란? 💡 docker 의 이미지를 직접 생성하기 위한 용도로 작성하는 파일입니다. Dockerfile을 작성할 때는 기본이 되는 이미지를 지정한 후, 특정 패키지를 설치하거나 파일을 추가하는 등의 작업을 통해 사용자가 직접 이미지를 빌드하고 사용할 수 있습니다.
  • Dockerfile은 언제 사용되나요? 💡 사용자가 개발한 프로젝트 혹은 설정파일 등을 이미지에 포함시키거나 이미지에 기본적으로 특정 패키지를 설치하고싶을 때 등 다양한 용도로 사용됩니다. 예를 들어 docker에서 django를 배포한다고 가정 했을 때, 기본 python 이미지를 불러온 후 django 패키지를 pip install 한 후 이미지를 생성하게 됩니다. 이번 예제에서는 원하는 html 파일을 컨테이너 이미지에 집어넣는 방법을 알아보도록 하겠습니다.
  • Dockerfile 작성하기
    # 빌드할 때 사용할 이미지를 지정해줍니다.
    FROM httpd:latest
    
    # 현재 경로에 존재하는 index.html 파일을 컨테이너 내부로 복사합니다.
    COPY ./index.html /usr/local/apache2/htdocs/index.html
  • docker-compose.yml
    version: '3.8' # docker-compose.yml에 사용될 문법 버전을 정의합니다.
    
    services:
      example: # 서비스 이름을 지정합니다. 서비스 이름은 컨테이너끼리 통신할 때 사용됩니다.
        container_name: example # 컨테이너 이름을 지정합니다.
        build: . # 현재 경로에 있는 Dockerfile을 사용해 이미지를 생성합니다.
        ports: # 포트포워딩을 설정해줍니다.
          - 80:80 # 외부에서 80 포트로 접속했을 때 컨테이너의 80 포트로 연결해줍니다.
        restart: always # 컨테이너가 종료됐을 때 다시 실행시켜 줍니다.
  • index.html을 직접 만들고 docker 실행해보기 💡 index.html을 직접 만들고, 직접 만든 파일이 포함된 이미지를 빌드해 보겠습니다. Dockerfile을 작성할 때 ./index.html 파일을 복사하도록 지정해 줬기 때문에, 동일한 이름으로 해당 파일을 생성하고 편집합니다. vi index.html # 내용 추가 sudo docker compose up --build -d ※ Dockerfile로 빌드된 이미지가 없을 경우, --build 옵션을 추가하지 않더라도 이미지를 빌드 하게 됩니다. 하지만, 기존에 빌드된 이미지가 있을 경우에는 새로 빌드하지 않고 기존에 빌드 된 이미지를 사용합니다. 때문에, Dockerfile을 수정하고 이미지를 새로 빌드해야 할 때는 --build 옵션을 추가해서 사용해야 합니다.

09. entrypoint 활용해보기

🔑 entrypoint를 활용해 컨테이너가 생성될 때 실행할 명령어를 지정하는 방법에 대해 알아보겠습니다.
  • entrypoint란? 💡 docker 컨테이너가 생성될 때 기본적으로 실행 할 명령어를 지정해 주는 옵션입니다. 예를 들어, 데이터베이스를 실행시키기 위해 만든 이미지는, 컨테이너가 생성될 때 데이터베이스 서비스를 실행시켜야 합니다. 이 때 사용되는 옵션이 entrypoint입니다. entrypoint는 Dockerfile과 docker-compose.yml 모두 작성할 수 있습니다. 만약 Dockerfile, docker-compose.yml 모두 entrypoint가 작성되어 있다면 Dockerfile의 entrypoint는 무시되고 docker-compose.yml의 명령어가 우선적으로 수행됩니다.
  • 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 # 컨테이너가 종료됐을 때 다시 실행시켜 줍니다.
  • 임의의 파이썬 파일을 만들어서 실행해보기 💡 vi 편집기를 사용해 실행시킬 python 파일을 만들고, entrypoint를 사용해 컨테이너에서 실행시켜 보겠습니다. vi 편집기로 main.py 파일을 열고 수정해보겠습니다. vi main.py ```python from time import sleep for i in range(100): print(f"print number : {i}") sleep(1) ``` 코드 작성 후 esc → :wq 를 입력해 파일을 저장하고 컨테이너를 생성합니다. sudo docker compose up --build -d ![Untitled](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/24d048b9-3572-45df-8f46-2c7585251b3c/Untitled.png) 이후 logs 명령어를 사용해 작성 한 print문이 정상적으로 출력되는지 확인합니다. sudo docker compose logs -f ![Untitled](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/70cb0222-af06-4f87-8bbf-7932e7de3b2b/Untitled.png)

10. 컨테이너를 두 개 이상 띄워보기

🔑 docker-compose.yml에서 두 개 이상의 컨테이너를 정의하고 생성하는 방법을 알아보겠습니다.
  • 주의사항 💡 컨테이너가 1개일 때와 2개 이상일 때 docker-compose.yml을 작성하는 방법은 기존과 크게 다르지 않습니다. 다만, ports 혹은 서비스 이름 등 중복되면 안되는 몇몇 옵션이 존재하기 때문에 중복되는 값이 있는지 확인해야 하며 만약 특정 값이 중복되어 들어간다면 컨테이너가 정상적으로 생성되지 않거나 생성하는 과정에서 에러가 발생할 수 이 아래 예제에서는 이전에 강의에서 생성했던 Dockerfile을 사용합니다.
  • 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
  • 컨테이너 생성해 보기 💡 docker-compose.yml 작성 이후 컨테이너를 실행시켜 보면 두 개의 컨테이너가 실행되는 것을 확인할 수 있습니다. sudo docker compose up ![Untitled](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/7417e771-16c8-4f2b-95fe-c29eaaa9d7e2/Untitled.png)
  • depends_on을 사용해 컨테이너 실행 순서 바꿔보기 💡 docker-compose.yml에 두 개 이상의 컨테이너를 생성하도록 작성한 경우, 기본적으로는 작성 한 순서대로 컨테이너가 실행됩니다. 하지만 경우에 따라 특정 컨테이너가 먼저 실행되어야 하는 경우가 있습니다. 예를 들어, django 컨테이너와 데이터베이스 컨테이너를 같이 띄우는 경우에는 데이터베이스 컨테이너가 먼저 생성되어야 django 컨테이너에서 데이터베이스에 연결할 수 있습니다. 이 때, depends_on 옵션을 사용해 컨테이너간 실행 순서를 컨트롤 할 수 있습니다. docker-compose.yml ```yaml 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 ``` 이후 컨테이너가 생성되는 로그를 보면 실행 순서가 바뀐 것을 확인할 수 있습니다. ※depends_on을 설정하지 않은 경우 ![Untitled](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/7417e771-16c8-4f2b-95fe-c29eaaa9d7e2/Untitled.png) ※depends_on을 설정해준 경우

0개의 댓글

관련 채용 정보