-
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
'TIL(Today I Learned)' 카테고리의 다른 글
6월 5일 TIL - 프로젝트 S.A 작성 (2) 2023.06.05 6월 2일 TIL - 최종 프로젝트를 앞두고... (0) 2023.06.02 5월 31일 TIL - Linux 알아보기 (2) 2023.05.31 5월 30일 TIL - 이미지/동영상 처리 (1) 2023.05.30 5월 29일 TIL - 머신러닝 프로젝트 마무리 (0) 2023.05.29