리눅스 서버에 Docker와 PostgreSQL을 안전하게 설치하는 방법 (프로덕션 친화적인 가이드)
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
작업 중인 동안 이 터미널을 열어두세요.
선호하는 클라이언트로 연결
| 설정 | 값 |
|---|---|
| Host | 127.0.0.1 |
| Port | 5432 |
| User | appuser |
| Password | your password |
| Database | appdb |
TablePlus, DBeaver, pgAdmin, psql 등에서 모두 동작합니다.
요약
- 공식 저장소와 강화된 데몬 기본값을 사용해 Docker를 안전하게 설치했습니다.
- PostgreSQL 18은 컨테이너에서 실행되며, 향후 확장성을 고려한 레이아웃과 공개 포트가 없습니다.
- SSH 터널링을 통해 데이터베이스에 암호화된 사설 접근을 제공합니다.
Kubernetes나 관리형 서비스를 사용하지 않아도, 올바른 절차와 기본값만으로 충분히 안전한 환경을 만들 수 있습니다.
다음 단계 (선택 사항)
pgdata볼륨에 대한 자동 백업 설정하기.- PostgreSQL 컨테이너에 리소스 제한 추가하기.
- 재현 가능한 배포를 위해
docker-compose사용하기. - 디스크 사용량을 모니터링하고 노출된 포트를 정기적으로 감사하기.
이 가이드를 따르면 대부분의 프로덕션 환경보다 더 안전한 서버를 운영할 수 있습니다. Happy shipping 🚀