⚠️

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

이미지 로딩 중...

Docker Hub와 레지스트리 완벽 가이드 - 슬라이드 1/7
A

AI Generated

2025. 11. 26. · 17 Views

Docker Hub와 레지스트리 완벽 가이드

Docker 이미지를 저장하고 공유하는 방법을 알아봅니다. Docker Hub 사용법부터 프라이빗 레지스트리 구축, 보안 스캔까지 실무에 필요한 모든 것을 다룹니다.


목차

  1. Docker_Hub_가입과_로그인
  2. 이미지_push와_pull
  3. 자동_빌드_설정
  4. 프라이빗_레지스트리_구축
  5. GitHub_Container_Registry
  6. 이미지_보안_스캔

1. Docker Hub 가입과 로그인

김개발 씨는 드디어 첫 번째 Docker 이미지를 완성했습니다. 로컬에서는 잘 돌아가는데, 이걸 어떻게 팀원들과 공유할 수 있을까요?

USB에 담아서 전달할 수는 없는 노릇입니다. 바로 이때 필요한 것이 Docker Hub입니다.

Docker Hub는 Docker 이미지를 저장하고 공유하는 클라우드 서비스입니다. 마치 GitHub가 소스 코드를 저장하는 곳이라면, Docker Hub는 Docker 이미지를 저장하는 곳입니다.

무료 계정으로도 공개 이미지는 무제한으로, 프라이빗 이미지는 1개까지 저장할 수 있습니다.

다음 코드를 살펴봅시다.

# Docker Hub 계정으로 로그인합니다
docker login

# 사용자명과 비밀번호를 입력하면 로그인 완료
# Username: your-username
# Password: your-password
# Login Succeeded

# 로그인 상태 확인 - 인증 정보가 저장된 위치
cat ~/.docker/config.json

# 로그아웃이 필요할 때
docker logout

# 특정 레지스트리에 로그인할 때
docker login registry.example.com

김개발 씨는 입사한 지 2주 된 신입 개발자입니다. 오늘 처음으로 Docker 이미지를 만들어 봤는데, 선배가 "그거 Hub에 올려둬"라고 말합니다.

Hub가 뭐지? 김개발 씨는 멍한 표정을 지었습니다.

선배 개발자 박시니어 씨가 다가와 설명을 시작합니다. "Docker Hub는 말이야, 쉽게 말해서 이미지 전용 클라우드 저장소야.

네가 GitHub에 코드 올리듯이, Docker 이미지는 Docker Hub에 올리는 거지." 그렇다면 Docker Hub란 정확히 무엇일까요? 쉽게 비유하자면, Docker Hub는 마치 앱스토어와 같습니다.

앱스토어에서 앱을 다운받아 설치하듯이, Docker Hub에서 이미지를 다운받아 컨테이너를 실행합니다. 반대로 내가 만든 앱을 앱스토어에 올리듯이, 내가 만든 이미지를 Docker Hub에 올릴 수도 있습니다.

Docker Hub가 없던 시절에는 어땠을까요? 개발자들은 이미지 파일을 직접 복사해서 전달해야 했습니다.

docker save 명령어로 tar 파일을 만들고, 이메일이나 USB로 전달하고, 받는 쪽에서 docker load로 불러오는 번거로운 과정이 필요했습니다. 서버가 여러 대면 하나하나 복사해야 했고, 버전 관리는 더 큰 문제였습니다.

바로 이런 문제를 해결하기 위해 Docker Hub가 등장했습니다. Docker Hub를 사용하면 인터넷만 연결되어 있으면 어디서든 이미지를 받을 수 있습니다.

버전 관리도 태그를 통해 자동으로 됩니다. 무엇보다 전 세계 개발자들이 만든 수백만 개의 공식 이미지를 무료로 사용할 수 있습니다.

위의 코드를 살펴보겠습니다. docker login 명령어를 실행하면 사용자명과 비밀번호를 물어봅니다.

올바르게 입력하면 "Login Succeeded"라는 메시지가 나타납니다. 이 인증 정보는 ~/.docker/config.json 파일에 저장되어, 다음부터는 자동으로 로그인됩니다.

