도커(Docker)

양지원·약 3시간 전

학습일지

목록 보기
4/4
post-thumbnail

그래서 도커가 뭔데?

앞서 VM과 Container에 대해 알아봤는데 거기에서 나왔던 개념은 도커이다.

부트캠프에서도 나를 못살게 굴던 도커.. 고래를 좋아하던 나지만 그때만큼은 고래 보기가 너무 싫었다. 오늘에야말로 머리에 박아줄테다.

Docker와 Container, 도대체 뭐가 다른 걸까?

도커와 컨테이너 뭐가 다를까? 이게 제일 받아들이기 어려운 부분이었다.
도커는 플랫폼.. 도커가 컨테이너 만듦.. 뭔가 알 것 같으면서도 손에 잡히지 않아 답답했다.

Container를 실행한다는 건 무슨 뜻이지?
Image는 또 뭐고, 코드를 수정하면 매번 다시 빌드해야 하나?

처음에는 Docker, Image, Container가 전부 비슷한 개념처럼 느껴졌는데, 실제로는 각각 역할이 명확하게 다르다.


1. Docker란?

Docker는 Container를 생성하고 실행하고 관리하는 플랫폼이다.

조금 더 쉽게 말하면,

Docker는 Container를 직접 실행하고 관리해주는 도구다.

Docker 자체가 애플리케이션이 실행되는 공간은 아니다.

Docker는 다음과 같은 일을 한다.

  • Docker Image 빌드
  • Container 생성
  • Container 실행 및 종료
  • Container 삭제
  • Network 관리
  • Volume 관리

즉, 실제 애플리케이션은 Container 안에서 실행되고, Docker는 그 Container를 관리한다.


2. Docker와 Container의 차이

구조를 그림으로 보면 다음과 같다.

Docker는 여러 Container를 만들고 실행하고 관리한다.

반면 Container는 실제로 애플리케이션이 실행되고 있는 격리된 환경이다.

예를 들어 Spring Boot 애플리케이션을 Docker로 실행한다면,

Docker
   ↓
Container 생성
   ↓
Container 내부에서
java -jar app.jar
   ↓
Spring Boot 실행

이라는 흐름이 된다.

정리하면,

Docker
= Container를 관리하는 플랫폼

Container
= 실제 애플리케이션이 실행되는 환경

3. Docker Image는 무엇일까?

Container는 아무것도 없는 상태에서 바로 만들어지는 것이 아니다.

Container를 만들기 위해서는 Image가 필요하다.

Dockerfile
   ↓
docker build
   ↓
Docker Image
   ↓
docker run
   ↓
Container

Docker Image는 쉽게 말하면

Container를 만들기 위한 실행 환경의 완성본

이라고 볼 수 있다.

예를 들어 Spring Boot 애플리케이션이라면 Image 안에는 다음과 같은 정보가 들어갈 수 있다.

Java 실행 환경
+
Spring Boot jar 파일
+
애플리케이션 실행 명령어

이 Image를 기반으로 Container가 생성된다.

부트캠프에서 튜터님께서는 Docker Image를 게임 CD에 비유해 설명해주셨다.

게임 CD에는 게임을 실행하는 데 필요한 파일들이 담겨 있기 때문에, 호환되는 컴퓨터라면 같은 CD를 이용해 동일한 게임을 실행할 수 있다.

Docker Image도 비슷하다. 애플리케이션을 실행하는 데 필요한 애플리케이션 파일, Runtime, Library, 설정 및 실행 명령 등을 하나의 Image로 만들어 둔다.

그리고 이 Image를 기반으로 어느 환경에서든 동일한 구성의 Container를 생성할 수 있다.

즉, Image는 실행 중인 프로그램 자체가 아니라 Container를 만들어내기 위한 원본이라고 이해할 수 있다.

CD ≈ Docker Image
CD를 이용해 실행된 게임 ≈ Container

Image = 저장되어 있는 원본
Container = Image를 기반으로 실제 실행된 인스턴스

4. Dockerfile은 무엇일까?

Dockerfile은

