본문 바로가기
[DevOps]/Docker

Docker - 이미지와 컨테이너를 공부하고 도커 이미지 다운로드 및 생성하기

by 팡펑퐁 2023. 6. 3.
728x90

Docker Image

  • 도커에서 서비스 운영 및 애플리케이션을 실행하는 데 필요한 서버 프로그램, 소스코드 및 라이브러리, 컴파일된 실행 파일 및 설정을 포함하는 탬플릿이며 일종의 빌드 블록이라고 생각할 수 있다. 도커 이미지는 읽기 전용이며 도커 컨테이너를 생성하는 데 사용된다.
  • 앞서 언급했듯이 애플리케이션을 실행하는 데 필요한 모든 것을 포함하고 있기 때문에 이식성이 높고 빠른 배포가 가능하다.
  • run 명령어를 사용하여 이미지의 인스턴스를 만드는데 이것은 이미지를 기반으로 하는 구체적인 컨테이너를 생성하는 명령어이다.

 

 

Docker Container

  • 도커 이미지를 실행한 것이다. 컨테이너는 격리된 환경에서 애플리케이션이 실행되며, 호스트 시스템으로부터 독립되어 있다. 컨테이너는 운영체제 수준의 가상화를 통해 여러 개의 독립된 컨테이너를 단일 호스트에서 실행할 수 있게 해 준다. 이러한 컨테이너화 기술은 애플리케이션을 쉽게 배포하고 확장할 수 있게 도와주며 애플리케이션 간 충돌을 방지하고 보안을 강화하는 등 이점을 제공한다. 

 

 

 간단하게 정리하면 도커 이미지는 모든 설정 명령과 코드가 포함된 공유 가능한 패키지이며, 도커 컨테이너는 그러한 이미지의 구체적인 실행 인스턴스이다.

 

 

도커 이미지를 사용하는 방법

  • 도커 이미지를 생성하고 가져오는 방법은 2가지가 있다.
  • 첫 번째는 이미 존재하는 이미지를 가져오는 방법이다. 스스로 이미지를 생성하는 것이다.
  • 두 번째는 스스로 이미지를 생성하는 것이다.
  • 도커 허브(Docker Hub)라는 곳에서 다른 사람이나 회사에서 공식적으로 구축한 이미지를 다운로드할 수 있다.
  • 예를 들어 도커 허브의 공식 노드 이미지는 공식 노드 팀에서 배포, 생성, 유지, 관리를 하며 사용자는 이러한 공식 이미지를 다운로드하여 실행하면 그만이다.

 

첫 번째 방법 : 노드 이미지 다운받아 실행하기

  • Unable to find image 'node:latest' locally
  • 로컬에 노드 이미지가 없기 때문에 Docker Hub에서 다운로드한다.

 

docker ps -a
  • 위 명령어로 도커가 생성한 모든 컨테이너, 프로세스를 볼 수 있다. ps는 프로세스이며, -a는 all을 뜻한다.

 

인터렉티브 쉘(Interactive shell)

  • 컴퓨터와 상호작용하여 명령어를 실행할 수 있는 쉘로 대화형 쉘이라고 한다.
  • 노드의 인터렉티브 쉘을 실행시키기 위해서는 도커 이미지 파일을 실행할 때 -it 명령어를 추가하면 된다.

 

  • -it 명령어를 통해 도커에게 컨테이너 내부에서 호스팅 머신으로 대화형 세션을 노출하고 싶다고 알릴 수 있다.
  • 핵심은 위의 화면은 로컬의 노드가 아니라 도커 컨테이너를 통해 실행 중인 노드라는 점이다.
  • 노드 컨테이너를 실행하고 상호 작용하는 데에 로컬 시스템에 노드를 설치할 필요가 전혀 없다.

 

  • docker ps -a 명령어로 다시 실행 중인 컨테이너를 확인해 보았다.
  • 하나의 도커 이미지로 두 개 이상의 컨테이너를 실행시키는 것 역시 가능함을 보여준다.

 

