본문으로 건너뛰기

Docker Compose + Ubuntu 로 안전한 배포

· 약 5 분

실리콘밸리 스타트업에서는 Docker Compose가 컨테이너화된 애플리케이션을 빠르게 배포하고 관리하기 위한 선호 도구 중 하나입니다. 하지만 편리함에는 보안 위험이 따르기 마련이죠. 사이트 신뢰성 엔지니어(SRE)로서 보안 취약점이 가져올 수 있는 재앙적인 결과를 잘 알고 있습니다. 이 글에서는 Docker Compose와 Ubuntu 시스템을 실제 업무에 결합해 적용하면서 정리한 최고의 보안 관행을 공유합니다. Docker Compose의 편리함을 누리면서도 시스템 보안을 확실히 지키는 방법을 알려드리겠습니다.

Docker Compose + Ubuntu 로 안전한 배포

I. Ubuntu 시스템 보안 강화​

컨테이너를 배포하기 전에 Ubuntu 호스트 자체의 보안을 확보하는 것이 가장 중요합니다. 주요 단계는 다음과 같습니다.

1. Ubuntu와 Docker를 정기적으로 업데이트​

시스템과 Docker 모두 최신 상태를 유지해 알려진 취약점을 즉시 패치합니다.

sudo apt update && sudo apt upgrade -y
sudo apt install docker-ce docker-compose-plugin

2. Docker 관리 권한 제한​

Docker 관리 권한을 엄격히 제어해 권한 상승 공격을 방지합니다.

sudo usermod -aG docker deployuser
# 일반 사용자가 쉽게 Docker 관리 권한을 얻지 못하도록 함

3. Ubuntu 방화벽(UFW) 설정​

네트워크 접근을 합리적으로 제한해 무단 접근을 차단합니다.

sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose

4. Docker와 UFW 연동 올바르게 구성​

Docker는 기본적으로 UFW를 우회해 iptables를 설정하므로 수동 제어가 필요합니다.

Docker 설정 파일을 수정합니다:

sudo nano /etc/docker/daemon.json

다음 내용을 추가합니다:

{
"iptables": false,
"ip-forward": true,
"userland-proxy": false
}

Docker 서비스를 재시작합니다:

sudo systemctl restart docker

Docker Compose에서 주소를 명시적으로 바인딩합니다:

services:
webapp:
ports:
- "127.0.0.1:8080:8080"

II. Docker Compose 보안 모범 사례​

아래 설정은 Docker Compose v2.4 이상을 기준으로 합니다. Swarm 모드와 비 Swarm 모드의 차이점에 유의하세요.

1. 컨테이너 권한 제한​

컨테이너가 기본적으로 root 권한으로 실행되면 위험이 크므로 비 root 사용자로 전환합니다.

services:
app:
image: your-app:v1.2.3
user: "1000:1000" # 비 root 사용자
read_only: true # 읽기 전용 파일시스템
volumes:
- /tmp/app:/tmp # 쓰기 권한이 필요한 경우에만 특정 디렉터리 마운트
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE

설명

  • 읽기 전용 파일시스템은 컨테이너 내부에서의 변조를 방지합니다.
  • 마운트하는 볼륨은 반드시 필요한 디렉터리만 제한합니다.

2. 네트워크 격리 및 포트 관리​

내부 네트워크와 외부 네트워크를 명확히 구분해 민감한 서비스가 외부에 노출되지 않도록 합니다.

networks:
frontend:
internal: false
backend:
internal: true

services:
nginx:
networks: [frontend, backend]
database:
networks:
- backend
  • frontend 네트워크: 외부에 공개 가능.
  • backend 네트워크: 내부 통신 전용으로 엄격히 제한.

3. 비밀 관리 보안​

민감한 데이터는 Compose 파일에 직접 넣지 않습니다.

단일 머신 모드:

services:
webapp:
environment:
- DB_PASSWORD_FILE=/run/secrets/db_password
volumes:
- ./secrets/db_password.txt:/run/secrets/db_password:ro

Swarm 모드:

services:
webapp:
secrets:
- db_password
environment:
DB_PASSWORD_FILE: /run/secrets/db_password

secrets:
db_password:
external: true # Swarm 내장 비밀 관리 사용

주의

  • Docker Swarm의 기본 비밀 관리 기능은 Vault, AWS Secrets Manager와 같은 외부 도구를 직접 사용할 수 없습니다.
  • 외부 비밀 저장소가 필요하다면 자체적으로 읽어오는 로직을 구현해야 합니다.

