⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

Docker 이미지와 컨테이너 개념 완벽 가이드 - 슬라이드 1/7
A

AI Generated

2025. 11. 26. · 2 Views

Docker 이미지와 컨테이너 개념 완벽 가이드

Docker의 핵심인 이미지와 컨테이너의 차이점부터 Docker Hub 활용, 이미지 레이어 구조, 생명주기 관리까지 초급 개발자를 위해 쉽게 설명합니다. 실무에서 바로 활용할 수 있는 필수 Docker 지식을 담았습니다.


목차

  1. 이미지와 컨테이너의 차이
  2. Docker Hub 이해하기
  3. 이미지 레이어 구조
  4. 이미지 pull과 push
  5. 컨테이너 생명주기
  6. 이미지 태그 관리

1. 이미지와 컨테이너의 차이

입사 첫 주, 김개발 씨는 선배에게 "Docker로 개발 환경 세팅해 놓았으니까 이미지 받아서 컨테이너 띄우면 돼요"라는 말을 들었습니다. 고개를 끄덕이긴 했지만, 솔직히 이미지와 컨테이너가 뭐가 다른지 헷갈렸습니다.

이미지는 애플리케이션을 실행하는 데 필요한 모든 것을 담은 읽기 전용 템플릿입니다. 마치 붕어빵 틀과 같습니다.

컨테이너는 그 이미지를 바탕으로 실제로 실행되는 인스턴스입니다. 붕어빵 틀에서 찍어낸 실제 붕어빵이라고 생각하면 됩니다.

다음 코드를 살펴봅시다.

# 이미지 목록 확인
docker images

# 이미지로부터 컨테이너 생성 및 실행
docker run -d --name my-app nginx:latest

# 실행 중인 컨테이너 확인
docker ps

# 하나의 이미지로 여러 컨테이너 생성 가능
docker run -d --name my-app-1 nginx:latest
docker run -d --name my-app-2 nginx:latest
docker run -d --name my-app-3 nginx:latest

김개발 씨는 입사 첫 주부터 Docker라는 단어를 수없이 들었습니다. 회의 시간마다 "컨테이너로 배포하면 되죠", "이미지 새로 빌드했어요"라는 대화가 오갔습니다.

처음에는 대충 알아듣는 척했지만, 어느 날 직접 환경을 세팅해야 하는 상황이 되자 막막해졌습니다. 선배 박시니어 씨가 김개발 씨의 모니터를 보더니 물었습니다.

"이미지랑 컨테이너 차이 알아요?" 김개발 씨가 머뭇거리자, 박시니어 씨는 빙긋 웃으며 설명을 시작했습니다. "쉽게 생각해요.

이미지는 붕어빵 틀이에요." 붕어빵 틀에는 붕어빵의 모양, 크기, 무늬가 다 정해져 있습니다. 하지만 틀 자체는 먹을 수 없습니다.

이 틀에 반죽을 넣고 구워야 비로소 먹을 수 있는 붕어빵이 나옵니다. Docker에서 이미지가 바로 이 붕어빵 틀입니다.

운영체제, 라이브러리, 애플리케이션 코드 등 실행에 필요한 모든 것이 담겨 있지만, 그 자체로는 실행되지 않습니다. 컨테이너는 그 틀에서 찍어낸 실제 붕어빵입니다.

이미지를 기반으로 메모리에 올라가 실제로 동작하는 프로세스입니다. 중요한 점은 하나의 틀에서 여러 개의 붕어빵을 찍어낼 수 있듯이, 하나의 이미지로 여러 개의 컨테이너를 만들 수 있다는 것입니다.

이미지가 없던 시절에는 어땠을까요? 개발자들은 새 서버를 세팅할 때마다 운영체제 설치, 라이브러리 설치, 환경 변수 설정을 일일이 손으로 해야 했습니다.

"제 컴퓨터에서는 되는데요"라는 악명 높은 문제가 끊이지 않았습니다. 개발 환경과 운영 환경이 미묘하게 달라서 생기는 버그는 찾기도 어려웠습니다.

