Docker란?

2025. 3. 20. 16:38개발 및 운영(DevOps) 도구

Trends

2024 Stack overflow에 설문조사에 따르면 (링크바로가기)

Docker는 전문 개발자(59%)들이 가장 많이 사용하고

 

Docker 사용자가 이 도구를 매우 높이(78%) 평가하고 있으며, 가장 선호하는 도구로 2년 연속으로 선정되고 있음

 

도커란 무엇인가?

Application을 패키징 할 수 있는 툴

Container라고 불리는 하나의 작은 소프트웨어 유닛안에

Application과 그에 필요한 System 환경설정, 모든 Dependencies를 하나에 묶어서

다른 Server, 다른 PC 그 어떤 곳에도 쉽게 배포하고 안정적으로 구동할 수 있게 도와주는 툴

Application을 구동하는데 많은 것들이 필요한데,

Node.js를 예로 든다면, 소스파일만 서버에 배포하기보다

Npm을 사용한다면 여러 dependencies, 환경설정, 환경변수 모든 것들을 다 설정해줘야 하는데

Server마다 개발자들의 PC마다 이런 모든 것을 설치하고 설정하는 것은 꽤 번거롭고 오류도 많이 발생할 수 있다. (ex. Node.js 버전 불일치)

 

이러한 문제점을 해결하기 위해 Docker를 사용

Docker Container안에는 Application, Node.js, 환경설정, npm, 여러 라이브러리의 dependencies, application에 필요한 다양한 리소스 들이 포함될 수 있음

Docker는 Application 구동을 위해 런타임 환경에 필요한 모든 것들을 어떤 PC에서도 언제든지 동일하게 구동할 수 있음

→ 로컬에서 동작하지만 서버에서 안되는 문제를 해결할 수 있고,

→ 설정의 번거로움을 줄일 수 있다.

 

Docker의 Container가 VM과 비슷한 것이 아닌가?

Virtual Machine(VM, 가상머신)

하드웨어 Infrastructure 위에 VMware, Virtual Box와 같은 Hypervisor 소프트웨어를 이용해서 각각의 가상머신을 만들 수 있음

한 운영체제 위에서, 동일한 Application의 각각의 고립된 다른 환경에서 구동하기 위해서는 이 가상머신을 이용해서 Application을 구동해야 함

VM은 각각의 운영체제를 포함하고 있기 때문에 맥이라는 OS 위에서 VM을 사용하면 윈도우와 리눅스를 동시에 구동할 수 있음

→ 운영체제를 포함하여 굉장히 무겁고 시작하는데도 오래 걸리고 리소스를 잡아먹는 불상사

 

Container : VM에서 경량화된 컨셉

HOST OS(하드웨어에 설치된 OS)에서 Container Engine이라는 소프트웨어를 설치만 하면 개별적인 Container를 만들어서 각각의 Application을 고립된 환경에서 구동할 수 있게 해줌

VM은 OS를 포함했다면, Container는 OS를 포함하지 않고 Container Engine 설치된 Host OS를 공유

Container가 구동하기 위해서 Container Engine이 필요하고,

Container Engine이 Host OS에 접근해서 필요한 것들을 처리해준다.

Container Engine중에 가장 많이 사용하는 것이 Docker

 

Docker의 3대 구성요소 (동작순서)

DockerContainer를 만들고 배포하고 구동

Container를 만들기 위해서는, Docker파일 생성 → Docker 이용하여 이미지 생성 → Container 구동

Dockerfile(도커 파일)

Container를 생성하는 방법을 명시하는 설정 파일

이것으로 컨테이너를 만들고, 실행 환경을 구성

Dockerfile의 주요 내용

  • 애플리케이션 실행을 위한 필수 파일 및 의존성 정의
  • 프레임워크 및 라이브러리 설치
  • 환경 변수 설정
  • 실행 스크립트 포함

 

이미지(Image)

Dockerfile을 기반으로 생성된 실행 가능한 애플리케이션 패키지

코드, 런타임 환경, 시스템 설정, 라이브러리 등이 포함되며, 이를 활용해 컨테이너를 실행할 수 있음

불변의 상태이며, 한 번 생성된 이미지는 변경할 수 없음

새로운 변경 사항을 적용하려면 새로운 이미지를 생성해야 함

 

컨테이너(Container)

캡처해둔 Application Image를 고립된 환경에서 개별적으로 실행할 수 있도록 하는 기술

이를 통해 동일한 Application을 여러 개의 독립적인 Container에서 실행할 수 있음

컨테이너와 이미지의 관계

