본문 바로가기
Docker

Docker 5회차 : 이미지 사용 전략 (pull, tag, inspect, history)

by 마틴블레이크 2026. 1. 1.
반응형

Docker 5회차 : 이미지 사용 전략 (pull, tag, inspect, history)

Docker를 실무에서 쓰기 시작하면 컨테이너보다 더 자주 마주치는 문제가 있습니다. 바로 “같은 Dockerfile인데 왜 오늘은 다르게 동작하지?” 같은 재현 불가능한 변화입니다. 이 문제의 출발점은 종종 이미지 태그(tag)에 있습니다. 특히 latest는 편해 보이지만, 팀 개발/운영 환경에서는 불안정성의 원인이 되기 쉽습니다.

이번 5회차에서는 pull, tag, inspect, history를 중심으로 이미지 사용 전략을 정리합니다. 초보자도 이해할 수 있도록 “태그가 정확히 무엇인지”, “inspect/history로 어떤 근거를 확인하는지”, “내 프로젝트에서 어떤 규칙으로 버전을 고정할지”까지 실습과 함께 안내합니다.

목차

핵심 포인트

  • 태그(tag)는 “이 이미지의 별명”에 가깝고, 같은 태그가 다른 이미지를 가리키도록 바뀔 수 있습니다.
  • latest는 “최신 안정 버전”을 보장하지 않으며, 시간이 지나면 내용이 바뀌는 태그일 가능성이 큽니다.
  • inspect는 “이 이미지가 무엇인지(설정/환경/포트/엔트리포인트/다이제스트)”를 근거로 확인하게 해줍니다.
  • history는 “이 이미지가 어떤 레이어로 만들어졌는지(대략의 빌드 과정)”를 보여줍니다.
  • 운영/팀 프로젝트에서는 “버전 고정 규칙”을 문서로 남겨 항상 같은 결과를 만들도록 관리하는 것이 핵심입니다.

핵심 개념: 이미지 태그 의미와 latest 위험성

초보자 관점에서 이미지는 “nginx 같은 이름”으로 보이지만, 실제로는 다음처럼 여러 층위가 있습니다.

  • 이미지 이름: 예) nginx, redis, python
  • 태그(tag): 예) 1.25-alpine, 3.12-slim, alpine, latest
  • 다이제스트(digest): 예) sha256:... 형태의 “내용 기반 고유 식별자”

여기서 가장 중요한 사실은 이것입니다.

  • 태그는 바뀔 수 있다: 동일한 nginx:alpine라도 어느 날 다른 이미지로 갱신될 수 있습니다.
  • 다이제스트는 내용이 같으면 고정: 운영에서 “완전 동일한 이미지”를 보장하고 싶으면 다이제스트 고정이 가장 강력합니다.

latest가 위험해지는 이유도 여기에 있습니다. 팀원이 오늘 빌드한 FROM nginx:latest와, 내일 CI가 빌드한 FROM nginx:latest다른 이미지를 가져오면, 버그/성능/취약점/호환성 이슈가 갑자기 생길 수 있습니다. “원인 없이 바뀐 것처럼 보이는 문제”는 운영에서 가장 비용이 큽니다.

이미지 가져오기와 별칭 만들기: pull, tag

이미지 전략을 이해하려면 pulltag를 정확히 구분해야 합니다.

  • docker pull: 레지스트리에서 이미지를 “다운로드”합니다.
  • docker tag: 로컬에 있는 이미지에 “새 별명(태그)”을 붙입니다(실제 이미지 내용이 바뀌는 것이 아닙니다).
# 1) 이미지 다운로드
docker pull nginx:alpine
docker pull nginx:1.25-alpine

# 2) 로컬 이미지에 별칭 붙이기(내용은 동일, 이름만 추가)
docker tag nginx:1.25-alpine myteam/nginx:prod-1.25-alpine

# 3) 로컬 이미지 목록 확인
docker images | head

실무에서는 “운영에서 쓰는 태그”를 별도로 두는 팀도 많습니다. 예를 들어, 내부적으로 검증된 이미지를 myteam/nginx:prod 같은 태그로 고정해두고, 배포 파이프라인은 그 태그만 사용하게 하는 방식입니다. 다만 이 경우에도 “prod 태그가 언제 어떤 이미지로 갱신되는지” 기록이 없으면 결국 같은 문제가 반복될 수 있으니, 아래에서 다룰 “버전 고정 규칙”과 함께 운영하시는 것을 권장합니다.

inspect로 이미지 메타데이터 확인하기