실제 현업에서는 어떻게 활용할까요? 보통 개발 환경에서는 개인 계정으로 로그인하고, CI/CD 파이프라인에서는 Access Token을 사용합니다.

Docker Hub 웹사이트에서 토큰을 생성하면 비밀번호 대신 토큰으로 로그인할 수 있어 더 안전합니다. 하지만 주의할 점도 있습니다.

초보 개발자들이 흔히 하는 실수 중 하나는 비밀번호를 스크립트에 직접 입력하는 것입니다. 이렇게 하면 보안 문제가 발생할 수 있습니다.

따라서 환경 변수나 Docker의 credential helper를 사용해야 합니다. 다시 김개발 씨의 이야기로 돌아가 봅시다.

박시니어 씨의 설명을 들은 김개발 씨는 바로 hub.docker.com에 접속해서 계정을 만들었습니다. "생각보다 쉽네요!" Docker Hub 계정이 있으면 이미지를 자유롭게 공유할 수 있습니다.

여러분도 지금 바로 계정을 만들어 보세요.

실전 팁

💡 - Access Token을 사용하면 비밀번호보다 안전하고, 필요할 때 즉시 폐기할 수 있습니다

  • 2단계 인증(2FA)을 활성화하면 계정 보안이 한층 강화됩니다

2. 이미지 push와 pull

김개발 씨는 Docker Hub 계정을 만들었습니다. 이제 로컬에서 만든 이미지를 올려볼 차례입니다.

그런데 막상 push 명령어를 실행하니 에러가 발생합니다. "denied: requested access to the resource is denied"라니, 대체 뭐가 문제일까요?

push는 로컬 이미지를 레지스트리에 업로드하는 것이고, pull은 레지스트리에서 이미지를 다운로드하는 것입니다. 마치 Git의 push와 pull과 같은 개념입니다.

단, Docker에서는 이미지 이름에 반드시 사용자명이 포함되어야 push가 가능합니다.

다음 코드를 살펴봅시다.

# 먼저 이미지에 올바른 태그를 붙입니다
# 형식: docker tag 원본이미지 사용자명/저장소명:태그
docker tag my-app:latest kimdev/my-app:1.0.0

# Docker Hub에 이미지 업로드
docker push kimdev/my-app:1.0.0

# 다른 컴퓨터에서 이미지 다운로드
docker pull kimdev/my-app:1.0.0

# 특정 버전 대신 최신 버전 받기
docker pull kimdev/my-app:latest

# 모든 태그 한번에 push
docker push kimdev/my-app --all-tags

김개발 씨가 처음 push를 시도했을 때 에러가 난 이유는 간단합니다. 이미지 이름이 그냥 my-app이었기 때문입니다.

Docker Hub는 "이 이미지가 누구 건지 모르겠는데요?"라고 말한 셈입니다. 박시니어 씨가 옆에서 설명합니다.

"Docker Hub에 올리려면 이미지 이름 앞에 네 사용자명을 붙여야 해. 마치 GitHub 저장소 주소가 github.com/사용자명/저장소명 인 것처럼 말이야." 그렇다면 태깅이란 정확히 무엇일까요?

쉽게 비유하자면, 태깅은 마치 택배 송장을 붙이는 것과 같습니다. 보내는 사람, 받는 사람, 내용물 정보가 없으면 택배가 어디로 가야 할지 모릅니다.

Docker 이미지도 마찬가지로 "어디로 보낼지", "어떤 버전인지" 정보를 태그로 붙여줘야 합니다. 태깅을 제대로 하지 않으면 어떤 문제가 생길까요?

버전 관리가 엉망이 됩니다. 모든 이미지가 latest 태그만 가지고 있다면, 어제 올린 이미지와 오늘 올린 이미지를 구분할 수 없습니다.

운영 서버에서 롤백해야 할 때 이전 버전을 찾을 수 없는 최악의 상황이 발생합니다. 바로 이런 문제를 해결하기 위해 시맨틱 버전을 사용합니다.