Docker 이미지는 이 문제를 깔끔하게 해결했습니다. 개발자가 만든 환경 그대로를 이미지에 담아두면, 어디서든 똑같은 환경을 재현할 수 있습니다.

개발 서버, 테스트 서버, 운영 서버 모두 동일한 이미지를 사용하니 환경 차이로 인한 문제가 사라집니다. 위의 코드를 살펴보면, docker images 명령어로 현재 시스템에 있는 이미지 목록을 확인할 수 있습니다.

docker run 명령어는 이미지를 기반으로 컨테이너를 생성하고 실행합니다. -d 옵션은 백그라운드 실행, --name은 컨테이너에 이름을 붙이는 옵션입니다.

실무에서는 하나의 웹 서버 이미지로 여러 컨테이너를 띄워 부하를 분산시킵니다. 트래픽이 몰리면 컨테이너를 더 만들고, 한가해지면 줄입니다.

이것이 바로 컨테이너 기반 아키텍처의 유연함입니다. 주의할 점이 있습니다.

컨테이너 안에서 파일을 수정해도 원본 이미지는 변하지 않습니다. 컨테이너를 삭제하면 그 안에서 변경한 내용도 함께 사라집니다.

영구적으로 보관해야 하는 데이터는 별도의 볼륨을 사용해야 합니다. 박시니어 씨의 설명을 들은 김개발 씨는 고개를 끄덕였습니다.

"아, 그러니까 이미지는 설계도고 컨테이너는 그 설계도로 만든 실제 제품이군요!" 정확히 그렇습니다. 이 차이를 이해하면 Docker의 나머지 개념들도 훨씬 쉽게 다가옵니다.

실전 팁

💡 - 이미지는 불변(immutable)이고, 컨테이너는 변경 가능하지만 일시적입니다

  • docker ps -a로 중지된 컨테이너까지 모두 확인할 수 있습니다
  • 컨테이너 안의 중요한 데이터는 반드시 볼륨으로 관리하세요

2. Docker Hub 이해하기

김개발 씨는 nginx 이미지를 어디서 가져오는지 궁금해졌습니다. 분명 자신의 컴퓨터에는 nginx를 설치한 적이 없는데, docker run 명령어 하나로 nginx가 실행되었기 때문입니다.

Docker Hub는 Docker 이미지를 저장하고 공유하는 클라우드 기반 저장소입니다. 마치 앱스토어에서 앱을 다운로드하듯이, Docker Hub에서 필요한 이미지를 내려받을 수 있습니다.

공식 이미지부터 개인이 만든 커스텀 이미지까지 수백만 개의 이미지가 등록되어 있습니다.

다음 코드를 살펴봅시다.

# Docker Hub에서 이미지 검색
docker search python

# Docker Hub에서 이미지 다운로드
docker pull python:3.11

# 공식 이미지 다운로드 (라이브러리 이미지)
docker pull redis:latest
docker pull mysql:8.0

# Docker Hub 로그인 (이미지 업로드 시 필요)
docker login

# 내 이미지를 Docker Hub에 업로드
docker push myusername/my-app:1.0

김개발 씨는 신기했습니다. docker run nginx 명령어 하나만 입력했을 뿐인데, 어디선가 nginx 이미지가 다운로드되어 컨테이너가 실행되었습니다.

마치 마법 같았습니다. "그 이미지, 어디서 온 거예요?" 김개발 씨가 물었습니다.

박시니어 씨가 답했습니다. "Docker Hub에서 온 거예요.

Docker 세계의 앱스토어라고 생각하면 돼요." Docker Hub는 인터넷에 있는 거대한 이미지 창고입니다. 스마트폰에서 앱스토어를 열어 필요한 앱을 다운로드하듯이, 개발자들은 Docker Hub에서 필요한 이미지를 내려받습니다.

nginx, python, mysql, redis 같은 유명한 소프트웨어들의 공식 이미지가 모두 여기에 있습니다. 공식 이미지는 특별합니다.

Docker에서 직접 검증하고 관리하는 이미지들입니다. 이 이미지들은 보안 업데이트도 빠르고, 문서화도 잘 되어 있습니다.

