TIL(22/11/15)

김규현·2022년 11월 17일
0

🌈 docker를 배우면서 느낀점
docker를 배우기 전 CLI 명령어를 익히면서 생각보다 쉽네? 라고 생각했는데 큰 오산이었다..
도커를 입문하는 순간 CLI 명령어와 함께 도커 명령어가 따로 있어 복잡해졌고 컨테이너를 다루는 것도 반복숙달이 필요할 것 같다.
밤새도록 강의를 여러번 돌려보며 복습했지만 보는 것만으로는 크게 도움이 될 것 같지 않다.
직접 코드를 작성해보면서 도커 명령어와 컨테이너를 익숙하게 다룰 수 있도록 노력해야겠다.

📝 오늘 배운 것

  • docker를 사용하여 컨테이너를 생성 및 실행
  • docker-compose를 사용하여 컨테이너 생성, 실행, 중지, 삭제
  • 컨테이너 포트 포워딩 설정
  • volume을 사용하여 데이터 보존하는 방법
  • 이미지 직접 빌드하는 방법
  • entrypoint로 컨테이너가 생성될 때 실행할 명령어 지정해주는 방법
  • 컨테이너를 두 개 이상 실행하고 실행 순서 지정하는 방법

💡 docker

django, db, web server 등 다양한 어플리케이션을 컨테이너 환경에서 테스트 및 배포할 수 있는 소프트웨어 플랫폼이다.

가상머신(Virtual machine)과 달리 앱마다 os가 존재하지 않고, 필요한 서비스만 독릭접인 환경에서 구동되기 때문에 가볍고, 빠르게 안정적인 서비스를 제공한다.

docker의 컨테이너는 docker의 이미지를 기반으로 생성되며 이미지는 컨테이너가 생성될 때 실행되는 실행파일, 설정 등을 가지고 있어 컨테이너를 생성만 해도 사용할 수 있는 환경이 만들어진다.

📌 docker 패키지 설치

# 실행하기 전 sudo apt update 명령어를 실행하여 설치가 가능한 목록을 최산화 후 docker 패키지 설치
sudo apt install docker.io

# 설치한 docker 패키지의 버전 확인
sudo docker --version

📌 docker 컨테이너

# httpd의 가장 최신 이미지를 사용해 컨테이너를 생성
# 80번 포트로 접속 시 컨테이너로 접근할 수 있도록 포트 포워딩
sudo docker run -d -p 80:80 httpd:latest

# 실행 중인 컨테이너 확인
sudo docker ps # ps뒤에 -a를 추가해주면 종료된 컨테이너도 포함

# 컨테이너 내부로 접근
# 이미지에 따라 /bin/bash 라는 쉘이 존재하지 않을 수도 있으며 그럴 땐 /bin/sh를 사용해 접속
sudo docker exec -it $container_id /bin/bash

📌 docker-compose

docker-compose는 여러개의 컨테이너를 간편하게 관리하도록 도와주는 툴이다.
docker-compose.yml 파일에 컨테이너에서 사용 될 이미지, 옵션 등을 작성하여 사용한다.

# /usr/lib/docker 경로에 cli-plugins라는 디렉토리를 생성
# -p : 만약 상위 디렉토리가 없다면 함께 생성합니다.
sudo mkdir -p /usr/lib/docker/cli-plugins

# github에 release 된 docker-compose 파일을 /usr/lib/docker/cli-plugins/ 경로에 다운로드
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

# 다운받은 docker-compose 파일에 실행 권한을 부여
sudo chmod +x /usr/lib/docker/cli-plugins/docker-compose

# docker-compose가 정상적으로 설치되었는지 확인.
# docker-compose.yml 파일이 존재하지 않는 경로에서 docker compose 명령어를 실행시킬 경우 not found error 발생
sudo docker compose version

📌 docker-compose로 컨테이너 다루기

docker-compose.yml 작성(생성할 컨테이너 설정)

version: '3.8' # docker-compose.yml에 사용될 문법 버전을 정의

services:
  example: # 서비스 이름을 지정 / 서비스 이름은 컨테이너끼리 통신할 때 사용
    container_name: example # 컨테이너 이름 지정
    image: 'httpd:latest' # 컨테이너를 생성할 때 사용될 이미지를 지정
    ports: # 포트포워딩을 설정
     - 80:80 # 외부에서 80 포트로 접속했을 때 컨테이너의 80 포트로 연결
    restart: always # 컨테이너가 종료됐을 때 다시 실행시킴

컨테이너 실행(docker-compose.yml로 설정한 컨테이너 생성)

# docker-compose.yml 파일을 읽어 정의된 서비스들을 백그라운드로 실행
sudo docker compose up -d

컨테이너 중지 및 삭제

# stop 명령어로 실행 중지한 컨테이너는 재실행하면 컨테이너 id가 동일함
sudo docker compose stop
# down 명령어로 실행 중지한 컨테이너는 삭제되어 재생성 해야함.
sudo docker compose down