4. 리소스 제한 (Docker Compose 버전에 맞게 적용)​

컨테이너 하나가 호스트 리소스를 고갈시키는 일을 방지합니다.

단일 머신 모드 (v2.4 권장):

version: '2.4'

services:
api:
image: your-image:1.4.0
mem_limit: 512m
cpus: 0.5

Swarm 모드 (v3 이상):

services:
api:
deploy:
resources:
limits:
cpus: "0.5"
memory: 512M
reservations:
cpus: "0.25"
memory: 256M

Note: 비 Swarm 환경에서는 deploy 섹션의 리소스 제한이 적용되지 않으니 Compose 파일 버전에 유의하세요.

5. 컨테이너 헬스 체크​

헬스 체크를 설정해 문제를 사전에 감지하고 서비스 다운타임을 최소화합니다.

services:
webapp:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 20s

6. latest 태그 사용 금지​

프로덕션 환경에서는 latest 태그가 가져오는 불확실성을 피하고, 명시적인 이미지 버전을 지정합니다.

services:
api:
image: your-image:1.4.0

7. 로그 관리 적절히 수행​

컨테이너 로그가 디스크를 가득 채우는 일을 방지합니다.

services:
web:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "5"

8. Ubuntu AppArmor 설정 확인​

Ubuntu는 기본적으로 AppArmor를 활성화합니다. Docker 프로파일 상태를 확인하는 것이 좋습니다.

sudo systemctl enable --now apparmor
sudo aa-status

Ubuntu에서 Docker는 기본적으로 AppArmor를 활성화하므로 별도 설정이 필요하지 않습니다. Ubuntu에 SELinux를 동시에 활성화하면 충돌이 발생하므로 권장되지 않습니다.

9. 지속적인 업데이트와 보안 스캔​

  • 이미지 취약점 스캔: CI/CD 파이프라인에 Trivy, Clair, Snyk 등 도구를 연동합니다.
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy image your-image:v1.2.3
  • 자동 보안 업데이트 프로세스: 알려진 취약점을 해결하기 위해 최소 주 1회 이상 이미지를 재빌드합니다.

III. 사례 연구: Docker Compose 설정 실수에서 얻은 교훈​

2019년 7월, Capital One은 1억 명이 넘는 고객의 개인 정보를 유출하는 대규모 데이터 유출 사고를 겪었습니다12. 주요 원인은 AWS 설정 오류였지만, 컨테이너 보안 문제도 크게 작용했습니다.

  1. 컨테이너 권한 문제: 공격자는 과도한 권한을 가진 컨테이너 내 WAF 취약점을 이용했습니다.
  2. 네트워크 격리 미비: 침해된 컨테이너가 다른 AWS 리소스에 접근할 수 있었으며, 이는 네트워크 격리가 충분히 이루어지지 않았기 때문입니다.
  3. 민감 데이터 노출: 설정 오류로 인해 대량의 고객 민감 데이터에 접근·탈취가 가능했습니다.
  4. 보안 설정 실수 누적: 컨테이너와 클라우드 서비스 설정 오류가 복합적으로 작용해 사고가 확대되었습니다.

이 사건으로 Capital One은 수억 달러 규모의 벌금과 장기적인 신뢰 위기를 겪었습니다. 권한 관리, 네트워크 격리, 민감 데이터 보호 등 보안 설정의 중요성을 다시금 일깨워 주는 사례라 할 수 있습니다.

IV. 결론 및 권고사항​

Docker Compose와 Ubuntu 조합은 컨테이너 애플리케이션을 빠르게 배포하는 편리한 방법이지만, 보안은 전체 프로세스에 걸쳐 내재되어야 합니다.

  • 컨테이너 권한과 네트워크 격리를 철저히 관리합니다.
  • 민감 데이터가 유출되지 않도록 비밀 관리를 강화합니다.
  • 정기적인 보안 스캔과 업데이트를 수행합니다.
  • 기업 규모가 커짐에 따라 Kubernetes와 같은 고급 오케스트레이션 시스템으로 전환을 고려합니다.

보안은 끝이 없는 연속적인 실천입니다. 이 글이 Docker Compose + Ubuntu 환경을 보다 안전하게 운영하는 데 도움이 되길 바랍니다.