이미지 이름 앞에 사용자명이 없으면 공식 이미지입니다. 예를 들어 nginx는 공식 이미지이고, johnsmith/nginx는 johnsmith라는 사용자가 만든 커스텀 이미지입니다.

Docker Hub가 없던 시절을 상상해 봅시다. 개발자마다 MySQL 이미지를 직접 만들어야 했을 것입니다.

누군가는 Ubuntu 기반으로, 누군가는 Alpine 기반으로, 각자 다른 방식으로 만들었을 것입니다. 통일된 기준도 없고, 보안 검증도 제각각이었을 것입니다.

Docker Hub 덕분에 개발자들은 바퀴를 다시 발명할 필요가 없어졌습니다. 검증된 공식 이미지를 기반으로 자신만의 애플리케이션을 올리면 됩니다.

또한 자신이 만든 이미지를 Docker Hub에 올려서 팀원들과 공유할 수도 있습니다. 위의 코드에서 docker search 명령어는 Docker Hub에서 이미지를 검색합니다.

docker pull은 이미지를 내려받고, docker push는 이미지를 업로드합니다. 업로드하려면 먼저 docker login으로 로그인해야 합니다.

실무에서는 회사 전용 이미지 저장소를 따로 운영하는 경우가 많습니다. AWS ECR, Google GCR, 사내 Harbor 같은 프라이빗 레지스트리를 사용합니다.

하지만 동작 원리는 Docker Hub와 동일합니다. 주의할 점도 있습니다.

Docker Hub에는 누구나 이미지를 올릴 수 있습니다. 검증되지 않은 이미지를 함부로 사용하면 보안 문제가 생길 수 있습니다.

가급적 공식 이미지를 사용하고, 커스텀 이미지를 쓸 때는 Dockerfile을 꼭 확인하세요. 김개발 씨는 Docker Hub 웹사이트에 접속해 보았습니다.

정말로 수많은 이미지가 있었고, 각 이미지마다 사용법이 친절하게 설명되어 있었습니다. "이제 어떤 환경이든 금방 세팅할 수 있겠네요!" 김개발 씨의 눈이 반짝였습니다.

실전 팁

💡 - 공식 이미지를 우선적으로 사용하세요. 보안과 안정성이 보장됩니다

  • docker pull 없이 docker run만 해도 이미지가 없으면 자동으로 다운로드됩니다
  • 회사 프로젝트라면 프라이빗 레지스트리 사용을 고려하세요

3. 이미지 레이어 구조

어느 날 김개발 씨는 이상한 현상을 발견했습니다. 500MB짜리 이미지를 두 개 다운로드했는데, 디스크 용량은 500MB밖에 늘지 않았습니다.

버그인가 싶어 다시 확인해도 마찬가지였습니다.

Docker 이미지는 여러 개의 레이어가 겹쳐진 구조입니다. 마치 투명 필름을 여러 장 겹쳐 하나의 그림을 만드는 것과 같습니다.

각 레이어는 읽기 전용이며, 동일한 레이어는 여러 이미지가 공유합니다. 이 덕분에 저장 공간을 효율적으로 사용할 수 있습니다.

다음 코드를 살펴봅시다.

# 이미지의 레이어 구조 확인
docker history nginx:latest

# 출력 예시:
# IMAGE          CREATED       SIZE    COMMENT
# a8758716bb6a   2 weeks ago   187MB   nginx base layer
# <missing>      2 weeks ago   0B      configuration
# <missing>      2 weeks ago   1.2MB   add nginx user

# Dockerfile에서 각 명령어가 레이어가 됨
# FROM ubuntu:22.04        <- 레이어 1
# RUN apt-get update       <- 레이어 2
# RUN apt-get install vim  <- 레이어 3
# COPY app.py /app/        <- 레이어 4

김개발 씨는 고개를 갸웃거렸습니다. 분명 python:3.11 이미지와 python:3.10 이미지를 둘 다 받았는데, 용량이 예상보다 훨씬 적었습니다.

혹시 다운로드가 덜 된 건 아닐까요? 박시니어 씨가 웃으며 설명했습니다.

"그게 바로 레이어의 마법이에요." Docker 이미지를 양파에 비유해 봅시다. 양파를 자르면 여러 겹의 층이 나옵니다.

