Docker 이미지 강화 및 공격 표면 감소를 위한 모범 사례

이미지 강화를 위한 모범 사례로 Docker 보안을 강화하세요. 비루트 사용자로 컨테이너를 실행하고, 패키지를 줄여 공격 표면을 최소화하며, 효과적인 상태 확인을 구현하고, 시크릿을 안전하게 관리하며, 멀티스테이지 빌드를 활용하는 방법을 배우세요. 이 가이드는 더 안전하고 탄력적인 Docker 이미지를 구축하고 배포 환경에서 취약점 위험을 줄이기 위한 실행 가능한 단계와 예시를 제공합니다.

37 조회수

Docker 이미지 강화 및 공격 표면 감소를 위한 모범 사례

Docker는 개발자가 애플리케이션과 해당 종속성을 휴대 가능하고 자체적인 컨테이너로 패키징할 수 있게 함으로써 애플리케이션 배포에 혁명을 일으켰습니다. 그러나 사용 편의성 때문에 보안의 중요성이 간과될 수 있습니다. Docker 이미지를 강화하는 것은 공격 표면을 최소화하고 잠재적인 위협으로부터 애플리케이션 및 인프라를 보호하는 데 가장 중요합니다. 이 글에서는 Dockerfile을 보호하고, 더 견고한 컨테이너를 구축하며, 컨테이너화된 배포와 관련된 전반적인 위험을 줄이기 위한 필수적인 모범 사례를 제시합니다.

이러한 관행을 채택함으로써 Docker 이미지의 보안 상태를 크게 개선하여 악용에 더 탄력적으로 대응하고 더 안전한 배포 환경을 보장할 수 있습니다. 우리는 최소 권한으로 컨테이너를 실행하고, 효과적인 상태 확인을 구현하며, 취약점 가능성을 줄이기 위해 이미지 크기를 최적화하는 등의 기술에 대해 자세히 알아볼 것입니다.

1. 컨테이너를 비루트 사용자로 실행

가장 기본적인 보안 원칙 중 하나는 최소 권한의 원칙입니다. 기본적으로 Docker 컨테이너 내의 프로세스는 루트 사용자로 실행됩니다. 이는 컨테이너가 손상될 경우 공격자가 악용할 수 있는 광범위한 권한을 부여합니다. 애플리케이션을 비루트 사용자로 실행하면 공격자가 컨테이너 내에서 가할 수 있는 잠재적 피해를 극적으로 줄일 수 있습니다.

비루트 사용자 생성

Dockerfile 내에서 새 사용자 및 그룹을 만들고, 애플리케이션을 실행하기 전에 해당 사용자로 전환할 수 있습니다.

# Use an official Python runtime as a parent image
FROM python:3.9-slim

# Set the working directory
WORKDIR /app

# Copy the current directory contents into the container at /app
COPY . /app

# Install any needed packages specified in requirements.txt
RUN pip install --no-cache-dir -r requirements.txt

# Create a non-root user and group
RUN addgroup --system --gid 1001 appgroup && \n    adduser --system --uid 1001 --ingroup appgroup appuser

# Switch to the non-root user
USER appuser

# Make port 80 available to the world outside this container
EXPOSE 80

# Define environment variable
ENV NAME World

# Run app.py when the container launches
CMD ["python", "app.py"]

비루트 사용자를 위한 고려 사항

  • 권한: 비루트 사용자가 애플리케이션에 필요한 디렉터리 및 파일에 대한 읽기 및 쓰기 권한을 가지고 있는지 확인하십시오. 소유권을 적절하게 설정하기 위해 chown을 사용해야 할 수도 있습니다.
  • 포트 바인딩: 비루트 사용자는 일반적으로 1024 이상의 포트에만 바인딩할 수 있습니다. 애플리케이션이 특권 포트(예: 80 또는 443)에 바인딩해야 하는 경우, 호스트 또는 적절한 권한을 가진 다른 컨테이너 내에서 실행되는 리버스 프록시(예: Nginx 또는 Traefik)를 사용하거나 Linux 기능을 구성하는 것을 고려하십시오.

2. 설치된 패키지 및 종속성 최소화

Docker 이미지에 설치된 모든 패키지는 이미지 크기를 증가시키고, 더 중요하게는 공격 표면을 증가시킵니다. 각 패키지는 공격자가 악용할 수 있는 자체 취약점을 가질 수 있습니다. 따라서 절대적으로 필요한 것만 포함하는 것이 중요합니다.