inspect는 “이미지가 실제로 어떤 설정을 갖고 있는지”를 근거로 확인할 수 있는 명령입니다. 초보자에게 특히 유용한 포인트는 다음과 같습니다.

  • RepoTags/RepoDigests: 이 이미지가 어떤 태그/다이제스트로 식별되는지
  • Config.Env: 기본 환경변수
  • Config.Entrypoint / Cmd: 컨테이너가 시작될 때 실행되는 기본 명령
  • Config.ExposedPorts: 이미지가 노출하는 포트(참고용)
  • Architecture / Os: 실행 환경(특히 ARM/AMD 혼용 시 중요)
# 전체 메타데이터(출력이 길 수 있음)
docker image inspect nginx:alpine

# 필요한 항목만 뽑아서 보기(필요한 경우에만 쓰시면 됩니다)
docker image inspect --format '{{.Id}}' nginx:alpine
docker image inspect --format '{{json .RepoDigests}}' nginx:alpine
docker image inspect --format '{{json .Config.Entrypoint}}' nginx:alpine
docker image inspect --format '{{json .Config.Cmd}}' nginx:alpine

운영 관점에서 inspect는 “추측이 아니라 근거 기반으로 확인”하게 해줍니다. 예를 들어 “왜 컨테이너가 바로 꺼졌지?” 같은 상황은 종종 엔트리포인트/명령(Cmd) 설정에서 힌트를 얻습니다.

history로 레이어 구조 맛보기

history는 이미지를 구성하는 레이어의 대략적인 목록을 보여줍니다. 레이어는 “이미지 제작 과정에서 쌓이는 변경 사항”이라고 생각하시면 됩니다. 초보 단계에서는 다음 정도만 이해하셔도 충분합니다.

  • 이미지는 여러 레이어로 구성됩니다.
  • 레이어는 캐시와 용량에 영향을 줍니다.
  • 어떤 명령으로 레이어가 만들어졌는지(대략) 확인할 수 있습니다.
# 레이어 목록 확인
docker image history nginx:alpine

# 보기 좋게(중간 단계 생략 없이)
docker image history --no-trunc nginx:alpine

레이어를 깊게 다루는 것은 빌드 최적화 단계에서 중요해집니다. 지금은 “이미지는 단일 덩어리가 아니라 내부 구조가 있으며, history로 단서를 얻을 수 있다” 정도로 연결해 두시면 좋습니다.

실습: 동일 이미지 다른 태그로 실행 비교 + 이미지 메타데이터 확인

이번 실습의 목표는 다음 3가지입니다.

  • 같은 이미지 이름이라도 태그가 다르면 “다른 이미지”일 수 있음을 확인합니다.
  • inspect로 “태그 뒤에 실제로 무엇이 있는지”를 근거로 확인합니다.
  • history로 “대략적인 구조”를 눈으로 확인합니다.

1) 동일 이미지, 다른 태그를 pull

docker pull nginx:alpine
docker pull nginx:1.25-alpine

docker images nginx

여기서 포인트는 “nginx라는 이름은 같지만, 태그가 다르면 이미지 ID가 다를 수 있다”는 점입니다. 이미지 ID가 다르다면 실제로 다른 이미지입니다.

2) 다른 태그로 실행해 보기(동시에 띄워서 비교)

두 컨테이너를 서로 다른 호스트 포트로 띄워 동시에 확인해 보겠습니다.

docker run -d --name nginx-alpine -p 8080:80 nginx:alpine
docker run -d --name nginx-125-alpine -p 8081:80 nginx:1.25-alpine

docker ps

브라우저로 각각 접속해 보시면 됩니다.

  • http://localhost:8080
  • http://localhost:8081

겉으로는 비슷해 보일 수 있지만, 운영 관점에서는 “실제 내부 버전/구성/취약점 상태”가 중요한 차이가 됩니다. 그래서 다음 단계가 필요합니다.

3) 컨테이너 내부에서 버전/환경 확인(간단 비교)

컨테이너 내부로 들어가 Nginx 버전을 확인해 봅니다(이미지에 따라 출력 형태가 다를 수 있습니다).

docker exec -it nginx-alpine sh -c "nginx -v || true; cat /etc/os-release 2>/dev/null | head -n 5 || true"
docker exec -it nginx-125-alpine sh -c "nginx -v || true; cat /etc/os-release 2>/dev/null | head -n 5 || true"

여기서 핵심은 “태그로 기대한 버전이 실제로 맞는지”를 확인하는 습관입니다. 운영에서 문제를 줄이려면, 기대와 실제의 차이를 “명령 한두 번”으로 확인할 수 있어야 합니다.

4) inspect로 메타데이터(근거) 확인

이제 이미지 자체를 근거로 확인합니다. 특히 다이제스트를 보면 “내가 지금 받아온 이미지가 정확히 무엇인지”를 추적하기 쉬워집니다.

docker image inspect --format 'ID={{.Id}}' nginx:alpine
docker image inspect --format 'ID={{.Id}}' nginx:1.25-alpine