Docker 이미지도 마찬가지로 여러 개의 레이어가 겹쳐져 있습니다. 맨 아래에는 운영체제 레이어가 있고, 그 위에 라이브러리 레이어, 애플리케이션 레이어가 차곡차곡 쌓입니다.

이 구조의 핵심은 공유입니다. python:3.11과 python:3.10은 서로 다른 이미지지만, 기반이 되는 운영체제 레이어는 동일합니다.

Docker는 똑똒한 레이어를 두 번 저장하지 않습니다. 한 번만 저장하고 두 이미지가 함께 사용합니다.

Dockerfile을 작성할 때 이 원리를 알면 큰 도움이 됩니다. Dockerfile의 각 명령어(FROM, RUN, COPY 등)는 하나의 레이어를 만듭니다.

명령어 순서를 잘 배치하면 빌드 시간을 크게 줄일 수 있습니다. 예를 들어봅시다.

애플리케이션 코드는 자주 바뀌지만, 라이브러리 설치는 가끔 바뀝니다. 만약 라이브러리 설치를 먼저 하고 코드 복사를 나중에 하면, 코드가 바뀌어도 라이브러리 레이어는 캐시에서 재사용됩니다.

반대로 코드 복사를 먼저 하면, 코드가 바뀔 때마다 라이브러리도 다시 설치해야 합니다. docker history 명령어로 이미지의 레이어 구조를 확인할 수 있습니다.

각 레이어의 크기와 생성 시점이 표시됩니다. 이 정보를 보면 이미지가 어떻게 구성되어 있는지 한눈에 파악할 수 있습니다.

레이어는 모두 읽기 전용입니다. 컨테이너가 실행되면 그 위에 얇은 쓰기 가능 레이어가 하나 추가됩니다.

컨테이너 안에서 파일을 수정하면 이 쓰기 레이어에만 기록됩니다. 원본 이미지 레이어는 절대 변하지 않습니다.

이것이 하나의 이미지로 여러 컨테이너를 안전하게 실행할 수 있는 비결입니다. 주의할 점이 있습니다.

레이어가 너무 많으면 이미지 크기가 커지고 성능이 떨어집니다. RUN 명령어를 여러 개 나눠 쓰기보다 &&로 연결해서 하나의 레이어로 만드는 것이 좋습니다.

김개발 씨는 이해가 됐습니다. "그래서 큰 이미지도 처음 한 번만 오래 걸리고, 그다음부터는 금방 받아지는 거군요!" 맞습니다.

이미 가지고 있는 레이어는 다시 받지 않으니까요.

실전 팁

💡 - Dockerfile에서 자주 바뀌는 명령어는 아래쪽에 배치하세요

  • RUN 명령어는 &&로 연결해서 레이어 수를 줄이세요
  • docker history로 이미지 구조를 분석하는 습관을 들이세요

4. 이미지 pull과 push

드디어 김개발 씨가 직접 만든 애플리케이션을 이미지로 만들었습니다. 이제 이 이미지를 팀원들과 공유해야 하는데, USB에 담아서 전달해야 할까요?

pull은 원격 저장소에서 이미지를 내려받는 명령어이고, push는 로컬 이미지를 원격 저장소에 올리는 명령어입니다. Git에서 코드를 pull하고 push하는 것과 동일한 개념입니다.

이 두 명령어로 팀 간 이미지 공유가 간편해집니다.

다음 코드를 살펴봅시다.

# 이미지 다운로드 (pull)
docker pull ubuntu:22.04

# 특정 아키텍처 이미지 다운로드
docker pull --platform linux/amd64 nginx:latest

# 이미지에 태그 붙이기 (push 전 필수)
docker tag my-app:latest myusername/my-app:1.0

# 이미지 업로드 (push)
docker push myusername/my-app:1.0

# 프라이빗 레지스트리에 push
docker tag my-app:latest registry.company.com/my-app:1.0
docker push registry.company.com/my-app:1.0

김개발 씨는 드디어 첫 번째 Docker 이미지를 만들었습니다. 회사의 API 서버를 이미지로 패키징한 것입니다.

