리눅스 서버에 Docker와 PostgreSQL을 안전하게 설치하는 방법 (프로덕션 친화적인 가이드)

발행: (2025년 12월 15일 오후 06:50 GMT+9)
7 min read
원문: Dev.to

Source: Dev.to

소개

서버에서 데이터베이스를 실행하는 것은 쉽지만, 보안을 확보하는 부분에서 대부분의 설정이 실패합니다. 이 가이드는 다음을 보여줍니다:

  • Docker를 올바르게 설치하기
  • Docker가 서버를 약화시키지 않도록 잠그기
  • PostgreSQL을 Docker에서 실행하되 인터넷에 노출되지 않게 하기
  • 로컬 머신에서 데이터베이스에 안전하게 접근하기
  • 흔히 발생하는 보안 실수를 피하기

단일 서버, 사이드 프로젝트, SaaS MVP, 그리고 안전을 우선시하는 프로덕션 환경에 적합합니다.

사전 요구 사항

  • Ubuntu 22.04 또는 24.04
  • sudo 권한이 있는 비‑root 관리자 사용자(예: dev)
  • SSH 키 기반 로그인
  • 방화벽 활성화(UFW)

중요: 일상 작업에 root 사용자를 사용하지 마세요.

공식 저장소에서 Docker 설치

# Remove any old Docker packages
sudo apt remove -y docker docker-engine docker.io containerd runc

# Install prerequisites
sudo apt update
sudo apt install -y ca-certificates curl gnupg

# Set up Docker’s official GPG key
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
  sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

# Add Docker’s APT repository
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# Install Docker Engine
sudo apt update
sudo apt install -y \
  docker-ce \
  docker-ce-cli \
  containerd.io \
  docker-buildx-plugin \
  docker-compose-plugin

설치 확인:

sudo docker version
sudo docker run --rm hello-world

Hello from Docker! 라는 메시지가 보이면 Docker가 정상적으로 작동하는 것입니다.

docker 그룹에 사용자 추가

sudo usermod -aG docker dev

로그아웃 후 다시 로그인(또는 ssh dev@SERVER_IP)하고 확인:

docker ps

⚠️ 경고: 애플리케이션이나 서비스 사용자를 docker 그룹에 추가하지 마세요. 이 그룹은 root와 동등한 권한을 부여합니다.

Docker 데몬 강화

/etc/docker/daemon.json 파일을 생성하거나 편집합니다:

sudo nano /etc/docker/daemon.json

다음 구성을 붙여넣으세요:

{
  "icc": false,
  "live-restore": true,
  "no-new-privileges": true,
  "userns-remap": "default",
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

설명

  • icc: false – 컨테이너 간 통신을 차단합니다.
  • userns-remap: "default" – 컨테이너 루트를 권한이 낮은 호스트 사용자에 매핑합니다.
  • no-new-privileges: true – 권한 상승을 차단합니다.
  • 로그 옵션은 디스크 사용량을 제한합니다.
  • live-restore: true 은 Docker 재시작 시에도 컨테이너가 계속 실행되도록 합니다.

Docker를 재시작하고 사용자 네임스페이스 매핑을 확인합니다:

sudo systemctl restart docker
docker info | grep -i userns

PostgreSQL용 Docker 볼륨 준비

docker volume create pgdata

Docker에서 PostgreSQL 18 실행

참고: PostgreSQL 18은 데이터를 /var/lib/postgresql에 저장합니다. /var/lib/postgresql/data를 마운트하지 마세요.

docker run -d \
  --name postgres \
  --restart unless-stopped \
  -e POSTGRES_USER=appuser \
  -e POSTGRES_PASSWORD=STRONG_PASSWORD_HERE \
  -e POSTGRES_DB=appdb \
  -v pgdata:/var/lib/postgresql \
  -p 127.0.0.1:5432:5432 \
  postgres:18
  • 데이터베이스 포트는 오직 127.0.0.1에만 바인딩되므로 외부에 공개되지 않습니다.
  • 데이터는 pgdata 볼륨에 영구 보관됩니다.
  • PostgreSQL은 컨테이너 내부에서 비‑root 사용자로 실행됩니다.

컨테이너 확인

docker ps
docker logs postgres

다음과 같은 문구가 표시되어야 합니다:

database system is ready to accept connections

데이터베이스에 접속:

docker exec -it postgres psql -U appuser -d appdb

psql 내부에서:

SELECT version();
\q

포트가 공개되지 않았는지 확인

ss -tulpn | grep 5432

예상 출력:

127.0.0.1:5432

만약 0.0.0.0:5432 가 보이면 컨테이너를 중지하고 바인딩을 수정하세요.

방화벽 상태 확인:

sudo ufw status

PostgreSQL이 허용된 서비스 목록에 표시되지 않아야 합니다.

SSH 터널을 통한 원격 접근 보안

로컬 머신에서 다음 명령을 실행해 원격 PostgreSQL 포트를 로컬 머신으로 포워딩하는 SSH 터널을 만듭니다:

ssh -N -L 5432:127.0.0.1:5432 dev@SERVER_IP

작업 중인 동안 이 터미널을 열어두세요.

선호하는 클라이언트로 연결

설정
Host127.0.0.1
Port5432
Userappuser
Passwordyour password
Databaseappdb

TablePlus, DBeaver, pgAdmin, psql 등에서 모두 동작합니다.

요약

  • 공식 저장소와 강화된 데몬 기본값을 사용해 Docker를 안전하게 설치했습니다.
  • PostgreSQL 18은 컨테이너에서 실행되며, 향후 확장성을 고려한 레이아웃과 공개 포트가 없습니다.
  • SSH 터널링을 통해 데이터베이스에 암호화된 사설 접근을 제공합니다.

Kubernetes나 관리형 서비스를 사용하지 않아도, 올바른 절차와 기본값만으로 충분히 안전한 환경을 만들 수 있습니다.

다음 단계 (선택 사항)

  • pgdata 볼륨에 대한 자동 백업 설정하기.
  • PostgreSQL 컨테이너에 리소스 제한 추가하기.
  • 재현 가능한 배포를 위해 docker-compose 사용하기.
  • 디스크 사용량을 모니터링하고 노출된 포트를 정기적으로 감사하기.

이 가이드를 따르면 대부분의 프로덕션 환경보다 더 안전한 서버를 운영할 수 있습니다. Happy shipping 🚀

Back to Blog

관련 글

더 보기 »