두 번째 방법 : 자체 이미지 빌드하기

  • 실습은 유데미 강의 자료로 진행했고 VSCode를 이용했다.
  • 강의 자료가 없더라도 괜찮다. 자체 이미지를 빌드하고 싶은 프로젝트 파일이라면 어떤 것도 상관없다.
  • 우선 원활한 Docker 실습을 위해 VSCode 내 Docker 확장프로그램을 설치했다.

 

  • 그리고 다운로드한 실습 자료 안에 Dockerfile을 만들었다. 확장프로그램의 설치 때문인지 고래모양이 나오는 걸 보니 VSCode에서 도커 파일로 인식하는 듯하다.
  • 이 파일 안에는 자체 이미지를 빌드할 때 실행하려고 하는 도커에 대한 명령이 포함된다.

 

  • 일반적으로 FROM 명령으로 시작한다. 
  • FROM 안에는 로컬 시스템에 존재하거나 도커 허브 상의 이미지와 같은 이름으로 한다.
  • 나는 FROM node라고 썼다.
  • node라는 이미지는 도커 허브에 존재한다. 위의 첫 번째 방법에서 Docker Hub에서 node 이미지를 가져와 컨테이너로 실행했기 때문에 현재 로컬 환경에서는 이 이미지가 다운로드 및 캐시 되어있다. 따라서 도커가 node라는 이미지를 찾을 수 있다.
  • 다음 단계로 도커에게 위의 노드 파일들이 이미지에 들어가야 한다는 것을 알려야 한다.
  • 이때 COPY 명령어를 사용한다.

 

  • COPY 이후에는 두 가지의 경로를 지정한다.
  • 첫번째 경로는 이미지, 컨테이너의 외부 경로이며 이미지로 복사되어야 할 파일들이 있는 위치이다.
  • 여기에 사진처럼 .을 넣으면 도커에게 Dockerfile이 포함된 폴더를 이미지로 복사하겠다고 알리는 것과 같다.(Dockerfile은 제외)

 

  • 실습 파일의 경우에는 NODEJS-APP-STARTING... 폴더에서 Dockerfile을 제외한 public 폴더, package.json, sever.js 파일이 이미지로 만들어질 것이다.
  • 두 번째 경로는 그 파일을 저장하는 이미지 내부의 경로이다.
  • 모든 이미지와 이미지를 기반으로 생성된 모든 컨테이너에는 로컬 머신의 파일 시스템에서 완전히 분리된 자체 내부 파일 시스템이 있다.
  • 여기서 알아둬야 할 점은 도커 시스템 내 루트 폴더보다는 사용자가 선택한 서브 폴더를 사용하는 것이 좋다는 것이다.
  • 원하는 대로 이름을 정할 수 있다. 예를 들어 /app이라고 짓는다. 만약 이미지 및 컨테이너 내에 app 폴더가 없다면 자동으로 생성된다.
  • 만약 두번째 경로도 .으로 지정하면 WORKDIR의 경로를 그대로 사용하겠다는 의미가 된다.

 

  • 첫 번째 경로와 두 번째 경로를 지정했다.

 

  • 이 파일은 node 파일이기 때문에 npm install을 통해 node.js 프로젝트에 필요한 패키지를 설치해야 한다.
  • 도커 파일에 npm install을 실행하도록 명시할 수 있다.
  • 그런데, 문제가 있다. 도커에서는 이러한 명령어가 디폴트로 루트 폴더에서 실행되게 되어 있다.
  • 우리는 package.json 파일이 있는 app 폴더 내에서 npm install이 실행되게 해야 한다.(위에 COPY를 통해 도커 컨테이너 내부에서 /app 경로를 만들고 파일을 저장했던 것을 기억하자.)

 

  • WORKDIR 명령어는 도커 컨테이너의 작업 디렉토리를 지정할 수 있다.
  • WORKDIR을 통해 /app 경로 내에서 작업을 하라는 것을 명시했다. 

 

 

RUN VS CMD

RUN 

  • 도커 이미지를 빌드하는 단계에서 실행되는 명령어이다.
  • RUN 명령어를 사용하면 도커 이미지를 빌드할 때 해당 명령어들이 순차적으로 실행되어 도커 이미지를 생성한다.
  • 일반적으로 패키지 설치, 의존성 관리, 환경 설정 등을 위해 사용한다.

 

CMD

  • 도커 컨테이너를 실행할 때 실행될 명령어를 정의한다.
  • Dockerfile 내의 CMD 명령어는 이미지를 실행하여 컨테이너를 생성할 때 실행될 기본 명령어를 지정한다.
  • 주로 애플리케이션 실행을 위해 사용한다.

 

 

  • RUN에서 패키지를 설치하고 CMD로 컨테이너가 실행된 후 노드 서버를 동작시킨다.
  • CMD는 명령어를 배열로 나눠 담는다.
  • 컨테이너 내부의 node 명령어를 사용하여 sever.js를 실행하라는 의미이다.
node server.js
  • 이 명령어와 같다.

 

 

포트  노출시키기

  • 이 노드 웹 서버는 80번 포트에서 수신 대기하고 있다.
  • 그런데 도커 컨테이너는 로컬 환경과 완전히 격리되어 있다.
  • 따라서 자체 내부 네트워크 역시 존재한다.
  • 문제는 컨테이너 내부의 노드 애플리케이션이 80번 포트를 수신할 때 컨테이너는 그 포트를 로컬 머신에 노출하지 않는다는 것이다.

 

  • 로컬 시스템에 특정 포트를 노출시키겠다는 것을 명시할 수 있다.
  • EXPOSE 명령어가 그 역할을 한다.
  • 이 실습 파일에서는 EXPOSE 80으로 80번 포트를 로컬 시스템에 노출시키겠다는 것을 명시했다.
  • EXPOSE라고 적는다고 노출되는 것은 아니다. 단지 명시하는 것일 뿐이다.
  • 노출시키는 방법은 다음에 알아보자.

 

 

 

참고

Udemy - Docker & Kubernetes : 실전 가이드

728x90