뿌듯한 마음에 팀 채팅방에 올리려는데, 이미지 파일 크기가 500MB였습니다. 메신저로는 보낼 수 없는 크기였습니다.

"그냥 Docker Hub에 올리면 되지 않아요?" 박시니어 씨가 힌트를 주었습니다. Git으로 코드를 GitHub에 올리듯이, Docker 이미지도 Docker Hub에 올릴 수 있습니다.

pullpush는 Docker의 핵심 명령어입니다. 마치 택배 시스템과 같습니다.

pull은 택배를 받는 것이고, push는 택배를 보내는 것입니다. 택배 회사(Docker Hub)가 중간에서 이미지를 보관하고 전달해 줍니다.

pull은 간단합니다. docker pull 이미지명만 입력하면 됩니다.

태그를 지정하지 않으면 자동으로 latest 태그가 붙습니다. 하지만 운영 환경에서는 latest 대신 구체적인 버전 태그를 사용하는 것이 좋습니다.

latest는 언제든 바뀔 수 있어서 예측이 어렵기 때문입니다. push는 조금 더 단계가 필요합니다.

먼저 docker login으로 Docker Hub에 로그인해야 합니다. 그다음 이미지에 적절한 태그를 붙여야 합니다.

태그 형식은 사용자명/이미지명:버전입니다. myusername/my-app:1.0처럼 말입니다.

회사에서는 보통 프라이빗 레지스트리를 사용합니다. 회사 코드가 담긴 이미지를 공개 저장소에 올릴 수는 없으니까요.

AWS ECR, Google GCR, GitHub Container Registry 같은 서비스를 많이 사용합니다. 사용법은 Docker Hub와 거의 같고, 레지스트리 주소만 다릅니다.

CI/CD 파이프라인에서 pull과 push는 핵심 역할을 합니다. 개발자가 코드를 푸시하면 CI 서버가 자동으로 이미지를 빌드하고 레지스트리에 push합니다.

배포 서버는 새 이미지를 pull해서 컨테이너를 교체합니다. 이 과정이 자동화되면 배포가 훨씬 빠르고 안정적입니다.

주의할 점이 있습니다. push 전에 반드시 올바른 태그를 확인하세요.

실수로 latest 태그에 개발 중인 이미지를 올리면 운영 서버에 영향을 줄 수 있습니다. 또한 .dockerignore 파일로 민감한 정보가 이미지에 포함되지 않도록 주의해야 합니다.

김개발 씨는 docker push 명령어로 이미지를 올렸습니다. 몇 분 후, 팀원들은 docker pull 한 줄로 같은 환경을 구축할 수 있었습니다.

"USB 필요 없었네요!" 김개발 씨가 웃었습니다.

실전 팁

💡 - 운영 환경에서는 latest 태그 대신 구체적인 버전 태그를 사용하세요

  • push 전에 docker images로 태그가 올바른지 확인하세요
  • 민감한 정보는 이미지에 포함하지 말고 환경 변수로 주입하세요

5. 컨테이너 생명주기

김개발 씨는 컨테이너를 띄우고 내리기를 반복하다가 문득 궁금해졌습니다. 컨테이너를 stop하면 사라지는 건가요, 아니면 어딘가에 남아 있는 건가요?

restart는 또 뭐가 다른 걸까요?

컨테이너는 **생성(create) - 시작(start) - 실행 중(running) - 일시정지(pause) - 중지(stop) - 삭제(rm)**의 생명주기를 가집니다. 마치 컴퓨터의 전원을 켜고, 절전 모드에 들어갔다가, 종료하고, 포맷하는 것과 비슷합니다.

각 상태를 이해하면 컨테이너를 효율적으로 관리할 수 있습니다.

다음 코드를 살펴봅시다.

# 컨테이너 생성 (실행하지 않음)
docker create --name my-container nginx

# 컨테이너 시작
docker start my-container

# 생성과 시작을 동시에 (가장 많이 사용)
docker run -d --name my-container nginx

# 컨테이너 일시정지
docker pause my-container

# 일시정지 해제
docker unpause my-container

# 컨테이너 중지 (SIGTERM 후 SIGKILL)
docker stop my-container