1.0.0, 1.0.1, 1.1.0 같은 형식으로 버전을 붙이면 언제든 원하는 버전으로 돌아갈 수 있습니다. major.minor.patch 형식을 따르면 버전만 보고도 어떤 변경이 있었는지 짐작할 수 있습니다.

위의 코드를 단계별로 살펴보겠습니다. 먼저 docker tag 명령어로 기존 이미지에 새로운 이름을 붙입니다.

원본 이미지는 그대로 유지되고, 같은 이미지를 가리키는 새 이름이 추가됩니다. 그다음 docker push로 해당 이미지를 Docker Hub에 업로드합니다.

이미지는 레이어 단위로 전송되므로, 이미 있는 레이어는 건너뛰어 빠르게 전송됩니다. 실제 현업에서는 어떻게 활용할까요?

보통 CI/CD 파이프라인에서 자동으로 태그를 붙입니다. Git 커밋 해시나 빌드 번호를 태그로 사용하면 정확히 어떤 코드로 만든 이미지인지 추적할 수 있습니다.

예를 들어 my-app:abc1234 같은 형식입니다. 하지만 주의할 점도 있습니다.

latest 태그를 맹신하면 안 됩니다. latest는 "최신"이라는 의미가 아니라 그냥 기본 태그일 뿐입니다. 누군가가 실수로 오래된 이미지를 latest로 푸시할 수도 있습니다.

운영 환경에서는 반드시 구체적인 버전 태그를 사용해야 합니다. 다시 김개발 씨의 이야기로 돌아가 봅시다.

이미지 이름을 올바르게 수정한 김개발 씨는 드디어 push에 성공했습니다. Docker Hub 웹사이트에서 자신의 이미지를 확인하니 뿌듯한 기분이 들었습니다.

이제 팀원들은 docker pull kimdev/my-app:1.0.0 한 줄로 김개발 씨의 이미지를 받을 수 있습니다.

실전 팁

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

  • docker push 전에 docker images로 태그가 올바른지 확인하는 습관을 들이세요

3. 자동 빌드 설정

김개발 씨는 매번 코드를 수정할 때마다 docker build, docker push를 반복하고 있습니다. 10번째 반복하던 중 문득 생각이 들었습니다.

"이거 자동화할 수 없나?" 당연히 있습니다. 자동 빌드 기능입니다.

자동 빌드는 GitHub나 Bitbucket 저장소에 코드를 푸시하면 자동으로 Docker 이미지를 빌드하고 레지스트리에 올려주는 기능입니다. 마치 GitHub Actions처럼, 코드가 바뀔 때마다 알아서 이미지가 갱신됩니다.

Docker Hub의 자동 빌드는 유료 기능이지만, GitHub Actions를 활용하면 무료로 구현할 수 있습니다.

다음 코드를 살펴봅시다.

# .github/workflows/docker-build.yml
name: Build and Push Docker Image

on:
  push:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_TOKEN }}

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          push: true
          tags: kimdev/my-app:${{ github.sha }}

김개발 씨는 하루에도 몇 번씩 코드를 수정합니다. 수정할 때마다 docker build, docker tag, docker push를 반복하니 손가락이 아플 지경입니다.

게다가 가끔 push를 깜빡해서 팀원이 옛날 이미지를 받아가는 사고도 났습니다. 박시니어 씨가 웃으며 말합니다.

"CI/CD 파이프라인을 구축하면 그런 고민 끝이야. 코드만 푸시하면 나머지는 자동으로 처리되거든." 그렇다면 자동 빌드란 정확히 무엇일까요?

쉽게 비유하자면, 자동 빌드는 마치 자동 세탁기와 같습니다. 빨래를 넣고 버튼만 누르면 세탁, 헹굼, 탈수가 자동으로 진행됩니다.

자동 빌드도 마찬가지로 코드를 푸시하면 빌드, 테스트, 배포가 자동으로 진행됩니다. 자동 빌드가 없으면 어떤 문제가 생길까요?

가장 큰 문제는 휴먼 에러입니다. 바쁜 와중에 빌드를 깜빡하거나, 잘못된 태그를 붙이거나, 테스트를 건너뛰는 실수가 생깁니다.