이미지(Image): 실행할 애플리케이션을 스냅샷처럼 저장한 불변(Immutable)한 상태의 파일

컨테이너(Container): 이미지를 실행한 개별적인 인스턴스

컨테이너는 이미지에서 파일을 생성하거나 수정할 수 있으며, 개별적으로 설정 및 실행이 가능. 하지만 이미지를 변경해도 기존 컨테이너에는 영향을 주지 않음.

→ 컨테이너(Container)는 실행 중에 파일을 수정할 수 있지만, 이미지 자체에는 영향을 주지 않음

→ 컨테이너에서 변경한 내용을 유지하려면 새로운 이미지를 생성해야 힘 (docker commit 명령어 활용 가능)

 

 

Docker Image 배포 과정

Docker Image는 로컬 환경에서 생성한 후, 컨테이너 레지스트리(Container Registry)에 업로드하여 배포

이를 통해 서버나 다른 개발자들이 동일한 이미지를 가져와 실행할 수 있음

 

배포 과정

  1. 로컬에서 도커 이미지 생성
  2. 컨테이너 레지스트리에 이미지 업로드 (PUSH)
  3. 필요한 서버 또는 개발자가 컨테이너 레지스트리에서 이미지 다운로드 (PULL)
  4. 다운로드한 이미지를 실행하여 컨테이너 생성 (컨테이너를 정상적으로 실행하려면 해당 서버에 도커 엔진이 반드시 설치되어 있어야 함)

컨테이너 레지스트리(Container Registry)란?

도커 이미지를 저장하고 공유할 수 있는 공간

1. Public 레지스트리

누구나 접근 가능하며, 오픈소스 및 퍼블릭 프로젝트에 주로 사용됨

ex) Docker Hub, Red Hat Quay.io, GitHub Packages

2. Private 레지스트리

보안이 중요한 기업 및 프로젝트에서 사용

외부 사용자가 접근할 수 없으며, 사내 프로젝트의 이미지 관리를 위해 활용됨

ex) AWS (Amazon Elastic Container Registry, ECR), Google Cloud Container Registry, Microsoft Azure Container Registry

대부분의 기업에서는 보안 및 접근 제어를 위해 private 레지스트리를 사용하며, 주요 클라우드 제공업체들도 해당 서비스를 지원

총 정리

  1. Docker 설치
    1. 로컬 개발 환경과 서버에 Docker를 설치
  2. Dockerfile 작성
    1. 애플리케이션 실행을 위한 Dockerfile을 작성
  3. Docker 이미지 생성 (Build)
    1. Dockerfile을 기반으로 실행 가능한 이미지를 생성
  4. 컨테이너 레지스트리에 업로드 (Push)
    1. 만든 이미지를 컨테이너 레지스트리(Container Registry)에 업로드
  5. 서버에서 이미지 다운로드 (Pull)
    1. 서버에서 필요한 이미지를 컨테이너 레지스트리에서 다운로드
  6. 컨테이너 실행 (Run)
    1. 서버에서 다운로드한 이미지를 기반으로 컨테이너를 실행

 

실습

1. 운영체제에 맞는 docker 설치

2. node.js 프로젝트 생성

프로젝트 초기화

npm init -y
 

express 설치

npm install express

 

 

index.js

const express = require("express");
 
 
const app = express();
 
 
app.get("/", (req, res) => {
  res.send("Programmer in Docker!");
});
 
 
app.listen(8080, () => console.log("Server is running"));

 

파일 실행

node index.js

 

결과 화면

3. Dockerfile 생성

Dockerfile

FROM node:16-alpine
 
 
WORKDIR /app
 
 
COPY package.json package-lock.json ./
 
 
RUN npm ci
 
 
COPY index.js .
 
 
ENTRYPOINT [ "node", "index.js" ]

Dockerfile 포맷

Dockerfile 은 기본적으로 다음과 같은 명령문이 겹겹이 쌓인 layer 형태로 구성되어 있음

 

# 주석 (Comment)명령어 (INSTRUCTION) 인자 (arguments)

 

각 명령어는 모두 대문자로 작성하며 여러개의 인자가 따라올 수 있음

주석 또한 달 수 있음

 

FROM (FROM node:16-alpine)

  • base image
  • node 의 경우 미리 만들어 둔 node base image 가 있어 그것을 가져옴

FROM <base image:version>

뒤에 오는 숫자는 버전을 의미하며, alpine 은 최소의 linux 버전

  • ubuntu 최신 버전을 base image 로 사용
    • FROM ubuntu:lastes
  • node.js 16 버전, linux 기반을 base image 로 사용
    • FROM node:16-alpine

 