패키지 관리 모범 사례:

  • 최소 기반 이미지 사용: 가능하면 기반 이미지의 slim 또는 alpine 변형을 선택하십시오. 이 이미지는 애플리케이션을 실행하는 데 필요한 필수 구성 요소만 포함하여 공격 표면을 크게 줄입니다. 예를 들어, python:3.9-slimpython:3.9보다 작고 더 안전합니다.
  • 설치 후 정리: 패키지 설치 후, 패키지 관리자 캐시 또는 임시 파일을 정리하십시오. 이는 이미지 크기를 줄일 뿐만 아니라 공격자를 위한 잠재적 스테이징 영역도 제거합니다.
    ```dockerfile
    # Example for Debian/Ubuntu based images
    RUN apt-get update && apt-get install -y --no-install-recommends some-package && \n rm -rf /var/lib/apt/lists/*

    Example for Alpine based images

    RUN apk add --no-cache some-package
    * **멀티 스테이지 빌드:** 이는 최종 이미지를 가볍게 유지하기 위한 강력한 기술입니다. 한 스테이지를 사용하여 애플리케이션을 빌드하고(빌드 도구, 컴파일러 등 설치), 두 번째 깨끗한 스테이지를 사용하여 빌드 스테이지에서 필요한 아티팩트만 복사합니다. 이렇게 하면 빌드 종속성이 프로덕션 이미지에 포함되는 것을 방지합니다.dockerfile

    --- Build Stage ---

    FROM golang:1.18-alpine AS builder
    WORKDIR /app
    COPY . .
    RUN go build -o myapp

    --- Production Stage ---

    FROM alpine:latest
    WORKDIR /app
    COPY --from=builder /app/myapp .
    CMD ["./myapp"]
    ```
    * 종속성 정기적으로 업데이트: 보안 패치를 통합하기 위해 애플리케이션 종속성 및 기반 이미지를 최신 상태로 유지하십시오.

3. 강력한 상태 확인 구현

상태 확인은 컨테이너의 상태를 모니터링하는 데 중요합니다. Docker는 이러한 확인을 사용하여 컨테이너가 올바르게 실행 중인지 판단하고, 비정상적인 컨테이너를 자동으로 다시 시작하거나 제거할 수 있습니다. 잘 정의된 상태 확인은 애플리케이션이 실행 중일 뿐만 아니라 응답성이 있고 예상대로 작동하는지 확인하는 데 도움이 됩니다.

상태 확인 정의:

Dockerfile의 HEALTHCHECK 명령어는 Docker가 컨테이너 내부에서 주기적으로 실행하여 상태를 테스트하는 명령어를 지정합니다. 명령어가 0이 아닌 상태로 종료되면 컨테이너는 비정상으로 간주됩니다.

# Example for a web application
FROM nginx:latest

# ... other instructions ...

# Check if the Nginx process is running and listening on port 80
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \n  CMD curl -f http://localhost:80/ || exit 1

# ... other instructions ...

상태 확인을 위한 모범 사례:

  • 간단하게 유지: 상태 확인 명령어는 가볍고 빠르게 실행되어야 합니다. 확인 속도를 늦추거나 자체적인 실패 지점을 초래할 수 있는 복잡한 로직을 피하십시오.
  • 핵심 기능 테스트: 확인은 프로세스가 실행 중인지 여부뿐만 아니라 애플리케이션의 핵심 기능을 테스트해야 합니다. 웹 서버의 경우, 기본적인 HTTP 요청에 응답할 수 있는지 확인하는 것을 의미할 수 있습니다.
  • start-period 구성: 초기화하는 데 시간이 걸리는 애플리케이션의 경우, 상태 확인이 실패하기 전에 시작할 시간을 주기 위해 start-period 옵션을 사용하십시오.

4. 시크릿 및 민감한 데이터 안전하게 관리

API 키, 암호 또는 인증서와 같은 시크릿을 Dockerfile 또는 이미지에 직접 포함하지 마십시오. 이러한 시크릿은 이미지 레이어의 일부가 되어 쉽게 검색될 수 있습니다. 대신, 민감한 정보는 Docker 시크릿 또는 오케스트레이션 플랫폼(예: Kubernetes 또는 Docker Swarm)에서 관리하는 환경 변수를 사용하십시오.