Docker Image를 어떻게 만들지 정의하는 파일

이다.

예를 들어 Spring Boot 프로젝트에서는 다음과 같이 작성할 수 있다.

FROM eclipse-temurin:17-jre

COPY build/libs/app.jar app.jar

ENTRYPOINT ["java", "-jar", "app.jar"]

각 줄의 의미는 다음과 같다.

FROM
→ Java 17 실행 환경을 사용한다.

COPY
→ Spring Boot jar 파일을 Image 안에 넣는다.

ENTRYPOINT
→ Container가 실행되면
   java -jar app.jar 명령어를 실행한다.

즉 Dockerfile은 일종의 Image 제작 설명서다.


5. Docker Image 빌드

Dockerfile을 작성했다면 Image를 만들어야 한다.

docker build -t my-spring-app .

여기서

docker build
→ Docker Image 생성

-t my-spring-app
→ Image 이름 지정

.
→ 현재 디렉터리의 Dockerfile 사용

이라는 의미다.

빌드가 완료되면 다음 명령어로 Image를 확인할 수 있다.

docker images

6. Container 실행

Image가 만들어졌다면 이제 Container를 실행할 수 있다.

docker run -d -p 8080:8080 my-spring-app

흐름은 다음과 같다.

my-spring-app Image
        ↓
docker run
        ↓
Container 생성
        ↓
Container 내부에서
java -jar app.jar 실행
        ↓
Spring Boot 실행

실행 중인 Container는 다음 명령어로 확인할 수 있다.

docker ps

7. Docker 명령어는 어디에서 실행할까?

Docker 명령어는 터미널(Terminal)에서 실행한다.

Windows라면 다음과 같은 환경에서 사용할 수 있다.

  • PowerShell
  • Command Prompt
  • Git Bash
  • WSL

나는 Windows에서 Docker Desktop을 사용하고 있기 때문에,

Docker Desktop 실행
        ↓
Docker Engine 실행
        ↓
WSL
        ↓
docker 명령어 입력

형태로 사용한다.

Docker가 정상적으로 실행되고 있는지는 다음 명령어로 확인할 수 있다.

docker version

또는

docker ps

8. 자주 사용하는 Docker 명령어

Docker Image 확인

docker images

실행 중인 Container 확인

docker ps

전체 Container 확인

docker ps -a

Container 실행

docker run IMAGE_NAME

Container 종료


docker stop CONTAINER_ID

Container 삭제

docker rm CONTAINER_ID

Image 삭제

docker rmi IMAGE_ID

Image 빌드

docker build -t IMAGE_NAME .

9. 코드를 수정하면 Image를 다시 빌드해야 할까?

결론부터 말하면,

기본적으로는 다시 빌드해야 한다.

Docker Image는 Image를 생성한 시점의 코드와 실행 환경을 가지고 있기 때문이다.

예를 들어 처음 Image를 만들었을 때 다음 코드가 들어 있었다고 해보자.

Image v1
└─ app.jar
   └─ 기존 코드

그 이후 Spring Boot 코드를 수정해도 기존 Image 안의 app.jar가 자동으로 바뀌지는 않는다.

따라서 다음 과정이 다시 필요하다.

Spring Boot 코드 수정
        ↓
Gradle Build
        ↓
새 app.jar 생성
        ↓
Docker Image 재빌드
        ↓
새 Container 실행

Spring Boot 기준으로는 대략 다음과 같다.

./gradlew bootJar
docker build -t my-spring-app .
docker run -d -p 8080:8080 my-spring-app

10. 그런데 매번 직접 재빌드하면 불편하지 않을까?

맞다.

개발하면서 코드를 한 줄 수정할 때마다

Gradle Build
→ Docker Build
→ Container 종료
→ Container 실행

을 직접 반복한다면 너무 비효율적이다.

그래서 개발 환경과 배포 환경에서는 Docker를 사용하는 방식이 조금 다르다.

로컬 개발 환경