# 컨테이너 재시작
docker restart my-container

# 컨테이너 삭제 (중지된 컨테이너만 가능)
docker rm my-container

# 강제 삭제 (실행 중이어도 삭제)
docker rm -f my-container

김개발 씨는 실수로 컨테이너를 잘못 설정했습니다. 급하게 docker stop을 실행했는데, 나중에 보니 컨테이너가 목록에 여전히 남아 있었습니다.

삭제된 게 아니었던 겁니다. 대체 stop과 rm은 뭐가 다른 걸까요?

박시니어 씨가 차근차근 설명했습니다. "컨테이너도 사람처럼 생로병사가 있어요.

태어나고, 활동하고, 잠들고, 죽는 거죠." 컨테이너의 생명주기는 크게 다섯 단계입니다. 먼저 create로 컨테이너가 태어납니다.

이 상태에서는 존재하지만 아직 실행되지 않습니다. 마치 컴퓨터를 조립해 놓고 전원을 안 켠 상태입니다.

start를 하면 컨테이너가 실행됩니다. 프로세스가 메모리에 올라가고 CPU를 사용하기 시작합니다.

대부분의 경우 docker run을 사용하는데, 이 명령어는 create와 start를 한 번에 수행합니다. 실행 중인 컨테이너는 pause로 일시정지할 수 있습니다.

모든 프로세스가 얼어붙지만 메모리 상태는 유지됩니다. 컴퓨터의 절전 모드와 비슷합니다.

디버깅할 때 유용하게 쓰입니다. stop은 컨테이너를 중지합니다.

먼저 SIGTERM 신호를 보내 프로세스에게 정상 종료할 기회를 줍니다. 10초 후에도 종료되지 않으면 SIGKILL로 강제 종료합니다.

중지된 컨테이너는 사라지지 않습니다. docker start로 다시 살릴 수 있습니다.

rm은 컨테이너를 완전히 삭제합니다. 중지된 컨테이너만 삭제할 수 있고, 실행 중인 컨테이너는 -f 옵션으로 강제 삭제해야 합니다.

삭제하면 컨테이너 안에 있던 모든 데이터가 사라집니다. 흔히 하는 실수가 있습니다.

컨테이너를 stop만 하고 rm을 안 하면 좀비 컨테이너가 쌓입니다. docker ps -a로 보면 Exited 상태의 컨테이너가 수십 개 남아 있는 경우가 많습니다.

디스크 공간을 차지하니 주기적으로 정리해야 합니다. docker container prune 명령어로 중지된 컨테이너를 한 번에 삭제할 수 있습니다.

운영 환경에서는 컨테이너가 비정상 종료될 때 자동으로 재시작되도록 설정합니다. docker run --restart=always 옵션을 사용하면 됩니다.

서버가 재부팅되어도 컨테이너가 자동으로 다시 뜹니다. 김개발 씨는 이제 이해가 됐습니다.

"stop은 컴퓨터 종료고, rm은 포맷이네요!" 정확한 비유입니다. 중지된 컨테이너는 언제든 다시 켤 수 있지만, 삭제된 컨테이너는 다시 만들어야 합니다.

실전 팁

💡 - docker container prune으로 중지된 컨테이너를 주기적으로 정리하세요

  • 운영 환경에서는 --restart=always 옵션을 고려하세요
  • docker ps -a로 전체 컨테이너 상태를 자주 확인하세요

6. 이미지 태그 관리

김개발 씨가 만든 이미지가 잘 동작해서 운영 서버에 배포했습니다. 그런데 일주일 후, 새 기능을 추가한 이미지를 같은 이름으로 다시 빌드했더니 운영 서버에서 문제가 생겼습니다.

이전 버전으로 돌아가고 싶은데 방법이 없었습니다.

태그는 이미지의 버전을 구분하는 라벨입니다. 같은 이미지 이름이라도 태그가 다르면 다른 버전입니다.

nginx:1.24와 nginx:1.25는 서로 다른 이미지입니다. 태그를 체계적으로 관리하면 버전 롤백, 테스트 환경 분리 등이 수월해집니다.

다음 코드를 살펴봅시다.