Docker 시크릿 (Swarm 모드):

Docker Swarm은 시크릿 관리를 위한 기본 메커니즘을 제공합니다. 시크릿을 생성하고 파일로 컨테이너에 마운트할 수 있습니다.

# Create a secret
docker secret create my_api_key api_key.txt

# Deploy a service using the secret
docker service create --secret my_api_key my_web_app

환경 변수 (주의 사항):

환경 변수는 편리하지만, 실행 중인 컨테이너를 검사할 때 (docker inspect)도 볼 수 있습니다. 민감하지 않은 구성 데이터에 사용하십시오. 민감한 데이터의 경우 Docker 시크릿 또는 외부 시크릿 관리 시스템이 선호됩니다.

5. 특정 이미지 태그 사용

Dockerfile에서 기반 이미지 또는 다른 이미지를 참조할 때(예: FROM ubuntu:latest) 항상 latest 대신 특정 버전 태그를 사용하십시오. latest를 사용하면 latest 태그가 시간이 지남에 따라 변경될 수 있으므로 예측 불가능한 빌드가 발생할 수 있으며, 잠재적으로 알지 못하는 사이에 호환되지 않는 변경 사항이나 심지어 보안 취약점이 도입될 수 있습니다.

# Avoid this:
# FROM ubuntu:latest

# Prefer this:
FROM ubuntu:22.04

6. 이미지 취약점 스캔

알려진 취약점에 대해 Docker 이미지를 정기적으로 스캔하십시오. CI/CD 파이프라인과 레지스트리 모두에서 이를 수행하는 데 도움이 되는 여러 도구가 있습니다.

인기 있는 스캔 도구:

  • Trivy: 컨테이너를 위한 간단하고 포괄적인 취약점 스캐너입니다. OS 패키지 및 애플리케이션 종속성을 스캔합니다.
    bash trivy image your-image-name:tag
  • Clair: 컨테이너 이미지의 취약점을 탐지하기 위한 오픈 소스 정적 분석 도구입니다.
  • Docker Scout: Docker에서 제공하는 서비스로, 컨테이너 이미지의 취약점을 분석하고 권장 사항을 제공합니다.

이러한 스캔을 빌드 프로세스에 통합하면 이미지를 배포하기 전에 잠재적인 보안 문제를 인지하고 해결할 수 있습니다.

7. 이미지 레이어 이해

Docker 이미지는 레이어로 빌드됩니다. Dockerfile을 변경하면 새 레이어가 생성됩니다. 레이어가 작동하는 방식을 이해하면 크기와 보안 모두에 최적화된 Dockerfile을 만드는 데 도움이 될 수 있습니다. 변경 빈도가 낮은 명령어(예: 기본 패키지 설치)를 Dockerfile의 앞쪽에 배치하고, 변경 빈도가 높은 명령어(예: 애플리케이션 코드 복사)를 뒤쪽에 배치하십시오. 이는 Docker의 빌드 캐시를 효과적으로 활용하고 빌드 속도를 높일 수 있습니다.

보안에 더 중요한 점은, 초기 레이어의 민감한 정보 또는 우발적인 노출이 유지될 수 있다는 것입니다. 더 이상 필요하지 않은 경우 최종 이미지 레이어에 남지 않도록 모든 민감한 파일 또는 명령어가 처리되었는지 확인하십시오.

결론

Docker 이미지 강화는 세부 사항에 대한 주의와 보안 모범 사례 준수가 필요한 지속적인 프로세스입니다. 컨테이너를 비루트 사용자로 실행하고, 종속성을 최소화하며, 강력한 상태 확인을 구현하고, 시크릿을 안전하게 관리하며, 특정 이미지 태그를 사용하고, 취약점에 대해 정기적으로 스캔함으로써 컨테이너화된 애플리케이션의 공격 표면을 크게 줄일 수 있습니다. 이러한 관행은 단순히 규정 준수에 관한 것이 아니라, 컨테이너 시대에 안전하고 안정적이며 탄력적인 소프트웨어 시스템을 구축하기 위한 기본적인 요소입니다.

기존 Dockerfile을 검토하고 이러한 권장 사항을 점진적으로 구현하는 것으로 시작하십시오. 귀하의 보안 상태가 이에 감사할 것입니다.