docker image inspect --format 'RepoDigests={{json .RepoDigests}}' nginx:alpine
docker image inspect --format 'RepoDigests={{json .RepoDigests}}' nginx:1.25-alpine

운영에서 “이미지가 바뀌었다”를 증명하거나 추적할 때는 태그보다 이런 근거(특히 다이제스트)가 훨씬 도움이 됩니다.

5) history로 구조 확인

docker image history nginx:alpine | head
docker image history nginx:1.25-alpine | head

지금은 “레이어가 있다”는 사실을 시각적으로 확인하는 것이 목표입니다. 추후 빌드 최적화 단계에서는 이 레이어 구조가 캐시/용량/빌드 시간에 직결됩니다.

6) 실습 정리(중지/삭제)

docker stop nginx-alpine nginx-125-alpine
docker rm nginx-alpine nginx-125-alpine

산출물: 내 프로젝트용 “이미지 버전 고정 규칙” 가이드

아래 가이드는 “팀/프로젝트에서 실제로 문서로 남겨두면 좋은 수준”으로 구성했습니다. 바로 복사해 프로젝트 위키/README에 붙여 넣고, 팀 규칙으로 사용하셔도 됩니다.

1) 목적

  • 빌드/배포 결과를 항상 재현 가능하게 만든다.
  • 이미지 업데이트는 의도적으로 수행하고, 변경 근거를 남긴다.
  • 운영 장애(갑작스러운 호환성 변화)를 줄인다.

2) 기본 원칙(한 줄 요약)

  • 금지: 운영/CI에서 latest 사용
  • 권장: 명시적 버전 태그 사용(가능하면 minor까지) + 변경 시 PR로 관리
  • 강력 권장: 핵심 서비스는 다이제스트 고정까지 고려

3) 허용/금지 규칙 표(프로젝트 표준)

구분 예시 허용 이유/비고
latest 태그 nginx:latest 금지 내용이 바뀔 수 있어 재현성이 깨질 수 있습니다.
움직이는 태그(일반적) nginx:alpine, python:3-slim 조건부 개발/학습은 가능하나, 운영은 가급적 더 고정된 버전을 권장합니다.
명시적 버전 태그 nginx:1.25-alpine 권장 예상 가능하며, 업데이트를 의도적으로 수행할 수 있습니다.
다이제스트 고정 nginx@sha256:YOUR_DIGEST 강력 권장 완전 동일 이미지 보장. 보안/규제/중요 서비스에 특히 유리합니다.

4) 적용 위치별 규칙(Dockerfile, Compose) 예시

아래 예시는 “무엇을 고정해야 하는지” 감을 잡기 위한 샘플입니다.

# Dockerfile (권장: latest 금지, 명시적 버전 태그 사용)
FROM nginx:1.25-alpine

# (선택) 더 강하게 고정하고 싶다면 다이제스트 방식도 고려
# FROM nginx@sha256:YOUR_DIGEST
# docker-compose.yml (권장: 서비스별 이미지 버전 명시)
services:
  web:
    image: nginx:1.25-alpine
    ports:
      - "8080:80"

5) 변경 관리(업데이트) 정책

  • 업데이트는 PR로만 진행: 이미지 태그 변경은 코드 변경과 동일하게 리뷰 대상입니다.
  • 릴리스 노트/변경 근거 기록: “왜 올렸는지(보안/버그/기능)”를 짧게 남깁니다.
  • 정기 업데이트 창구: 월 1회 또는 분기 1회 등 “계획된 업데이트 시간”을 만들어 예측 가능성을 높입니다.
  • 검증 절차: 변경 후 최소한의 스모크 테스트(컨테이너 실행, 헬스체크, 핵심 API 호출)를 자동화합니다.

6) PR 체크리스트(그대로 붙여 쓰기)

  • 이미지에 latest가 포함되어 있지 않다.
  • 태그 변경 시 변경 이유(보안/버그/기능)가 PR에 기록되어 있다.
  • 필요하면 docker image inspect로 다이제스트/엔트리포인트/기본 포트를 확인했다.
  • 배포 전후 주요 동작(접속/로그/헬스체크)을 확인했다.

추가로 생각해볼 점

  • 버전 고정은 “안전”과 “업데이트”의 균형입니다. 너무 오래 고정하면 보안 패치가 늦어질 수 있으므로, “고정 + 정기 업데이트” 조합이 현실적인 해법입니다.
  • 태그 전략은 팀 합의가 중요합니다. 개인이 임의로 올리기 쉬운 영역이므로, 문서화된 규칙(금지/허용/검증)이 운영 비용을 크게 줄입니다.
  • 다이제스트 고정은 강력하지만 운영 난이도도 증가할 수 있습니다. 중요한 서비스부터 단계적으로 적용하는 방식을 권장합니다.

 

이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

반응형