# 태그 지정하여 이미지 빌드
docker build -t my-app:1.0.0 .
docker build -t my-app:1.0.1 .
docker build -t my-app:1.1.0 .

# 하나의 이미지에 여러 태그 붙이기
docker tag my-app:1.1.0 my-app:latest
docker tag my-app:1.1.0 my-app:stable

# 태그로 버전 관리 예시
docker tag my-app:1.1.0 myrepo/my-app:1.1.0
docker tag my-app:1.1.0 myrepo/my-app:1.1
docker tag my-app:1.1.0 myrepo/my-app:1

# 특정 버전 이미지 사용
docker run -d myrepo/my-app:1.0.0  # 이전 버전으로 롤백

# 이미지 목록에서 태그 확인
docker images my-app

김개발 씨는 큰 실수를 했습니다. 새 기능을 추가한 이미지를 my-app:latest로 빌드해서 운영 서버에 배포했는데, 치명적인 버그가 있었습니다.

이전 버전으로 돌아가고 싶었지만, 이전 이미지를 latest로 덮어써 버린 후였습니다. 박시니어 씨가 한숨을 쉬며 말했습니다.

"그래서 태그 관리가 중요한 거예요. latest만 쓰면 안 돼요." 태그는 도서관의 청구기호와 같습니다.

같은 책이라도 초판, 2판, 3판이 있듯이, 같은 애플리케이션 이미지도 1.0, 1.1, 2.0 버전이 있을 수 있습니다. 태그가 없으면 어떤 버전인지 구분할 수 없습니다.

Semantic Versioning이라는 버전 명명 규칙이 있습니다. MAJOR.MINOR.PATCH 형식입니다.

1.0.0에서 버그를 고치면 1.0.1, 기능을 추가하면 1.1.0, 큰 변화가 있으면 2.0.0으로 올립니다. Docker 이미지 태그에도 이 규칙을 적용하면 버전 관리가 깔끔해집니다.

실무에서는 하나의 이미지에 여러 태그를 붙이는 경우가 많습니다. 예를 들어 1.2.3 버전 이미지에 my-app:1.2.3, my-app:1.2, my-app:1, my-app:latest 태그를 모두 붙입니다.

정확한 버전이 필요하면 1.2.3을, 마이너 버전까지만 고정하려면 1.2를, 최신 버전을 원하면 latest를 사용합니다. 운영 환경에서는 절대 latest 태그를 사용하면 안 됩니다.

latest는 "가장 최근에 빌드된 이미지"를 의미하는데, 언제 바뀔지 예측할 수 없습니다. 어제는 1.2.3이었는데 오늘은 1.2.4일 수 있습니다.

운영 환경에서는 반드시 구체적인 버전 태그를 사용해야 합니다. 태그를 잘 관리하면 롤백이 쉬워집니다.

1.2.4 버전에 문제가 생기면 docker run my-app:1.2.3 한 줄로 이전 버전으로 돌아갈 수 있습니다. 이전 버전 이미지가 레지스트리에 남아 있기 때문입니다.

주의할 점이 있습니다. 같은 태그에 다른 이미지를 덮어쓰면 이전 이미지는 사라집니다.

docker tag my-app:1.0.0 my-app:latest를 하고, 나중에 docker tag my-app:2.0.0 my-app:latest를 하면, latest 태그는 2.0.0을 가리키게 됩니다. 1.0.0 이미지 자체는 남아 있지만, latest로는 더 이상 접근할 수 없습니다.

김개발 씨는 그날 이후로 태그 규칙을 철저히 지켰습니다. 빌드할 때마다 버전을 올리고, 운영 배포에는 구체적인 버전 태그만 사용했습니다.

덕분에 다시는 롤백 불가능한 상황을 겪지 않았습니다.

실전 팁

💡 - 운영 환경에서는 latest 대신 구체적인 버전 태그를 사용하세요

  • Semantic Versioning(MAJOR.MINOR.PATCH)을 따르면 버전 관리가 쉬워집니다
  • Git 커밋 해시를 태그에 포함시키면 코드 추적이 편리합니다

이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!

#Docker#Container#Image#DockerHub#DevOps#Docker,Container,DevOps

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.