또한 여러 사람이 각자 다른 환경에서 빌드하면 "내 컴퓨터에서는 됐는데"라는 클래식한 문제가 발생합니다. 바로 이런 문제를 해결하기 위해 자동 빌드를 설정합니다.

자동 빌드를 사용하면 항상 동일한 환경에서 빌드가 진행됩니다. 코드와 이미지의 버전이 정확히 일치합니다.

무엇보다 개발자는 코드 작성에만 집중할 수 있습니다. 위의 코드를 살펴보겠습니다.

이 파일은 GitHub Actions 워크플로우입니다. main 브랜치에 푸시가 발생하면 자동으로 실행됩니다.

먼저 Docker Hub에 로그인하고, 이미지를 빌드한 후, Git 커밋 해시를 태그로 붙여서 푸시합니다. secrets.DOCKER_USERNAME과 secrets.DOCKER_TOKEN은 GitHub 저장소 설정에서 미리 등록해둬야 합니다.

실제 현업에서는 어떻게 활용할까요? 보통 main 브랜치에는 latest 태그를, 릴리즈 브랜치에는 버전 태그를 붙입니다.

PR이 머지되기 전에 이미지 빌드 테스트를 수행하기도 합니다. 이렇게 하면 빌드가 안 되는 코드가 머지되는 것을 방지할 수 있습니다.

하지만 주의할 점도 있습니다. 시크릿 관리를 철저히 해야 합니다.

Docker Hub 토큰이 노출되면 누구나 여러분의 이미지를 덮어쓸 수 있습니다. 반드시 GitHub Secrets나 비슷한 보안 저장소를 사용하고, 토큰 권한은 최소한으로 설정해야 합니다.

다시 김개발 씨의 이야기로 돌아가 봅시다. 자동 빌드를 설정한 김개발 씨는 이제 git push만 하면 됩니다.

5분 후 Docker Hub에 새 이미지가 올라간 것을 확인하고 감탄했습니다. "세상이 좋아졌네요!" 자동 빌드는 현대 DevOps의 필수 요소입니다.

여러분의 프로젝트에도 꼭 적용해 보세요.

실전 팁

💡 - GitHub Secrets에 토큰을 저장할 때는 write 권한만 있는 제한된 토큰을 사용하세요

  • 빌드 캐시를 활용하면 빌드 시간을 크게 단축할 수 있습니다

4. 프라이빗 레지스트리 구축

김개발 씨의 회사에서 새로운 요구사항이 생겼습니다. "우리 이미지는 외부에 공개하면 안 돼.

사내망에서만 접근 가능해야 해." Docker Hub는 인터넷에 있는데, 어떻게 해야 할까요? 바로 프라이빗 레지스트리를 직접 구축하면 됩니다.

프라이빗 레지스트리는 자체 서버에 Docker 이미지 저장소를 구축하는 것입니다. Docker에서 공식적으로 제공하는 registry 이미지를 사용하면 몇 분 만에 나만의 레지스트리를 만들 수 있습니다.

회사 내부망에서만 접근 가능하게 설정하면 보안을 크게 강화할 수 있습니다.

다음 코드를 살펴봅시다.

# 프라이빗 레지스트리 컨테이너 실행
docker run -d \
  --name registry \
  --restart always \
  -p 5000:5000 \
  -v /data/registry:/var/lib/registry \
  registry:2

# 로컬 이미지에 프라이빗 레지스트리 태그 붙이기
docker tag my-app:latest localhost:5000/my-app:1.0.0

# 프라이빗 레지스트리에 push
docker push localhost:5000/my-app:1.0.0

# 프라이빗 레지스트리에서 pull
docker pull localhost:5000/my-app:1.0.0

# 저장된 이미지 목록 확인
curl http://localhost:5000/v2/_catalog

김개발 씨의 회사는 금융 관련 서비스를 운영합니다. 보안 규정상 소스 코드는 물론 Docker 이미지도 외부 서버에 저장할 수 없습니다.

Docker Hub의 프라이빗 저장소도 결국 외부 서버이기 때문에 사용할 수 없습니다. 박시니어 씨가 해결책을 제시합니다.

