[SSL] docker 컨테이너 프로젝트 ssl 적용

무1민·2023년 9월 3일
0

infra

목록 보기
8/14

개요

웹을 배포해본 적이 있다면 SSL에 대해 들어본 적이 있을 것이다. SSL이 적용된 URL의 프로토콜은 https://로 시작하며, http://와 달리 보안을 의미하는 s가 붙는다. 현재 velog도 ssl이 적용된 걸 확인할 수 있다.

SSL?

SSL은 Secure Socket Layer의 약자로, 직역하면 암호화 소켓층이다.

SSL은 웹 서버와 클라이언트의 통신 암호화 프로토콜이다.

SSL이 적용되지 않은 통신의 경우, 위 그림과 같이 평문(Plain Text)이 그대로 전송된다.
만약 제 3자가 어떠한 방식으로든 통신 패킷을 탈취할 경우, 그 내용을 쉽게 확인할 수 있다.

SSL을 적용한다면 요청을 암호화해서 보내므로 통신 패킷이 탈취돼도 복호화 키가 없으면 원래 내용을 알 수 없기 때문이다.

TLS(Transposrt Layer Security)

SSL을 접하다보면 TLS라는 개념도 접하게 된다.
TLS는 SSL 3.0의 보안취약점을 보완한 통신 보안 프로토콜로, SSL을 보완한 것이 TLS지만, 인터넷에 적용되는 통신 보안 프로토콜을 전부 통틀어서 SSL이라고 부른다.
SSL은 마지막 버전인 3.0마저 금지됐으므로, 현재 사용 중인 통신 보안 프로토콜은 모두 TLS이다.

SSL의 특징

  1. URL 프로토콜은 https이며, 기본 포트는 443이다.
  2. 통신 데이터가 암호화되어, 패킷이 탈취되는 사고가 발생해도 데이터를 지킬 수 있다.
  3. SSL 인증서를 통해 도메인의 신뢰성을 검증할 수 있다.
  4. 데이터 송/수신 과정에서 암/복호화가 발생하므로 속도가 느리다.

SSL 적용법

SSL을 적용시키기 위해선 단일 Nginx 방식이 있고, 이중 Nginx 방식이 있다.

단일 Nginx 방식:
Docker 컨테이너 안에 React 앱과 Nginx를 함께 배치하고, 이 Nginx를 사용하여 HTTPS를 설정한다. 이렇게 하려면, Let's Encrypt와 같은 툴로 인증서를 획득한 후, 해당 인증서를 컨테이너 안의 Nginx에 연결해야 한다.
이 방식의 단점은 컨테이너를 재시작할 때마다 인증서를 다시 설정해야 할 가능성이 있다는 것이다.

이중 Nginx 방식:
호스트 PC에 Nginx를 설치하고, 이를 리버스 프록시로 사용하여 Docker 컨테이너 내의 앱으로 트래픽을 전달한다. 호스트 PC의 Nginx에서 HTTPS를 설정한다.
Docker 컨테이너 내에도 Nginx를 두어 React 앱을 서빙한다. (이 Nginx는 HTTPS 설정 없이 그냥 사용한다.)
이 방식의 장점은 호스트 PC의 Nginx가 HTTPS를 관리하므로, 컨테이너를 자유롭게 재시작하거나 변경하는 것이 더 쉽다는 것이다.

필자는 이중 Nginx 방식으로 진행하겠다.

SSL 적용

이전에 진행하였던 프로젝트를 ssl적용시켜 보겠다.

0. ec2 보안그룹 443 포트 포워딩

기본적으로 ssl은 443을 사용하기 때문에 ec2 보안그룹에 접속해서 인바운드 규칙을 생성한다.

1. 호스트 pc에 Nginx 설치 및 SSL 설정

호스트 pc로 접속하고 Nginx를 설치한다.

sudo apt update
sudo apt install nginx

sudo apt install certbot python3-certbot-nginx

2. 인증서 획득

Certbot을 사용하여 인증서를 획득한다. 웹 서버(Nginx)를 직접 제어하지 않으므로, 일반적으로 standalone모드를 사용하여 인증서를 받아야 한다. 80번 포트를 잠시 사용 가능해야 하므로 중지하고 실행시키도록 하자

sudo certbot certonly --standalone -d [yourdomain.com]

위 명령을 실행하면, Certbot은 도메인의 소유권을 확인하기 위해 잠시 HTTP 서버를 실행한다. 인증서가 성공적으로 발급되면 /etc/letsencrypt/live/[yourdomain.com]/ 디렉터리에 저장된다.

3. 리버스 프록시 설정

호스트 PC의 Nginx에서 리버스 프록시 설정을 통해 Docker 컨테이너 내의 앱으로 트래픽을 전달하도록 설정해야 한다.
/etc/nginx/sites-available/default 파일을 수정하여 아래의 리버스 프록시 설정을 추가한다.

server {
    listen 80;
    server_name [your_domain.com];
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name [your_domain.com];

    ssl_certificate /etc/letsencrypt/live/[your_domain.com]/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/live/[your_domain.com]/privkey.pem;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;

    location / {
        proxy_pass http://localhost:[8081]; # 맞게 변경한다.
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

4. Docker 컨테이너에 설정 변경

docker-compose.yml 파일에 인증서의 경로를 볼륨으로 연결해야 한다.
또한 기존의 서비스가 80포트를 사용한다면, 충돌하기 때문에 포트번호를 변경해야 한다.

react-app:
  ...
  ports:
      - "8081:80"
  volumes:
    - /etc/letsencrypt:/etc/letsencrypt

5. Jenkins shell script 수정

docker-compose를 통해 인증서를 연결 시켜줬기 때문에 기존의 docker pull, docker run 방식을 변화 시켜야한다.

최신 이미지 pull 및 실행
docker pull bangjinseong/my-react-app:${BUILD_NUMBER}
docker run -d -p 80:80 bangjinseong/my-react-app:${BUILD_NUMBER}

react-app 서비스 이미지를 최신으로 업데이트
docker-compose pull react-app
react-app 서비스만 재시작
docker-compose up -d react-app

로 변화시킨다.

docker-compose up -d react-app을 한다면, docker-compose.yml파일 중에 react-app파일만 실행시킨다.

6. Jenkins 컨테이너 안에 docker-compose 설치

하지만, 이렇게 되면 jenkins 컨테이너 안에서 docker-compose 명령어를 실행시킬 수 있어야 하기 때문에, 컨테이너 안에 docker-compose를 설치해준다.

docker exec -it [JENKINS_CONTAINER_NAME] /bin/bash

로 컨테이너 안에 접속해준 뒤

curl -L "https://github.com/docker/compose/releases/download/1.28.5/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

를 통해 docker-compose를 설치해준다.
이렇게 하면 jenkins shell script로 docker-compose 명령어를 실행시킬 수 있게 된다.

7. 리디렉션 횟수가 너무 많습니다. 오류

필자는 sudo systemctl restart nginx를 통해 해결하였다.
sudo nginx -t를 통해 Nginx 설정을 테스트할 수 있고,
/var/log/nginx/error.log 파일을 확인하여 관련 오류 메시지나 경고를 찾아볼 수 있다.

profile
야호

0개의 댓글