'll Hacker

[WIL] 7주차, 컨테이너 환경설정 본문

Dev/GDSC

[WIL] 7주차, 컨테이너 환경설정

씨이오가 되자 2024. 12. 21. 23:39
Contents
728x90

모놀리식 아키텍처 vs 마이크로 서비스 아키텍처

모놀리식 아키텍처

= 하나의 큰 목적이 있는 서비스 또는 애플리케이션에 어떤 기능이 통합되어 있는 구조

장점 : 초기 단계에서 설계하기 용이함, 단순한 구현과정, 코드 관리 간편.

단점 : 서비스가 성장할수록 서비스 간의 관계가 매우 복잡 

 

마이크로 서비스 아키텍처

= 하나의 큰 목적이 있는 서비스 또는 애플리케이션에 각 기능이 독립된 서비스로 분리되어 실행되며, API Gateway 등을 통해 서로 통신.

장점 : 서비스 재사용, 서비스 변경 시 전체 영향 안 미침, 사용자의 요구사항에 따라 가용성을 즉각적으로 확보해야 하는 IaaS 환경에 적합함 

IaaS
클라우드 서비스의 한 종류로, 물리적 하드웨어 대신 가상화된 인프라를 클라우드에서 제공

단점 : 관리가 복잡하며, 서비스 간 통신 비용이 증가함

컨테이너

컨테이너란?

소프트웨어의 표준 단위로, 코드와 모든 종속성을 하나로 묶어 응용 프로그램이 다양한 컴퓨팅 환경에서 빠르고 안정적으로 실행될 수 있도록 함.

애플리케이션과 애플리케이션이 실행되기 위한 모든 것(코드, 라이브러리, 환경설정 파일 등)을 하나의 "상자(=컨테이너) 안에 담아두는 것과 같음. 이 상자를 어디로 옮기든, 상자 안에 있는 애플리케이션은 똑같이 실행될 수 있음 

 

"컨테이너화" 기본 운영체제 커널을 동일한 시스템의 다른 컨테이너와 공유하는 격리된 환경에서 애플리케이션을 실행하는 방법이다. 종속성, 필요한 라이브러리 및 바이너리와 함꼐 애플리케이션을 컨테이너 이미지라고 하는 독립된 패키지로 패키지화하여 여러 컴퓨팅 환경에 쉽게 배포 할 수 있음 

 

[비유: 컨테이너는 배달 음식과 같다]

  • 컨테이너 = 음식 배달 상자
    음식 배달 상자 안에는 필요한 모든 것(음식, 포크, 소스)이 들어 있음.
    상자를 어디로 가져가든 상자를 열면 동일한 음식을 먹을 수 있음.
  • 도커 엔진 = 배달 서비스
    배달 음식이 도착하려면 배달원이 필요함.
    도커 엔진은 컨테이너(상자)를 실행하고, 전달하는 배달원 같은 역할
  • 애플리케이션의 실행 환경
    컨테이너는 음식 상자 안에 필요한 모든 것을 넣어둠
    예를 들어, 어떤 음식이든 "포크가 필요해요"라고 말 x -> 포크는 이미 상자 안에 있음 

[왜 도커 컨테이너가 필요할까요?]

컨테이너의 목적은 애플리케이션이 어디서 실행되든 똑같이 동작하도록 보장
예를 들어:

  • 개발자가 윈도우에서 애플리케이션을 개발했는데, 서버는 리눅스라면 문제가 생길 수 있음
  • 개발 환경에서는 잘 실행되던 애플리케이션이, 테스트 환경에서는 문제가 생길 수도 있음

이러한 문제는 환경 차이에서 발생. 도커 컨테이너는 이런 차이를 없애줌 

 

[도커 컨테이너가 환경 차이를 없애는 방법]

도커 컨테이너는 애플리케이션과 그 실행에 필요한 모든 것을 하나의 이미지에 포함.

