Docker - 볼륨과 컨테이너 교체

김소희·2025년 11월 18일

이미지를 업데이트하면 왜 컨테이너를 지우고 다시 만들어야 하지?
데이터는 어디에 저장되는 거지?

운영 중인 컨테이너 내부에서 직접 소스를 수정하기 시작하면 어떤 버전의 코드가 적용되어 있는지 추적하기 어려워지고, 운영 환경과 테스트 환경 간의 일관성이 무너지게 된다.
그 결과 “왜 이 서버만 오류가 나는가?”와 같은 원인을 파악하기 힘든 문제가 발생한다.
따라서 코드는 항상 이미지를 통해 버전이 명확하게 관리되어야 하며,
컨테이너는 그 이미지를 기반으로 실행되는 단위일 뿐이다.
필요할 때마다 컨테이너를 재생성하여 변경 사항을 적용하는 방식이 DevOps의 기본 원칙이다.

컨테이너의 특징: 휘발성과 불변성

Docker 컨테이너는 휘발성이다
컨테이너 내부에 데이터를 저장하면 컨테이너가 삭제되는 순간 함께 사라진다.

또한 Docker는 Immutable Infrastructure(불변 인프라) 원칙을 따른다.

항목Docker 원칙
실행 중인 컨테이너버려도 됨
실행 환경(이미지)항상 동일하게 유지
데이터영구 저장해야 함

컨테이너는 언제든 죽일 수 있는 실행 단위,
데이터는 영구 보관해야 할 자산
→ 그래서 볼륨은 유지하고 컨테이너만 교체한다.


컨테이너의 데이터 저장소: Volume

Docker Volume은 컨테이너 외부에 있는 저장 공간이다.
컨테이너를 지워도 볼륨에 저장된 데이터는 남아있다.

Volume = 컨테이너가 바뀌어도 유지되는 영구 데이터 저장소

쉽게 비유하면

  • 컨테이너 내부 디스크 = 안내문 (확인하고 버려짐)
  • 볼륨 = 사물함 (중요 자료는 여기 보관)

예시: MySQL 데이터 보호하기

기존 컨테이너

docker run -d \
  --name mysql-old \
  -e MYSQL_ROOT_PASSWORD=1234 \
  -v mysql_data:/var/lib/mysql \
  mysql:8.0
  • mysql_data 볼륨에 데이터 저장
  • 컨테이너는 mysql-old

① MySQL 버전 업그레이드 이미지 업데이트

docker pull mysql:8.1

② 기존 컨테이너 제거

docker stop mysql-old
docker rm mysql-old

데이터는 볼륨에 있으니 안전하다

③ 새 이미지로 컨테이너 실행

docker run -d \
  --name mysql-new \
  -e MYSQL_ROOT_PASSWORD=1234 \
  -v mysql_data:/var/lib/mysql \
  mysql:8.1

새 컨테이너지만 기존 데이터 그대로 사용


왜 이렇게 해야 할까?

운영 환경을 항상 동일하게 유지

서버 안에서 직접 코드 수정 → 불일치 환경 발생
이미지를 새로 빌드 → 완전한 재현성

배포 자동화와 무중단 서비스 가능

  • 새 컨테이너 생성
  • 검증 후 트래픽 전환
  • 기존 컨테이너 제거

롤링 업데이트 가능

장애 대응 및 롤백이 쉬움

컨테이너 교체 = 몇 초면 완료


실습

// 도커 설치 및 실행
docker run -e MYSQL_ROOT_PASSWORD=1004 -p 3307:3306 -d mysql
-e : 환경변수 / -P :  포트 바인딩 / -d : detached mode 백그라운드 실행

// 컨테이너 안으로 진입 (58f은 컨테이너 id의 앞글자 3)
docker exec -it 58f bash

// 환경변수 확인
echo $MYSQL_ROOT_PASSWORD # MYSQL_ROOT_PASSWORD

툴에서 포트번호 3307로 컨테이너의 DB에 접속이 가능하다

docker exec -it 81a bash
bash-5.1# mysql -u root -p    → 비번 입력

create database mydb;
show Databases;