"우리가 직접 레지스트리 서버를 운영하면 돼. Docker에서 공식 이미지를 제공하니까 생각보다 쉬워." 그렇다면 프라이빗 레지스트리란 정확히 무엇일까요?

쉽게 비유하자면, Docker Hub가 공용 도서관이라면 프라이빗 레지스트리는 회사 전용 자료실입니다. 아무나 들어올 수 없고, 회사 직원만 자료를 열람하고 보관할 수 있습니다.

중요한 기밀 자료는 당연히 회사 자료실에 보관하는 것이 안전합니다. 프라이빗 레지스트리가 왜 필요할까요?

첫째, 보안입니다. 회사의 비즈니스 로직이 담긴 이미지가 외부에 노출되면 큰 문제가 됩니다.

둘째, 속도입니다. 사내망에서 이미지를 주고받으면 인터넷보다 훨씬 빠릅니다.

셋째, 비용입니다. Docker Hub 유료 플랜 비용 대신 자체 서버 비용만 들면 됩니다.

위의 코드를 단계별로 살펴보겠습니다. 먼저 registry:2 이미지로 컨테이너를 실행합니다.

-v 옵션으로 볼륨을 마운트하면 컨테이너가 재시작되어도 이미지가 유지됩니다. 5000번 포트로 접근할 수 있습니다.

그다음 이미지 이름 앞에 레지스트리 주소(localhost:5000)를 붙여서 태그를 만듭니다. 이제 docker push로 업로드하면 됩니다.

실제 현업에서는 어떻게 활용할까요? 대부분의 회사에서는 프라이빗 레지스트리에 인증을 추가합니다.

nginx를 앞에 두고 HTTPS와 Basic Auth를 설정하는 것이 일반적입니다. 또한 Harbor 같은 엔터프라이즈급 레지스트리를 사용하면 취약점 스캔, 이미지 서명, 복제 등 고급 기능을 활용할 수 있습니다.

하지만 주의할 점도 있습니다. 기본 설정으로는 HTTPS 없이 HTTP로 동작합니다.

같은 서버에서 테스트할 때는 괜찮지만, 다른 서버에서 접근하려면 Docker 데몬 설정에서 insecure-registries를 추가하거나, 제대로 된 TLS 인증서를 설정해야 합니다. 다시 김개발 씨의 이야기로 돌아가 봅시다.

회사 서버에 프라이빗 레지스트리를 구축한 김개발 씨는 보안팀의 칭찬을 받았습니다. "이제 안심하고 이미지를 관리할 수 있겠네요!" 프라이빗 레지스트리는 기업 환경에서 필수입니다.

보안과 효율성을 동시에 챙길 수 있습니다.

실전 팁

💡 - 프로덕션 환경에서는 반드시 HTTPS와 인증을 설정하세요

  • 정기적인 백업과 디스크 용량 모니터링을 잊지 마세요

5. GitHub Container Registry

김개발 씨는 GitHub에서 코드를 관리하고 있습니다. Docker Hub 계정을 따로 만들어야 하는 게 번거롭다고 느꼈는데, 어느 날 좋은 소식을 들었습니다.

"GitHub 계정으로도 이미지를 저장할 수 있대!" 바로 GitHub Container Registry, 줄여서 GHCR입니다.

**GitHub Container Registry(GHCR)**는 GitHub에서 제공하는 컨테이너 이미지 저장소입니다. GitHub 계정만 있으면 바로 사용할 수 있고, GitHub Actions와의 연동이 매우 자연스럽습니다.

공개 저장소는 무료이고, 프라이빗 저장소도 일정 용량까지 무료입니다.

다음 코드를 살펴봅시다.

# GitHub Personal Access Token으로 로그인
# 토큰은 write:packages 권한이 필요합니다
echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin

# GitHub Container Registry용 태그 붙이기
docker tag my-app:latest ghcr.io/kimdev/my-app:1.0.0

# GHCR에 이미지 push
docker push ghcr.io/kimdev/my-app:1.0.0

# GHCR에서 이미지 pull
docker pull ghcr.io/kimdev/my-app:1.0.0

# GitHub Actions에서는 자동 인증 가능
# ${{ secrets.GITHUB_TOKEN }}을 사용하면 됩니다