WORKDIR (WORKDIR /app)

  • 리눅스 명령어 cd 처럼 container 상에서 작업 디렉토리를 전환하기 위해 사용

WORKDIR <경로>

  • 루트 디렉토리의 app 폴더 안의 모든 파일을 카피

 

COPY (COPY package.json package-lock.json ./)

  • host PC 의 파일을 Docker image의 파일 시스템으로 복사하기 위해 사용
  • 절대경로와 상대경로를 모두 사용할 수 있으며, 상대경로를 사용하는 경우 이전에 WORKDIR 명령어로 전환된 현재 위치를 고려해야 함
  • Dockerfile 에서 명령어를 수행할 때 레이어 시스템으로 구성되므로 빈번히 변경되는 파일일수록 제일 마지막에 작성하는게 좋음

COPY <파일> <경로>

  • package.json 파일을 현재 경로에 복사
    • COPY package.json ./

→ 파일 중 소스코드를 담고 있는 index.js가 디펜던시에 대한 정보를 담고 있는 package.json 이나 package-lock.json 보다 빈번히 변경되므로 제일 나중에 복사

 

RUN (RUN npm ci)

실행 명령어

RUN <커맨드>

npm install을 사용하면 최신 버전이 설치되어 버전이 달라질 수 있기 때문에

개발 시 사용한 정확한 버전을 설치하도록 package-lock.json 을 참고하는 npm ci 를 사용하는 것이 좋음

  • npm 패키지 설치
    • RUN npm install <패키지>

 

ENTRYPOINT

이미지가 컨테이너로 만들어져 실행될 때 항상 실행되어야 하는 커맨드를 지정

ENTRYPOINT <커맨드>

  • npm start
    • ENTRYPOINT npm start

 

 

4. Image 만들기

build

docker build -f Dockerfile -t my-first-docker .
  • .
    • build context 최상위 경로에 Dockerfile 이 있음
  • -f, --file
    • Dockerfile 을 가리킴
    • 기본적으로 Dockerfile 이라고 작성하지만 다른 이름을 지정할 수 있음
    • default = 'PATH/Dockerfile'
  • -t, --tag
    • -tag
    • Docker image 의 이름을 지정함

다음과 같이 만들어지는 것을 확인할 수 있음

 

images

docker images 명령어를 사용하면 생성된 image 파일을 볼 수 있음

 

docker images

  • REPOSITORY
    • github의 repository 와 동일하며, container 에 올릴 때 이 이름을 재사용하게 됨
  • TAG
    • image 버전을 따로 지정하지 않았기 때문에 default 값인 lastest임

 

run

docker run -d -p 8080:8080 my-first-docker

 

  • -d, --detach
    • container 가 백그라운드에서 실행되고 있게 함
    • node.js 백엔드 어플리케이션이기 때문에 terminal 이 기다리지 않도록 detach 해줌
  • -p, --publish
    • <host 의 포트>:<container 의 포트>
    • container 는 고립된 환경에서 동작하므로 host 의 포트와 container 의 포트를 연결

 

5. 실행 결과

docker ps 명령어로 실행중인 container 의 리스트를 확인할 수 있다.

docker ps

 

localhost:8080 으로 들어가보면

 

추가 명령어

docker logs <container id>

container 에서 발생하고 있는 터미널 메세지 (로그) 를 확인

 

docker tag

image 파일의 이름을 변경

 

그러면 두개의 이름이 나와있는 것을 볼 수 있음

 

배포 (Docker hub)

Repository 생성 

Docker hub (https://hub.docker.com/) 에서 새로운 repository 를 만들면, Docker commands 에 어떻게 image 를 push 할 수 있는지 알려줌

접속하여 Create a Repository 클릭

 

docker push <docker 계정>/<repository 이름>:<태그>

image 이름 변경

tag 명령어를 사용하여 만들었던 image 의 이름을 docker 계정을 넣어 새롭게 만들어 줌

 

docker push soyeong5857/my-first-repository:tagname

 

로그인

푸쉬 전에 로그인 먼저 해야한다.

docker login 명령어를 사용하여 로그인

docker login

 

push

docker push soyeong5857/my-first-repository:latest

 

push 완료 (https://hub.docker.com/

 

이렇게 도커의 이미지가 등록된 것을 볼 수 있다.

 

출처

https://www.youtube.com/watch?v=LXJhA3VWXFA

https://survey.stackoverflow.co/2024/technology#most-popular-technologies-tools-tech