본문 바로가기
  • 달려가보자고~!
개발공부/Python

docker를 설치하고 활용해보기

by 도전왕 2022. 11. 11.

  • 발생한 오류는 아래에서 작성.


  • docker
    - django, db, web server 등 다양한 애플리케이션을 컨테이너 환경에서 테스트 및 배포할 수 있는 소프트웨어 플랫폼.
    - 컨테이너 환경은 가상 머신(Virtual machine)에서 사용되는 가상 환경과 비슷하지만 다른 구조를 가지고 있음.
    - 가상 머신과 컨테이너 환경의 차이


       - docker를 사용하는 이유
         ㄴ docker를 사용할 경우 다양한 어플리케이션을 쉽고 빠르게 배포할 수 있음.
         ㄴ 컨테이너는 각각 독립적인 환경에서 구동되기 때문에 안정적인 운영이 가능.
         ㄴ docker 이미지를 통해 동일한 환경을 가진 컨테이너를 쉽게 생성하고 관리할 수 있음.

       - docker 이미지
         ㄴ 가상 머신에서 윈도우를 설치할 때, 윈도우 ISO를 사용해 설치하는 것처럼 docker 컨테이너는 docker 이미지를 기반으로 생성.
         ㄴ 이미지는 docker 컨테이너가 생성될 때 실행되는 실행파일, 설정 등을 가지고 있음.
              예를 들어, docker postgresql 이미지는 컨테이너가 실행됐을 때 postgresql을 실행시키기 위한 패키지들이
              기본적으로 설치되어 있음.

 

  • 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를 사용해 접속합니다.

 

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


  • 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는 실행할 때 사용자가 작성한 docker-compose.yml 파일의 내용에 맞게 컨테이너를 설정하고 실행함.
    - 때문에 docker-compose.yml 파일이 존재하지 않는 경로에서 docker compose 명령어를 실행시킬 경우
       다음과 같은 에러가 발생할 수 있음.

 

  • 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

          - 이후 docker ps 명령어를 쳐보면 컨테이너 목록에 아무것도 보이지 않음.


          - 하지만 docker ps 명령어에 -a 옵션을 추가해 주면 중지 상태의 컨테이너를 확인할 수 있음.
          - sudo docker ps -a



         ㄴ down으로 중지시킬 때
          - sudo docker compose down


          - stop과는 다르게 컨테이너가 Removed 됐다는 로그를 확인할 수 있으며, 이와 같이 삭제된 컨테이너는
             docker ps -a 명령어로도 확인되지 않음.
          - sudo docker ps -a

 

         ㄴ 즉, stop 명령어는 컨테이너를 완전히 삭제시키는 것이 아닌 중지 상태로 만드는 것이며,
             이는 docker compose start 명령어로 다시 실행시킬 수 있음.
         ㄴ 반면 down 명령어로 컨테이너를 종료시켰을 때에는 해당 컨테이너 자체가 삭제되어 컨테이너를
             다시 실행시키기 위해서는 docker compose up 명령어로 컨테이너를 다시 생성해야 함.

 

  • 컨테이너 포트 포워딩 설정하기
    - db, web, ssh 등 다양한 서비스는 기본적으로 가지고 있는 포트 번호가 존재.
    - 포트번호 예시 
      ㄴ http : 80
      ㄴ https : 443
      ㄴ postgresql : 5432
      ㄴ django : 8000
      ㄴ ssh : 22
    - 포트 포워딩이라는 이름과 같이, 외부에서 서버의 특정 포트에 접근했을 때 지정한 서비스로 전달해 주는 것을 의미.
    - 예를 들어 특정 컨테이너의 포트 포워딩 설정을 80:8000과 같이 해줬다면, 외부에서 80 포트로 접속했을 때
       해당 컨테이너의 8000번 포트로 접속하겠다는 의미.
    ※ 웹 브라우저에서 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 restart

 

  • 컨테이너 로그 확인하기
    - docker로 앱을 배포하다 보면 배포가 정상적으로 되고 있는지 정상적으로 확인해야 하는 경우가 있습니다.
       이때, docker compose logs 명령어를 사용해 컨테이너가 정상적으로 동작하는지 확인할 수 있음.
    - sudo docker compose logs


       - 이 때, -f 옵션을 추가하면 컨테이너가 동작하며 발생하는 로그를 실시간으로 확인할 수 있음.
       - sudo docker compose logs -f
       - ※ -f 옵션을 사용한 경우 ctrl+c를 입력해 탈출할 때까지 해당 컨테이너의 로그를 실시간으로 출력.

 

  • volume을 사용하여 데이터 보존하기
    - docker 컨테이너는 컨테이너가 종료될 때 변경된 데이터는 모두 초기화된다는 특징을 가지고 있음.
    - volume을 사용하지 않으면?
      ㄴ 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라는 문구가 추가된 것을 확인할 수 있음.

 

         ㄴ exit 명령어를 사용해 컨테이너에서 나간 후
         ㄴ sudo docker compose down
              sudo docker compose up -d
         ㄴ 위 명령어를 사용해 컨테이너를 재시작시키면, 조금 전 추가한 test라는 문구가 사라지는 것을 확인할 수 있음.

       - volume이 해주는 역할
         ㄴ volume은 컨테이너에 저장되는 데이터의 일부를 host와 공유해 주는 역할.
         ㄴ host에 저장된 데이터는 사용자가 직접 삭제하지 않는 이상 계속해서 유지되며, 때문에 컨테이너가
             종료된다 하더라도 데이터는 유실되지 않음.
         ㄴ 이와 같은 특성 덕분에, volume은 컨테이너 내부에서 변경되는 내용들을 유지해야 할 때 주로 사용.
 

  • docker volume 종류
    - docker volume의 종류는 docker volume, bind mount, tmpfs mount방식이 있으며 docker volume 방식이 주로 사용.
    - 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-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 설정 확인하기
    - 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


         ㄴ 이와 같이 docker volume을 설정해 준다면 해당 경로에서 작업하는 내용은 host의 저장소에 남아
              데이터 손실 없이 작업할 수 있음.

       - 사용하지 않는 docker volume 삭제하기
         ㄴ docker compose down 혹은 docker rm 명령어로 컨테이너를 삭제해도, docker volume은 삭제되지 않고 남아있게 됨.
         ㄴ 이러한 데이터들이 지속적으로 쌓일 경우 불필요한 리소스 낭비가 생길 수 있어 주기적으로 정리해주는 습관을 들이는 게 좋음.
         ㄴ 아래 명령어를 활용해 사용되지 않는 docker volume들을 일괄적으로 삭제할 수 있음.
         ㄴ sudo docker volume prune

 

  • 이미지 직접 빌드하기
    - Dockerfile
      ㄴ docker의 이미지를 직접 생성하기 위한 용도로 작성하는 파일.
      ㄴ Dockerfile을 작성할 때는 기본이 되는 이미지를 지정한 후, 특정 패키지를 설치하거나
           파일을 추가하는 등의 작업을 통해 사용자가 직접 이미지를 빌드하고 사용할 수 있음.
    - Dockerfile은 언제 사용?
      ㄴ 사용자가 개발한 프로젝트 혹은 설정 파일 등을 이미지에 포함시키거나 이미지에 기본적으로
           특정 패키지를 설치하고 싶을 때 등 다양한 용도로 사용.
      ㄴ 예를 들어 docker에서 django를 배포한다고 가정했을 때, 기본 python 이미지를 불러온 후
          django 패키지를 pip install 한 후 이미지를 생성하게 됨.
      ㄴ 원하는 html 파일을 컨테이너 이미지에 집어넣는 방법은 밑에서.

    - Dockfile 작성하기
# 빌드할 때 사용할 이미지를 지정해줍니다.
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 옵션을 추가해서 사용해야 함.

 


  • 오류 발생


       - 오류코드를 봤을  때 lates에서 오류가 발생한 것 같아서 다시 하나씩 되돌아가면서 확인.


       - 오류 수정 후 정상 작동되는 모습.

댓글