새소식

Linux

Linux - Docker + nginx + ssl 인증 받기

  • -

준비물

  1. 도메인
  2. 도메인과 서버 연결
  3. 80, 443 port 열기

작업 디렉토리 구조

  1. nginx/default.conf 파일 생성
  2. docker-compose.yml 파일 생성
~.ssh/project
├── my-project # backend 서비스 파일
├── nginx
│   └── default.conf
└── docker-compose.yml

Docker 설치

# 필수 패키지 설치
sudo apt-get update
sudo apt-get install apt-transport-https ca-certificates curl software-properties-common
# Docker GPG key 추가
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
# Docker 저장소 추가
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Docker 설치
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
# Docker 서비스 시작 및 자동 시작 설정
sudo systemctl start docker
sudo systemctl enable docker

Docker Compose 설치

# Docker Compose 다운로드 및 설치
sudo curl -L "https://github.com/docker/compose/releases/download/$(curl -s https://api.github.com/repos/docker/compose/releases/latest | grep -Po '"tag_name": "\K.*?(?=")')/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# 실행 권한 추가
sudo chmod +x /usr/local/bin/docker-compose

# 설치 확인
docker-compose --version

~.ssh/project/nginx/default.conf 작성

events {
    worker_connections  1024;  # 각 워커 프로세스가 처리할 수 있는 동시 연결 수를 설정
}

http {
    server {
        listen 80;  # 80번 포트에서 HTTP 요청 수신

        server_name 도메인.com;  # 서버와 연결해둔 도메인

        location /.well-known/acme-challenge/ {
            allow all;  # /.well-known/acme-challenge/ 경로의 요청을 모두 허용
            root /var/www/certbot;  # 인증서 발급을 위한 파일들이 위치하는 디렉토리 지정
        }

        location / {
            return 301 https://$host$request_uri;  # 모든 다른 경로로의 요청은 HTTPS로 리다이렉트
        }
    }
}

~.ssh/project/docker-compose.yml 작성

version: '3'  # Docker Compose 버전

services:
  nginx:  # nginx 서비스 정의
    image: nginx:latest  # 사용할 Docker 이미지
    volumes:
      - ./nginx/default.conf:/etc/nginx/nginx.conf  # 호스트의 nginx 설정 파일을 컨테이너 내 nginx 설정 경로로 마운트
      - ./data/certbot/conf:/etc/letsencrypt  # 인증서 관련 설정을 담은 디렉토리를 컨테이너 내 /etc/letsencrypt 로 마운트
      - ./data/certbot/www:/var/www/certbot  # certbot이 사용할 웹 루트 디렉토리를 컨테이너 내 /var/www/certbot 로 마운트
    restart: always  # 컨테이너가 종료될 경우 항상 재시작
    ports:
      - 80:80  # 호스트의 80 포트를 컨테이너의 80 포트로 매핑
      - 443:443  # 호스트의 443 포트를 컨테이너의 443 포트로 매핑
    command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"  
      # 컨테이너 시작 시 실행할 명령어. nginx를 실행하고 주기적으로 설정을 다시 불러옴.

  certbot:  # certbot 서비스 정의
    image: certbot/certbot  # 사용할 Docker 이미지 지정
    volumes:
      - ./data/certbot/conf:/etc/letsencrypt  # 인증서 관련 설정을 담은 디렉토리를 컨테이너 내 /etc/letsencrypt 로 마운트
      - ./data/certbot/www:/var/www/certbot  # certbot이 사용할 웹 루트 디렉토리를 컨테이너 내 /var/www/certbot 로 마운트
    entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"  
      # 컨테이너 시작 시 실행할 진입점(entrypoint)을 설정. certbot을 주기적으로 갱신하는 작업을 반복적으로 수행.

docker 컨테이너 실행

cd ~/.ssh/project
docker-compose up # 출력되는 docker log를 보며 에러없이 정상 실행되는지 확인

인증서 발급 스크립트 실행

# 인증서 발급 스크립트 다운로드
curl -L https://raw.githubusercontent.com/wmnnd/nginx-certbot/master/init-letsencrypt.sh > init-letsencrypt.sh

# 인증서 발급 스크립트 권한 수정
chmod +x init-letsencrypt.sh

# domain, email 수정
vi init-letsencrypt.sh 
# 인증서 발급 스크립트 실행
sudo ./init-letsencrypt.sh

~.ssh/project/nginx/default.conf 수정

events {
    worker_connections  1024;  # 각 워커 프로세스가 처리할 수 있는 동시 연결 수를 설정
}

http {
    server {
        listen 80;  # 80번 포트에서 HTTP 요청 수신

        server_name 도메인.com;  # 서버와 연결해둔 도메인

        location /.well-known/acme-challenge/ {
            allow all;  # /.well-known/acme-challenge/ 경로의 요청을 모두 허용
            root /var/www/certbot;  # 인증서 발급을 위한 파일들이 위치하는 디렉토리 지정
        }

        location / {
            return 301 https://$host$request_uri;  # 모든 다른 경로로의 요청은 HTTPS로 리다이렉트
        }
    }

    server {
        listen 443 ssl;
        server_name 도메인.com;

        ssl_certificate /etc/letsencrypt/live/도메인.com/fullchain.pem; # 도메인.com 부분 꼭 수정할 것
        ssl_certificate_key /etc/letsencrypt/live/도메인.com/privkey.pem; # 도메인.com 부분 꼭 수정할 것
        include /etc/letsencrypt/options-ssl-nginx.conf;
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

        location / {
            proxy_pass http://backend:8080; # 요청을 backend 서비스로 프록시
            proxy_set_header Host $host; # 요청의 호스트 헤더 설정
            proxy_set_header X-Real-IP $remote_addr; # 클라이언트의 실제 IP 설정
        }
    }
}

~.ssh/project/docker-compose.yml 수정

version: '3'  # Docker Compose 버전

services:
  nginx:  # nginx 서비스 정의
    image: nginx:latest  # 사용할 Docker 이미지
    volumes:
      - ./nginx/default.conf:/etc/nginx/nginx.conf  # 호스트의 nginx 설정 파일을 컨테이너 내 nginx 설정 경로로 마운트
      - ./data/certbot/conf:/etc/letsencrypt  # 인증서 관련 설정을 담은 디렉토리를 컨테이너 내 /etc/letsencrypt 로 마운트
      - ./data/certbot/www:/var/www/certbot  # certbot이 사용할 웹 루트 디렉토리를 컨테이너 내 /var/www/certbot 로 마운트
    restart: always  # 컨테이너가 종료될 경우 항상 재시작
    ports:
      - 80:80  # 호스트의 80 포트를 컨테이너의 80 포트로 매핑
      - 443:443  # 호스트의 443 포트를 컨테이너의 443 포트로 매핑
    command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"  
      # 컨테이너 시작 시 실행할 명령어. nginx를 실행하고 주기적으로 설정을 다시 불러옴.

  certbot:  # certbot 서비스 정의
    image: certbot/certbot  # 사용할 Docker 이미지 지정
    volumes:
      - ./data/certbot/conf:/etc/letsencrypt  # 인증서 관련 설정을 담은 디렉토리를 컨테이너 내 /etc/letsencrypt 로 마운트
      - ./data/certbot/www:/var/www/certbot  # certbot이 사용할 웹 루트 디렉토리를 컨테이너 내 /var/www/certbot 로 마운트
    entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"  
      # 컨테이너 시작 시 실행할 진입점(entrypoint)을 설정. certbot을 주기적으로 갱신하는 작업을 반복적으로 수행.

  backend: # backend 서비스
    build:
      context: ./my-project # 빌드 컨텍스트
      dockerfile: Dockerfile # Dockerfile 경로
    ports:
      - "8080:8080" # 호스트:컨테이너 포트 매핑

Docker 컨테이너 재실행

docker-compose down
docker-compose up
반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.