개발 중에는 보통

  • IntelliJ에서 Spring Boot 직접 실행
  • Spring Boot DevTools 사용
  • Volume 또는 Bind Mount 사용
  • Docker Compose 사용

등의 방법을 사용한다.

나는 여기에서 Docker Compose를 사용했었다.

Docker Compose를 사용하면 Spring Boot, MySQL, Redis처럼 여러 애플리케이션이나 인프라를 각각 따로 실행하지 않고, 하나의 설정 파일을 통해 여러 Container를 함께 실행하고 관리할 수 있다.

compose.yaml
      ↓
docker compose up
      ↓
┌──────────────────┐
│ Spring Boot     │
│ Container       │
└──────────────────┘

┌──────────────────┐
│ MySQL           │
│ Container       │
└──────────────────┘

┌──────────────────┐
│ Redis           │
│ Container       │
└──────────────────┘

다만 Docker Compose를 사용한다고 해서 코드 변경 사항이 자동으로 Container에 반영되는 것은 아니다.

코드 변경 사항을 빠르게 반영하려면 상황에 따라 Bind Mount, Volume, DevTools, Docker Compose Watch 또는 Image 재빌드 등의 방법을 함께 사용해야 한다.

즉, Docker Compose의 핵심 역할은 코드 자동 반영보다는 여러 Container의 실행 환경을 한 번에 구성하고 관리하는 것에 가깝다.


11. 배포에서는 CI/CD로 자동화할 수 있다

배포 환경에서는 Docker Image 재빌드를 사람이 직접 하지 않고 CI/CD가 처리하도록 만들 수 있다.

예를 들어 프로젝트를 진행할 때 우리 팀은 GitHub Actions를 사용했다.

코드 수정
   ↓
git push
   ↓
GitHub Actions 실행
   ↓
Gradle Build
   ↓
Test
   ↓
Docker Image Build
   ↓
Docker Hub / ECR Push
   ↓
EC2에서 새로운 Image Pull
   ↓
기존 Container 종료
   ↓
새 Container 실행

과 같은 흐름으로 자동화할 수 있다.

즉 개발자가 하는 일은 결국

코드 수정
↓
git push

까지가 되고,

그 이후

빌드
테스트
Docker Image 생성
Image Push
배포

과정은 CI/CD Pipeline에서 자동화할 수 있다.


12. Docker 전체 흐름 정리

Docker를 이해할 때는 다음 흐름을 기억하면 된다.

Dockerfile
   ↓
docker build
   ↓
Docker Image
   ↓
docker run
   ↓
Container
   ↓
Application 실행

Spring Boot 기준으로 조금 더 확장하면,

Spring Boot 코드
       ↓
Gradle Build
       ↓
app.jar
       ↓
Dockerfile
       ↓
docker build
       ↓
Docker Image
       ↓
docker run
       ↓
Container
       ↓
Spring Boot 실행

그리고 실제 배포 환경에서는,

Spring Boot
   ↓
Docker Image
   ↓
Docker Hub / ECR
   ↓
EC2
   ↓
docker pull
   ↓
docker run
   ↓
Container 실행

형태로 이어진다.


정리

Docker 관련 개념을 한 줄씩 정리하면 다음과 같다.

Docker
→ Container를 생성/실행/관리하는 플랫폼

Dockerfile
→ Docker Image를 만드는 방법을 정의한 파일

Docker Image
→ Container를 만들기 위한 실행 환경의 완성본

Container
→ Image를 기반으로 실제 애플리케이션이 실행되는 격리된 환경

docker build
→ Image 생성

docker run
→ Image를 기반으로 Container 생성 및 실행

가장 중요한 관계는 결국 이것이다.

Dockerfile
    ↓ build
Image
    ↓ run
Container
    ↓
Application

처음 Docker를 볼 때는 Docker, Image, Container가 모두 비슷하게 느껴지지만, 역할을 나눠 보면 생각보다 단순하다.

Docker는 관리자이고, Image는 실행 환경의 원본이며, Container는 그 Image를 실제로 실행한 상태다.

profile
비전공자의 우당탕탕 백엔드 취업기

0개의 댓글