이 이미지를 기반으로 실행되는 컨테이너는 환경에 상관없이 동일한 동작을 보장

구성 요소:

  • 애플리케이션 코드: 실행될 프로그램.
  • 필요한 라이브러리: 프로그램 실행에 필요한 파일들.
  • 운영체제의 기본 환경: 애플리케이션이 필요로 하는 OS의 최소한의 구성.

컨테이너는 "이 상자 안에서 애플리케이션이 실행되는 데 필요한 모든 걸 다 제공할게!" 라고 약속

 

 

도커 컨테이너 이미지란?

응용 프로그램 실행에 필요한 코드, 런타임, 시스템 도구, 시스템 라이브러리 및 설정 등 포함하는 가볍고 독립적이며 실행가능한 소프트웨어 패키지

 

컨테이너 인프라 환경은 컨테이너를 서비스 단위로 포장해 배포하고 확장할 수 있기 때문에 마이크로 아키텍처 서비스를 구현하기에 적합함.

 

가상머신 vs 컨테이너 환경 

가상머신 컨테이너
하이퍼바이저 위에 앱마다 다른 게스트 OS를 실행 Host OS 커널을 공유하여 격리된 여러 개의 컨테이너를 실행
각 VS은 자체 운영체제와 애플리케이션을 포함 각 컨테이너는 Host OS에서 프로세스로 실행되며 자체적으로 격리된 파일 시스템, 네트워크 인터페이스 및 리소스를 갖기 때문에 VM에 비해 가벼운 환경에서 빠르게 실행될 수 있음 

이미지

컨테이너 실행을 위한 템플릿 역할을 함.

컨테이너 실행에 필요한 파일과 설정값을 포함하고 있는 것으로 상태값을 가지지 않고 변하지 않는 읽기 전용 파일 시스템.

이미지를 실행하면 컨테이너 상태가 되고, 추가되거나 변하는 값은 컨테이너에 저장됨.

같은 이미지로 연러 컨테이너를 생성할 수 있고, 컨테이너가 삭제되더라도 이미지는 그대로 남아있음. 

 

Docker

이러한 애플리케이션을 신속하게 구축, 테스트 및 배포할 수 있는 소프트웨어 플랫폼.

다시 말해 컨테이너화를 가능하게 해주는 여러 도구 중 하나이다. 

도커를 사용하면 환경에 구애받지 않고 애플리케이션을 신속히 배포 및 확장 가능

 

도커의 주요 기능 

  1. 컨테이너를 사용해 애플리케이션과 필요한 구성요소 개발
    애플리케이션과 이를 지원하는 모든 요소를 컨테이너로 개발
  2. 컨테이너를 배포 및 테스트의 단위로 사용
    컨테이너 자체가 애플리케이션을 배포하고 테스트하는 단위
  3. 프로덕션 환경에 컨테이너를 배포
    애플리케이션을 프로덕션 환경에 컨테이너 환경이나 오케스트레이션 서비스를 통해 배포할 때 사용
    프로덕션 환경이 로컬 데이터 센터, 클라우드 제공업체, 또는 두 환경의 혼합형인 경우에도 동일하게 작동
💡 오케스트레이션
컨테이너화된 애플리케이션 및 서비스를 자동으로 배포, 관리, 확장, 네트워킹, 모니터링하는 과정을 말함
여러 컨테이너가 서로 협력하며 동작해야할 때, 이를 효율적이고 일관되게 관리하기 위해 필요한 기술과 도구를 지칭

 