이렇게 만든 다음 컨테이너를 지우면 사라진다.


볼륨을 가진 컨테이너 만들기

호스트 컴퓨터에 저장할 빈 폴더를 만들고 경로(D:\Temp\Volume) + :/var/lib/mysql 를 넣어준다.

docker run -d --name mysql -p 3307:3306 -e MYSQL_ROOT_PASSWORD=1007 -v "D:\Temp:/var/lib/mysql" mysql

docker exec -it [컨테이너 ID 3글자] bash
bash-5.1# mysql -u root -p

연결만 끝났는데도 빈폴더에 많은 파일들이 자동으로 생겼다.


이미지 만들기

// 현재 디렉토리를 나타내는 `.`까지 넣어주기
docker build -t my-jdk-server .

잘 되니까 원하는 설정대로 해보자

FROM eclipse-temurin:17-jdk
ENTRYPOINT ["/bin/bash", "-c", "sleep 500"]


Dockerfile이란?

Docker 이미지는 Docker Hub에서 다운로드하여 사용할 수 있다.
이 Docker 이미지들 역시 누군가 Dockerfile을 사용하여 만들고 Docker Hub에 업로드한 것이다.

나만의 Docker 이미지를 만들고 싶을 때 Dockerfile을 활용한다.
예를 들어, 직접 개발한 Spring Boot 프로젝트를 Docker 이미지로 만들고 싶을 수 있다.
이 경우 Dockerfile을 작성하면, 내 프로젝트 자체를 기반으로 한 이미지를 생성할 수 있다.

Dockerfile은 Docker 이미지를 생성하기 위한 설정 파일이다.


Dockerfile 문법

Dockerfile에서 사용하는 주요 명령어는 다음과 같다.

지시어설명예시
FROM베이스 이미지를 지정한다FROM node:20-alpine
WORKDIR컨테이너 내부에서 작업할 디렉터리를 지정한다WORKDIR /app
COPY호스트의 파일을 컨테이너 이미지 내부로 복사한다COPY . .
RUN빌드 과정에서 실행할 명령을 지정한다RUN npm install
CMD컨테이너 시작 시 기본으로 실행될 명령을 지정한다CMD ["npm", "start"]
EXPOSE컨테이너가 사용하는 포트를 정의한다EXPOSE 3000

그중 FROM 명령어는 베이스 이미지를 지정하여, 해당 환경을 기반으로 추가적인 설정을 진행할 수 있게 해준다.


Spring Boot JAR 배포용 Dockerfile

Dockerfile을 활용하면 직접 만든 Spring Boot 애플리케이션을 독립적인 실행 환경으로 구성할 수 있다. 이를 통해 운영 환경에서 실행 오류를 줄이고, 재현 가능한 배포 환경을 손쉽게 만들 수 있다.

Spring Boot 프로젝트를 Docker로 배포하려면 아래와 같은 구조를 가진다.

spring-boot-app/
├── Dockerfile
└── build/libs/app.jar

스프링 프로젝트를 Docker로 올려보기

  1. Spring Boot 프로젝트를 생성한다.
  2. src/main/resources/static/index.html 파일을 만들고
    Hello World 출력 코드를 작성한다.
  3. 프로젝트 루트 경로에 Dockerfile을 생성하고 아래 내용을 작성한다.
FROM eclipse-temurin:17-jdk
WORKDIR /app
COPY build/libs/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

  1. JAR 파일 빌드
./gradlew clean build -x test
  1. Docker에서 이미지 생성
docker build -t spring-docker-app .
  1. 기존 컨테이너가 있다면 중지 및 삭제
docker stop spring-docker-app
docker rm spring-docker-app
  1. Docker 컨테이너 실행 및 포트 매핑
    현재 로컬 PC에서 Oracle이 8080 포트를 사용 중이므로,
    컨테이너의 8080 포트를 호스트의 8090 포트로 매핑하여 접속한다.
docker run -d -p 8090:8080 --name spring-docker-app spring-docker-app

웹 브라우저에서 접속 테스트:

http://localhost:8090

profile
백엔드 개발자의 노트

0개의 댓글