Skip to main content

Docker 외부 연결 TLS 암호화로 보호하기

·661 words·4 mins
미뇽
Author
미뇽
안녕하세요! 기술로 세상을 이롭게 만들고 싶은 개발자 미뇽입니다.
Table of Contents

지난 가이드에서는 Docker 데몬을 외부에서 접속할 수 있도록 TCP 포트를 여는 방법을 알아보았습니다. 하지만 당시 강조했듯이, 암호화되지 않은 Docker API를 외부에 노출하는 것은 매우 위험합니다.

오늘은 이 문제를 해결하기 위해, 자체 서명된 인증 기관(CA)을 만들고, TLS 인증서를 발급하여 Docker 서버와 클라이언트 간의 모든 통신을 암호화하는 방법을 단계별로 상세히 안내합니다. 이 절차를 통해 서버는 신뢰된 클라이언트의 접속만 허용하고, 클라이언트는 신뢰된 서버에만 접속하여 중간자 공격(Man-in-the-middle attack)을 방지하는 안전한 환경을 구축할 수 있습니다.

사전 준비
#

  • OpenSSL: 인증서 생성을 위한 도구입니다. 대부분의 Linux 배포판에 기본 설치되어 있으며, 없다면 sudo apt-get install openssl 명령어로 설치합니다.

인증서 생성
#

모든 인증서 파일을 한곳에서 관리하기 위해 작업 디렉토리를 생성하고 그 안에서 모든 작업을 진행합니다.

# 변수 설정 (자신의 환경에 맞게 수정)
export SERVER_HOSTNAME="docker.example.com"
export SERVER_IP="192.168.0.100"

# 작업 디렉토리 생성 및 이동
mkdir ~/docker-certs
cd ~/docker-certs

인증 기관(CA) 키 및 인증서 생성
#

먼저, 우리의 서버 및 클라이언트 인증서를 발급할 최상위 인증 기관(CA)을 만듭니다.

# 1. CA 개인키 생성
openssl genrsa -aes256 -out ca-key.pem 4096

# 2. CA 인증서 생성 (ca.pem)
# Common Name(CN)은 구분을 위해 "My Docker CA" 와 같이 자유롭게 입력합니다.
openssl req -new -x509 -days 3650 -key ca-key.pem -sha256 -out ca.pem

서버 키 및 인증서 생성
#

이제 Docker 데몬(서버)이 사용할 개인키와 인증서를 생성합니다. 이 인증서는 CA에 의해 서명됩니다.

# 1. 서버 개인키 생성
openssl genrsa -out server-key.pem 4096

# 2. 서버 인증서 서명 요청(CSR) 생성
# ※ 중요: Common Name(CN)에 반드시 서버의 DNS 호스트명을 입력해야 합니다.
openssl req -subj "/CN=${SERVER_HOSTNAME}" -sha256 -new -key server-key.pem -out server.csr

# 3. 서버 인증서가 IP 주소와 호스트명 모두에서 유효하도록 설정 파일 생성
echo "subjectAltName = DNS:${SERVER_HOSTNAME},IP:${SERVER_IP}" >> extfile.cnf

# 4. CA를 이용해 서버 인증서 서명 (server-cert.pem)
openssl x509 -req -days 3650 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem \
  -CAcreateserial -out server-cert.pem -extfile extfile.cnf

클라이언트 키 및 인증서 생성
#

원격에서 서버에 접속할 클라이언트가 사용할 개인키와 인증서를 생성합니다. 이 인증서 역시 CA에 의해 서명되어야 서버가 신뢰할 수 있습니다.

# 1. 클라이언트 개인키 생성
openssl genrsa -out key.pem 4096

# 2. 클라이언트 인증서 서명 요청(CSR) 생성
# Common Name(CN)은 "client" 등 식별 가능한 이름으로 입력합니다.
openssl req -subj "/CN=client" -new -key key.pem -out client.csr

# 3. 클라이언트 인증 용도로 확장 키 사용 설정
echo "extendedKeyUsage = clientAuth" > extfile-client.cnf

# 4. CA를 이용해 클라이언트 인증서 서명 (cert.pem)
openssl x509 -req -days 3650 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem \
  -CAcreateserial -out cert.pem -extfile extfile-client.cnf

생성된 파일 정리 및 권한 설정
#

이제 불필요한 파일(CSR, .cnf 등)을 정리하고, 개인키 파일의 권한을 소유자만 읽을 수 있도록 변경하여 보안을 강화합니다.

# 불필요한 파일 삭제
rm -v client.csr server.csr extfile.cnf extfile-client.cnf ca.srl

# 개인키 파일 권한 설정 (읽기 전용)
chmod -v 0400 ca-key.pem key.pem server-key.pem

# 인증서 파일 권한 설정 (읽기 전용)
chmod -v 0444 ca.pem server-cert.pem cert.pem

Docker 데몬 설정
#

생성된 서버용 인증서를 Docker가 읽을 수 있는 위치로 복사하고, daemon.json 파일을 수정하여 TLS를 활성화합니다.

인증서 복사

sudo mkdir -p /etc/docker/certs
sudo cp -v ca.pem server-cert.pem server-key.pem /etc/docker/certs/

/etc/docker/daemon.json 파일 수정

TLS를 강제하고, 인증서 경로를 지정하며, 보안 포트인 2376을 사용하도록 변경합니다.

{
  "hosts": ["tcp://0.0.0.0:2376", "unix:///var/run/docker.sock"],
  "tlsverify": true,
  "tlscacert": "/etc/docker/certs/ca.pem",
  "tlscert": "/etc/docker/certs/server-cert.pem",
  "tlskey": "/etc/docker/certs/server-key.pem"
}

Docker 재시작

sudo systemctl restart docker

원격 클라이언트 설정 및 접속
#

원격으로 접속할 클라이언트 PC로 아래 세 개의 파일을 안전하게 전송합니다.

  • ca.pem (인증 기관 인증서)
  • cert.pem (클라이언트 인증서)
  • key.pem (클라이언트 개인키)

클라이언트 PC의 ~/.docker 디렉토리에 전송받은 파일들을 저장합니다. 이 디렉토리는 Docker가 기본적으로 인증서를 찾는 위치입니다.

아래 명령어를 사용하여 원격 서버에 안전하게 접속되는지 테스트합니다.

docker --tlsverify \
  --tlscacert=~/.docker/ca.pem \
  --tlscert=~/.docker/cert.pem \
  --tlskey=~/.docker/key.pem \
  -H=${SERVER_HOSTNAME}:2375 version

환경 변수 설정으로 편리하게 사용하기

매번 긴 명령어를 입력하는 대신, 클라이언트 PC의 셸 설정 파일(.bashrc, .zshrc 등)에 아래 환경 변수를 추가하면 docker ps와 같은 일반 명령어로 바로 원격 서버에 접속할 수 있습니다.

export DOCKER_HOST=tcp://${SERVER_HOSTNAME}:2375
export DOCKER_TLS_VERIFY=1
export DOCKER_CERT_PATH=~/.docker

마무리하며
#

이것으로 Docker 원격 연결을 TLS로 암호화하는 모든 과정이 완료되었습니다. 이제 여러분의 Docker 서버는 지정된 CA가 서명한 유효한 클라이언트 인증서를 가진 사용자만 접속을 허용하는 안전한 상태가 되었습니다. 이 방식은 프로덕션 환경이나 신뢰할 수 없는 네트워크에서 원격으로 Docker를 관리할 때 필수적인 보안 조치입니다.


참조