도커에 대한 얘기를 주변에서 많이 들었으면서 항상 관심 있게 알아보려고 생각하지 않았습니다.
그러다 이번에 배포 환경에 대한 스터디를 하려고 알아보다가 인프런의 따라 하며 배우는 도커와 CI환경 인강을 알게 되었고, 이전부터 궁금했던 도커와 CI환경에 대해서 가볍게 살펴볼 수 있을 것 같아 학습한 내용을 정리했습니다.
컴퓨터는 하나의 서버를 하나의 용도로만 사용해서 남는 서버 공간은 그대로 방치되었고 하나의 운영체제만 사용하고 하나의 프로그램만 운영했기에 안정적이었지만 비효율적이였습니다.
이러한 비효율적인 문제를 해결하기 위해 나온 기술이 가상화 기술이며, 물리 서버 1대 위에 여러대의 가상 서버를 만들어서 사용하는 기술로 용량을 늘리거나 줄이는 부분이 쉬워 효율적으로 사용할 수 있습니다.
하이퍼 바이저는 논리적으로 공간을 분할하여 VM이라는 독립적인 가상 환경의 서버 이용이 가능한 기술입니다.
하이퍼 바이저는 논리적으로 분리되어 있기 때문에 하나의 VM에 오류가 발생해도 다른 VM으로 퍼지지 않는다는 장점이 있습니다.
도커란 리눅스 컨테이너 기반으로 하는 가상화 플랫폼으로 쉽게 말하면, 데이터 또는 프로그램을 격리시키는 기능을 제공하는 소프트웨어입니다.
도커는 기존의 가상화 기술에서 나온 컨테이너 가상화 기술로서 기존 VM과 비교했을 때 하이퍼바이저와 게스트OS가 필요하지 않기 때문에 훨씬 가볍습니다.
도커의 컨테이너 격리에 대해 알기 위해 리눅스에서 쓰이는 Cgroup(control groups)과 네임스페이스(namespaces)에 대해 알아야 합니다.
이런 기술들을 이용해서 컨테이너 기술을 사용할 수 있고, 리눅스 커널에 있는 기능을 컨테이너 기술로 가져온 것이라고 생각할 수 있습니다.
도커 컨테이너 기술도 리눅스에서 쓰이는 기술을 사용하여 컨테이너를 사용할 수 있다고 했습니다.
즉, 도커는 리눅스 운영체제에서 사용되는 프로그램입니다.
하지만 윈도우 , macOS를 사용하는 사용자도 도커를 사용할 수 있는데, 어떻게 리눅스 운영체제에서 돌아가는 도커를 사용할 수 있을까요?
윈도우 , macOS를 사용하는 사용자는 도커를 설치해서 사용할 수 있는데, 이 때 도커 패키지안에는 리눅스 운영체제등의 실행 환경에 필요한 것들을 함께 묶어서 패키지로 설치하기 때문에 가능합니다.
가상의 리눅스 환경을 만들고 이 환경에서 도커 엔진을 구동하게 하는 것입니다.
즉, mac용 도커를 설치하면 그 안에 가상환경(Hyper-Kit)과 리눅스 운영체제와 도커엔진이 한번에 패키지로 다운받게 되어 가상화 소프트웨어나 리눅스 운영체제의 존재를 신경쓰지 않고 사용할 수 있습니다.
앞서, 도커 패키지를 설치할때 가상환경, 리눅스 운영체제, 도커 엔진을 한번에 패키지로 받는다고 설명했습니다.
하이퍼바이저의 단점이 게스트OS의 무거움이라고 했는데 도커를 설치할때 리눅스 운영체제를 설치하면 무겁지 않을까요?
그래서 실제 도커 컨테이너 안에는 운영체제가 들어있는 것이 아니라, 운영체제 비슷한 무언가가 들어가 있을 뿐입니다.
도커는 컨테이너가 완전히 분리되어 있음으로, 컨테이너 속에 운영체제의 주변 부분이 들어있어서 프로그램의 명령을 전달받고 이를 밑바탕이 되는 커널에 전달하는 구조로 되어있습니다.
즉, 리눅스 운영체제 전체를 컨테이너에 넣지 않음으로써 도커는 가볍게 가상화를 구현할 수 있습니다.
도커 컨테이너 기술로 격리된 가상화 공간을 만들 수 있으며, 도커의 컨테이너는 도커 이미지를 통해 만들 수 있습니다.
도커 이미지란, 템플릿과 같으며 컨테이너의 설계도 역할을 합니다.
예를들어 로봇 장난감을 만들 수 있는 금형 틀을 이미지라고 할 수 있으며, 금형 틀로 만들어내는 로봇 인형은 컨테이너로 비유할 수 있습니다.
이렇듯 이미지 하나로 동일한 컨테이너를 여러개 만들 수 있습니다.
즉, 이미지는 코드, 런타임, 시스템 도구, 시스템 라이브러리 설정과 같은 프로그램을 실행하는데 필요한 모든 것을 포함합니다.
컨테이너는 이미지로 생성된 인스턴스이며 각각의 독립된 환경에서 프로그램을 실행합니다.
도커 허브는, 도커 이미지를 저장하고 공유할 수 있는 서비스로 직접 만든 이미지를 업로드할 수도 있고 다른사람들이 만들어둔 이미지를 다운로드할 수 있습니다.
전체 소스 코드는 여기서 확인 가능합니다.
Dockerfile.dev
, Dockerfile
docker build ./
: Dockerfile을 찾아서 실행합니다.docker build -f Dockerfile.dev -t <image-name> ./
: 개발서버의 도커 환경을 실행하려면 -f 옵션으로 도커파일을 직접 지정합니다.docker run <image-name>
로 도커 이미지로 컨테이너를 생성 후 실행하게 되는데 http://localhost:3000
로 접속해도 리액트 프로젝트가 제대로 나오지 않는 문제가 발생합니다. docker run -it -p 3000:3000 <image-name>
: 로 포트 매핑docker-compose.yml
, docker-compose-dev.yml
작성docker run -it <image-name> npm run test
docker build -t <image-name> .
docker run -p 8080:80 <image-name>
# Node.js 16 버전을 사용하는 Alpine 이미지 선택
FROM node:16-alpine as builder
# 작업 디렉토리 설정
WORKDIR '/app'
# .package.json 복사
# 의존성 설치 전에 package.json을 먼저 복사하는 이유는 package.json 의 파일들이 변경되지 않는 한, Docker가 이전에 캐시된 의존성 설치 단계를 재사용하게 하기 위함입니다.
COPY package.json .
# 의존성 설치
RUN npm install
# 전체 애플리케이션 코드 복사
COPY . .
# React 애플리케이션 빌드
RUN npm run build
# 빌드된 결과물을 Nginx로 복사
FROM nginx
COPY --from=builder /app/build /usr/share/nginx/html
docker ps , docker ps -a : 도커 상태보기
stop : 컨테이너 중지, 만약 메시지를 보내고 있었다면 다 보내고 이후 중지된다.
kill : 메시지를 다 보내지 않았더라도 즉시 컨테이너 중지
rm : docker rm 컨테이너 아이디. 삭제할때 사용
docker rm `docker ps -a -q` : 모든 컨테이너 삭제
docker build -t <image-name> : 도커 이미지 생성
docker run <image-name> : 도커 이미지로 컨테이너 생성 후 실행
docker-compose up : 이미지가 없을 때 이미지를 빌드하고 컨테이너 시작
docker compse up --build : 이미지가 있든 없든 이미지 빌드하고 컨테이너 시작
docker compose down : 중지시키기
이전 회사에서 리액트 프로젝트를 할 때 팀원의 노드 버전이나 다른 패키지의 버전이 다를 경우 다른 팀원들이 다 같이 버전을 맞춰야 하는 번거로움이 있었습니다.
이번 도커를 공부할 때 흥미로웠던 점은 이전 회사의 경험이랑 비교해 보면서 도커를 사용했으면 편하게 개발할 수 있었겠다는 라는 체감이 느껴져서였던 것 같습니다.
하지만 도커는 이론으로 이러이러한 것이 도커구나 라고 머리로는 이해해도 실습을 따라 하면서 도커 플로우를 이해한다는 것이 생각보다 어려웠습니다.
이번에는 도커와 배포 환경에 대해 가볍게 훑어보는 과정이었지만, 앞으로 여러 번 더 해보면서 플로우를 익혀야 할 것 같다는 생각을 했습니다.