김개발 씨는 이미 GitHub를 열심히 사용하고 있습니다. 코드도 GitHub, 이슈 관리도 GitHub, CI/CD도 GitHub Actions.

그런데 이미지 저장만 Docker Hub를 쓰니 뭔가 어색합니다. 계정도 따로 관리해야 하고, 토큰도 따로 발급받아야 합니다.

박시니어 씨가 귀띔합니다. "GitHub Container Registry 써봐.

GitHub 생태계 안에서 다 해결돼." 그렇다면 GHCR이란 정확히 무엇일까요? 쉽게 비유하자면, Docker Hub가 대형 마트라면 GHCR은 백화점 안의 식품관입니다.

백화점(GitHub)에서 쇼핑하면서 식품관(GHCR)도 자연스럽게 이용할 수 있습니다. 별도로 다른 곳에 갈 필요가 없습니다.

GHCR의 가장 큰 장점은 무엇일까요? 통합된 권한 관리입니다.

GitHub 저장소에 접근 권한이 있으면 해당 이미지에도 접근할 수 있습니다. 별도의 팀 관리나 권한 설정이 필요 없습니다.

또한 GitHub Actions에서 GITHUB_TOKEN을 사용하면 추가 인증 없이 바로 push/pull이 가능합니다. 위의 코드를 살펴보겠습니다.

로그인할 때 주소가 ghcr.io입니다. Docker Hub의 docker.io 대신 GitHub의 ghcr.io를 사용합니다.

이미지 태그도 ghcr.io/사용자명/이미지명 형식입니다. Personal Access Token은 GitHub 설정에서 발급받으며, write:packages 권한이 필요합니다.

실제 현업에서는 어떻게 활용할까요? 오픈소스 프로젝트에서 특히 많이 사용합니다.

코드와 이미지가 같은 GitHub 저장소에 연결되어 있으면 사용자 입장에서 훨씬 편리합니다. 기업에서도 GitHub Enterprise를 사용한다면 GHCR을 표준으로 채택하는 경우가 많습니다.

하지만 주의할 점도 있습니다. GHCR의 무료 용량은 **500MB(프라이빗 기준)**입니다.

이미지가 크고 버전이 많다면 금방 차버릴 수 있습니다. 오래된 이미지를 정리하는 정책을 세워두는 것이 좋습니다.

또한 Docker Hub만큼 많은 공식 이미지가 있지는 않습니다. 다시 김개발 씨의 이야기로 돌아가 봅시다.

GHCR로 전환한 김개발 씨는 관리 포인트가 줄어서 만족합니다. GitHub 하나로 코드부터 이미지까지 모든 것을 관리할 수 있게 되었습니다.

이미 GitHub를 사용하고 있다면 GHCR은 자연스러운 선택입니다. 통합의 편리함을 경험해 보세요.

실전 팁

💡 - GitHub Actions에서는 permissions: packages: write를 설정해야 이미지를 푸시할 수 있습니다

  • 오래된 이미지는 주기적으로 삭제하여 용량을 관리하세요

6. 이미지 보안 스캔

김개발 씨는 열심히 이미지를 만들어 배포했습니다. 그런데 어느 날 보안팀에서 연락이 왔습니다.

"이 이미지에 치명적인 취약점이 있습니다. 즉시 조치해 주세요." 취약점이라니, 내가 만든 코드는 멀쩡한데 무슨 일일까요?

이미지 보안 스캔은 Docker 이미지에 포함된 패키지들의 알려진 취약점(CVE)을 검사하는 것입니다. 우리가 작성한 코드가 아니라 베이스 이미지나 설치한 패키지에 취약점이 있을 수 있습니다.

Docker Scout, Trivy 같은 도구로 미리 스캔하면 보안 사고를 예방할 수 있습니다.

다음 코드를 살펴봅시다.

# Docker Scout으로 이미지 스캔 (Docker Desktop에 내장)
docker scout cves my-app:latest

# 간단한 요약만 보기
docker scout quickview my-app:latest