도커는 클라이언트-서버 아키텍처를 사용

  • 도커 클라이언트
    사용자가 명령어를 입력해 도커를 제어하는 인터페이스
    CLI나 API를 통해 도커 데몬에 요청을 보냄
  • 도커 데몬
    클라이언트의 요청을 받아 실제로 컨테이너를 생성, 실행, 관리하는 백그라운드 프로세스
    도커 API 요청을 수신하며, 이미지, 컨테이너, 네트워크, 볼륨과 같은 도커 객체를 관리함
  • 도커 컴포즈
    단일 서버에서 여러 개의 컨테이너를 하나의 서비스를 정의해 컨테이너 묶음으로 관리할 수 있는 작업 환경을 제공하는 관리도구
    여러 개의 컨테이너가 작동할 때 도커 컴포즈를 사용하면, 여러 개의 컨테이너 옵션과 환경을 정의한 파일을 읽어 컨테이너를 순차적으로 한꺼번에 실행가능 
  • 도커이미지
    도커 허브에 등록하거나 도커 레지스트리 저장소를 직접 만들어 관리할 수 있음

도커 클라이언트와 데몬은 같은 시스템에서 실행될 수도 있고, 클라이언트가 원격 도커 데몬에 연결가능

클라이언트와 데몬은 REST API를 사용하여 UNIX 소켓이나 네트워크 인터페이스를 통해 통신함

도커 컴포즈는 또 다른 도커 클라이언트로, 여러 개의 컨테이너로 구성된 애플리케이션을 다룰 수 있도록 도와줌

 

포트 포워딩

서버에 접속하기 위해서는 일종의 창구 역할을 하는 포트를 지나가야 하는데, 이때 외부 포트를 내 포트와 연결시켜주는 작업을 포트 포워딩이라고 함. 예를들어, 특정 컨테이너에서 포트 포워딩을 80:8000으로 해줬다면, 외부에서 80번 포트로 접속할 시 8000번 포트로 연결시켜준다는 것을 의미함.

💡웹브라우저에서 naver.com과 같은 사이트에 접근할 때 https://www.naver.com 과 같은 주소로 접근하게 되는데, http 프로토콜은 기본적으로 80번 포트를 사용하고 https 프로토콜은 443 포트를 사용하게 되며 이는 웹브라우저에 주소를 입락할때 생략된다.

 

볼륨

도커는 기본적으로 컨테이너를 닫으면 그 안의 데이터를 모두 초기화시킴.

그래서 도커 컨테이너 안의 데이터를 백업하기 위해서는 볼륨을 이용해야함.

볼륨은 컨테이너 내의 데이터를 호스트와 공유하여 변경 내용을 저장할 수 있게 도와줌.

 

docker volume에는 docker volume, bind mount, tmpfs mount 방식이 있으며 docker volume 방식이 주로 사용됨

1. docker volume

  • docker 엔진이 관리하는 volume를 생성하는 방식
  • docker volume 방식을 사용해 생성된 volume은 host의 /var/lib/docker/volumes/ 경로에 저장됨

2. bind mount

  • docker container를 생성할 때 사용자가 지정한 경로에 데이터가 저장됨
  • docker 엔진의 관리를 받지 않는 영역이기 때문에 사용자가 직접 파일을 추가/수정/삭제할 수 있다는 특징이 있는데,
    docker 공식 문서에서는 이러한 특징으로 인해 운영에 영향을 미칠 수 있기 때문에 유사한 기능인 docker volume 방식을 사용하는 것을 권장

3. tmpfs mount

  • 기존의 방식들이 ssd 혹은 hdd(하드디스크)와 같은 저장장치에 데이터를 저장한다면, tmpfs mount 방식은 휘발성 메모리인 RAM(주기억장치)에 데이터를 저장함.
  • 휘발성이기 때문에 파일로 저장하면 안되는 민감한 정보를 다룰 때 사용됨 
docker volume bind mount tmpfs mount
컨테이너간 파일이나 설정 등 중요한 파일을 사용자가 건드리지 못하게 할 때 사용 해당 파일들을 사용자들이 공유할 수 있도록 할 때 사용 많은 양의 데이터를 '임시로' 저장할 때, 혹은 민감한 정보들을 다룰 때 사용 

 

볼륨을 생성했다면 컨테이너를 중지시킨 뒤 다시 실행시켜야 생성된 볼륨을 확인할 수 있음