컨테이너 로그 확인하기

# 컨테이너가 정상적으로 동작하는지 로그로 확인 가능하다.
# logs 뒤에 -f를 붙이면 실시간으로 로그 확인이 가능하며 ctrl+c로 exit
sudo docker compose logs

📌 volume을 사용해 데이터 보존하는 방법

docker 컨테이너는 컨테이너가 종료될 때 변경된 데이터는 모두 초기화 된다는 특징을 가지고 있다. 하지만 volume 옵션을 사용해 데이터를 보존할 수 있다.

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

docker volume 종류

  • docker volume

    docker 엔진이 관리하는 volume을 생성하는 방식이며 생성된 volume은 host의 /var/lib/docker/volumes/ 경로에 저장되고, 컨테이너간 파일을 공유하거나 중요도가 높은 파일들을 사용자가 쉽게 수정/삭제 하지 못하도록 할 때 주로 사용한다.

version: '3.8'

volumes:
  example_http_code: {} # docker volume을 정의합니다.

services:
  example:
    container_name: example 
    image:
    ports:
      - 80:80 
    volumes: 
      - example_http_code:/usr/local/apache2/htdocs/ #
    restart: always
  • bind mount
    docker volume은 /var/lib/docker/volumes/ 경로에 저장이 되지만 bind mount는 사용자가 지정한 경로에 데이터가 저장되는 차이가 있다.

    docker 엔진의 관리를 받지 않는 영역이기 때문에 사용자가 직접 파일을 추가, 삭제, 수정할 수 있으므로 서비스 운영에 영향을 미칠 수가 있어 docker volume을 사용하는 것을 권장하며 설정파일 혹은 소스코드를 프로젝트와 서버가 공유할 때 주로 사용한다.

version: '3.8'

services:
  example: 
    container_name: example 
    image: 'httpd:latest'
    ports:
      - 80:80
    volumes: 
      - ./example_http_code/:/usr/local/apache2/htdocs/ # 정의한 volume의 mount할 경로를 지정합니다.
    restart: always
  • tmpfs mount
    tmpfs mount 방식은 휘발성 메모리인 RAM에 데이터를 저장하기 때문에 파일로 저장하면 안 되는 민감한 정보를 다룰 때 사용된다.

📌 Dockerfile을 활용하여 이미지 빌드업 하는 방법

Dockerfile은 docker의 이미지를 직접 생성하기 위한 용도로 작성하는 파일이다.

Dockerfile을 작성할 때는 기본이 되는 이미지를 지정한 후, 특정 패키지를 설치하거나 파일을 추가하는 등의 작업을 통해 사용자가 직접 이미지를 빌드하고 사용할 수 있다.

사용자가 개발한 프로젝트 혹은 설정파일 등을 이미지에 포함시키거나 이미지에 기본적으로 특정 패키지를 설치하고싶을 때 등 다양한 용도로 사용된다.

#Dockerfile
FROM httpd:latest # 빌드할 때 사용할 이미지를 지정

# ex)현재 경로에 존재하는 index.html 파일을 컨테이너 내부로 복사한다.
COPY ./index.html /usr/local/apache2/htdocs/index.html
#docker-compose.yml
version: '3.8' 

services:
  example: 
    container_name: example 
    build: . # 현재 경로에 있는 Dockerfile을 사용해 이미지를 생성
    ports: 
      - 80:80 
    restart: always 

위와 같이 Dockerfile을 작성하고, docker-compose.yml 파일에 build를 추가한 후 현재 경로에서 index.html을 만들어서 컨테이너를 실행하면 Dockerfile에서 COPY 명령한대로 현 위치의 index.html이 컨테이너 내부에 있는 index.html로 복사되어 내용이 변경된다.

📌 entrypoint로 컨테이너 실행 시 동작할 명령어 설정

entrypoint는 컨테이너가 생성될 때 기본적으로 실행 할 명령어를 지정해 주는 옵션이다.
Dockerfile과 docker-compose.yml 모두 작성 가능하며 docker-compose.yml의 명령어가 우선적으로 수행된다.

version: '3.8'

services:
  example: 
    container_name: example 
    build: . 
    entrypoint: sh -c "python3 main.py" # ex)작업 디렉토리에 존재하는 main.py 파일을 실행
    restart: always 

📌 docker-compose로 두 개 이상 컨테이너 실행하는 방법

2개의 컨테이너를 띄우는 것은 1개를 띄웠을 때랑 작성방법이 크게 다르지 않지만 ports 혹은 서비스 이름 등 중복되면 안되는 몇몇 옵션이 존재하기 때문에 중복되는 값이 있는지 확인해야 한다.

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는 기본적으로 위에서 작성한 순서대로 실행되며 depends_on을 사용하여 먼저 실행될 컨테이너를 지정해줄 수 있다.

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
profile
웹개발 회고록

0개의 댓글