# Trivy로 이미지 스캔 (오픈소스 도구)
docker run --rm \
  -v /var/run/docker.sock:/var/run/docker.sock \
  aquasec/trivy image my-app:latest

# 심각도 HIGH 이상만 출력
docker run --rm \
  -v /var/run/docker.sock:/var/run/docker.sock \
  aquasec/trivy image --severity HIGH,CRITICAL my-app:latest

# CI에서 취약점 발견 시 빌드 실패 처리
# --exit-code 1 옵션 사용

김개발 씨가 당황한 이유는 간단합니다. 자신이 작성한 코드에는 문제가 없었지만, 베이스 이미지인 ubuntu:20.04에 포함된 openssl 라이브러리에 보안 취약점이 있었던 것입니다.

해커는 이런 알려진 취약점을 노립니다. 박시니어 씨가 설명합니다.

"네가 아무리 코드를 잘 짜도, 그 위에 올라간 OS나 라이브러리에 구멍이 있으면 소용없어. 그래서 이미지 스캔이 중요한 거야." 그렇다면 이미지 보안 스캔이란 정확히 무엇일까요?

쉽게 비유하자면, 보안 스캔은 자동차 정기 검사와 같습니다. 운전자가 아무리 안전 운전을 해도, 자동차 자체에 결함이 있으면 사고가 납니다.

정기 검사로 브레이크, 타이어 등을 점검하듯이, 보안 스캔으로 이미지 내부의 취약점을 점검합니다. 보안 스캔은 어떻게 동작할까요?

스캐너는 이미지에 설치된 모든 패키지 목록을 추출합니다. 그리고 CVE 데이터베이스와 비교합니다.

CVE는 Common Vulnerabilities and Exposures의 약자로, 전 세계적으로 공유되는 취약점 목록입니다. 일치하는 취약점이 있으면 심각도와 함께 보고합니다.

위의 코드를 살펴보겠습니다. Docker Scout은 Docker에서 공식적으로 제공하는 스캐너입니다.

Docker Desktop을 사용하면 기본으로 포함되어 있습니다. Trivy는 오픈소스 스캐너로, CI/CD 파이프라인에 쉽게 통합할 수 있어 인기가 많습니다.

--severity 옵션으로 심각한 취약점만 필터링할 수 있습니다. 실제 현업에서는 어떻게 활용할까요?

보통 CI/CD 파이프라인에 스캔을 포함시킵니다. CRITICAL이나 HIGH 취약점이 발견되면 빌드를 실패시키고 배포를 막습니다.

정기적으로 운영 중인 이미지도 스캔하여 새로 발견된 취약점에 대응합니다. 하지만 주의할 점도 있습니다.

모든 취약점이 실제로 위험한 것은 아닙니다. 해당 기능을 사용하지 않으면 영향이 없는 경우도 많습니다.

심각도실제 사용 여부를 함께 고려해서 우선순위를 정해야 합니다. 무조건 모든 취약점을 0으로 만들려다 보면 개발이 멈출 수 있습니다.

취약점이 발견되면 어떻게 해야 할까요? 가장 쉬운 방법은 베이스 이미지를 최신으로 업데이트하는 것입니다.

FROM ubuntu:20.04를 FROM ubuntu:22.04로 바꾸는 것만으로도 많은 취약점이 해결됩니다. 특정 패키지가 문제라면 해당 패키지만 업데이트할 수도 있습니다.

다시 김개발 씨의 이야기로 돌아가 봅시다. Trivy를 CI에 추가한 김개발 씨는 이제 취약점이 있는 이미지가 배포되는 것을 미리 막을 수 있게 되었습니다.

보안팀도 만족스러워했습니다. 보안은 사후 대응보다 사전 예방이 중요합니다.

이미지 스캔을 개발 프로세스의 일부로 만드세요.

실전 팁

💡 - 베이스 이미지는 가능한 한 가벼운 것(alpine, distroless)을 사용하면 취약점도 줄어듭니다

  • CVE 데이터베이스는 매일 업데이트되므로, 정기적인 재스캔이 필요합니다

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

#Docker#DockerHub#ContainerRegistry#GHCR#ImageSecurity#Docker,Container,DevOps

댓글 (0)

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