Docker가 뭐에요?
Docker랑 Docker Compose 알아보기
DevOps
Docker
애플리케이션을 컨테이너라는 격리된 환경에 패키징하여, 어떤 환경에서든(로컬 PC, 클라우드 서버 등) 동일하게 실행될 수 있도록 하는 기술
Docker는 왜 쓸까?
"제 컴퓨터에서는 잘 되는데요" 문제를 해결하기 위함
- 과거의 문제
- VM을 예시로 들어보면, 새 VM을 만들면 OS를 설치하고, Node.js 버전을 맞추고,
npm으로 패키지를 설치하고, DB 연결 설정 등 모든 것을 수동으로 다시 해야 했다. - 로컬 환경과 서버의 리눅스 환경이 다르기 때문에 예상치 못한 오류가 발생한다.
- VM을 예시로 들어보면, 새 VM을 만들면 OS를 설치하고, Node.js 버전을 맞추고,
- Docker의 해결책 (환경의 일치)
- Docker는 앱(e.g. Node.js 서버 코드)과 그 실행에 필요한 모든 것(e.g. Node.js 런타임, 특정 npm 패키지, 환경변수)을 하나의 "상자"(컨테이너)에 담아버린다.
이 컨테이너는 어디서나 완벽히 동일하게 동작한다. 즉, 개발자는 이 컨테이너만 잘 만들면 된다.
도커는 VM에 비해 매우 가벼우며(MB 단위), 시작 속도가 빠르고 자원 소모가 적다. VM 처럼 OS를 따로 설치하지도 않으며, 앱과 그 의존성만 격리된 공간에 띄운다.
핵심 용어
Dockerfile (설계도)
- 이미지를 어떻게 만들지에 대한 지시사항이 적힌 텍스트 파일
- 개발자가 작성하는 유일한 파일
- 예시:
# 1. 어떤 환경에서 시작할지 (Node.js 18 버전)
FROM node:18-alpine
# 2. 내 컴퓨터의 현재 폴더(.) 코드를 컨테이너의 /usr/src/app 폴더로 복사
COPY . /usr/src/app
# 3. 컨테이너의 작업 폴더를 방금 복사한 곳으로 변경
WORKDIR /usr/src/app
# 4. package.json을 보고 의존성 설치
RUN npm install
# 5. 컨테이너가 시작될 때 실행할 명령어 (서버 시작)
CMD ["npm", "start"]
이미지 (앱의 스냅샷 또는 설치 파일)
- Dockerfile을 바탕으로 빌드 명령어를 실행하면 생성되는 읽기 전용 템플릿
- 내 코드, 라이브러리 및 종속 항목까지 모든 것이 설치된 상태의 파일
컨테이너 (실행 중인 앱)
- 이미지를 실행 명령어로 실행시킨 실제 인스턴스
- 실제로 메모리에 올라가서 실행되는 프로세스이다. 즉, 사용자의 Node.js 서버 그 자체다.
- 하나의 이미지로 여러 개의 컨테이너를 실행할 수 있다.
Docker Compose
| 특징 | docker (Dockerfile) | docker-compose (docker-compose.yml) |
|---|---|---|
| 목적 | 단일 컨테이너 | 다중 컨테이너 애플리케이션 |
| 결과물 | 이미지 (Image) | 실행 중인 서비스 묶음 |
| 설정 파일 | Dockerfile (어떻게 빌드할까?) | docker-compose.yml (어떻게 실행하고 연결할까?) |
| 주요 명령어 | docker build, docker run | docker-compose up, docker-compose down |
Docker Compose는 여러 개의 컨테이너를 동시에 정의하고 실행하기 위한 도구이다.
Dockerfile이 단일 컨테이너의 설계도(e.g. 내 Node.js 앱)라면, docker-compose.yml 파일은 앱 전체의 설계도 (e.g. 내 Node.js 앱 + DB + Redis 캐시)이다.
Docker Compose는 왜 쓸까?
실제 앱은 대부분 단일 컨테이너로 동작하지 않는다. 데이터를 저장할 DB(e.g. MySQL)가 필요하다.
Compose가 없다면 일일이 번거롭게 복잡한 설정을 하고, 명령어를 입력하는 과정을 매번 반복해야 한다.
반면에 Compose를 사용한다면 docker-compose.yml 파일 하나만 작성해두고, 터미널에 명령어 단 하나만 입력하면 자동 관리가 된다.
docker-compose up: 파일에 정의된 모든 컨테이너(앱, DB)를 한번에 실행docker-compose down: 실행된 모든 컨테이너를 한 번에 중지하고 삭제
Docker를 활용한 워크플로우
개발과 배포에 다음과 같은 하이브리드 방식을 사용해 볼 수 있다.
평소 개발
- 로컬에서
docker-compose를 사용 (NestJS앱 + MySQL DB 컨테이너) - 빠른 속도와 무료로 기능을 개발하고 테스트
배포 전 테스트
- 기능 개발이 완료되면, Staging 또는 Dev 환경으로 Azure에 배포
- 이때 Azure Container Apps와 Azure Database for MySQL을 사용
- 실제 프로덕션 환경과 거의 동일한 이 환경에서 클라우드에서 잘 동작하는지 최종 검증
- 검증이 끝나면 프로덕션에 배포
특히 Azure Container Apps는 쿠버네티스 기반으로 만들어졌지만, 추상화가 잘 되어있어 개발자가 쿠버네티스에 대해 몰라도 쉽게 사용할 수 있는 서비스이며, 사용한 만큼 비용을 지불하기 때문에 Azure App Service보다 훨씬 비용 효율성이 좋다.
스테이징 환경
배포 환경에 바로 배포하면 코드에 심각한 버그가 있을 경우 실제 사용자들이 그대로 피해를 입는다.
이를 막기 위해 실제 서비스와 똑같은 환경을 복제한 '리허설' 서버를 만들어 두는데, 이게 바로 스테이징 환경이다.
로컬 환경과 서버 환경은 다르다. 따라서 안전하게 배포하기 위한 목적도 있다.
스테이징 환경은 프로덕션 환경과 거의 100% 동일하게 구성하며, 각종 동작을 점검한다.