사용하지 않는 볼륨은 sudo docker volume prune 명령어를 통해 일괄 삭제가능 


실습

도커 시작하기 - 단일 컨테이너

1. 도커 설치

sudo apt install docker.io -y

 

2. 소스코드 다운

git clone <github 주소>

 

3. 프로젝트 루트 폴더에 도커 설정과 이미지를 위한 Dockerfile 작성

# Python 베이스 이미지 사용
# 본인의 python --version 에 맞는 파이썬 이미지 사용
FROM python:3.11-slim

# 작업 디렉토리 설정
WORKDIR /app

# 필요한 패키지 설치
RUN apt-get update && apt-get install -y \
    libpq-dev gcc && \
    apt-get clean

# requirements.txt 복사 및 설치
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 소스 코드 복사
COPY . .

# 포트 노출
EXPOSE 8000

# 서버 실행 명령어
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]

 

4. 도커 컴포즈 설치와 실행을 위한 docker-compose.yml 작성

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

services:
  example: # 서비스 이름을 지정한다. 서비스 이름은 컨테이너끼리 통신할 때 사용
    container_name: example # 컨테이너 이름을 지정
    image: 'httpd:latest' # 컨테이너를 생성할 때 사용될 이미지를 지정
    restart: always # 컨테이너가 종료됐을 때 다시 실행시키기

 

5. Docker 이미지 빌드

docker build -t my-django-app . # 이미지 빌드

docker run -d -p 8000:8000 --name django-app my-django-app # 포트 포워딩 및 컨테이너 실행

docker-compose up -d  # docker compose 실행

 

6. 실행중인 컨테이너 확인

sudo docker ps
# or
sudo docker ps -a

 

도커 시작하기 - 복수 컨테이너

컨테이너 두 개 이상 사용할 시 docker-compose.yml을 작성하는 방법은 컨테이너 이름이나 포트번호 등 중복되면 안되는 몇가지 옵션들이 존재하기 때문에 이를 확인한 뒤에 실행해야함.(겹치지 않게 다른 번호로)

 

Dockerfile 작성

실행할 두 프로젝트에 각각 Dockerfile을 작성함

 

requirements.txt

설치해야하는 패키지와 라이브러리, 그에 대한 정보를 적어놓은 문서

해당 프로젝트를 clone 시 requirements.txt를 이용하여 빠른 라이브러리 설치가 가능

생성 : pip freeze > requirements.txt

설치 : pip install -r requirements.txt 

 

docker-compose.yml 작성 후 프로젝트 동시 실행

docker-compose up --build
이미지가 빌드되어있지 않을 때는 --build 옵션을 주지 않아도 괜찮지만,
이미지를 빌드한 후에 새로운 이미지를 배경으로 실행할 때는 -build를 붙여줘야함.
없을 시 Dockerfile로 빌드된 이미지를 사용하는 것이 아니라 기본 이미지를 빌드하여 실행되기 때문.

 

docker run vs docker-compose up -build
docker run : 단일 컨테이너를 실행하거나 테스트할 때 유용함. 빠르게 컨테이너를 띄워 확인하는데 적합함
docker-compose up --build : 복잡한 멀티컨테이너 환경에서 유용함. 배포 및 개발 환경설정하고 실행할 때 사용 

 

컨테이너 중지

docker-compose down

 

docker image bash 들어가기

sudo docker exec -it $container_id /bin/bash
# $containser_id : sudo docker ps를 쳤을 때 확인되는 container_id를 입력
# /bin/bash : 컨테이너에 접속할 때 사용되는 쉘을 입력
	# 이미지에 따라 /bin/bash라는 쉘이 존재하지 않을 수 있는데, 이 경우에는 /bin/sh를 사용해 접속한다.

 

bash shell에 접속한 뒤 마이그레이션 실행

python manage.py makemigrations
python manage.py migrate

 

 

 

728x90