이 포스트는 ec2 인스턴스에 운영 중인 웹사이트에 도메인을 연결하는 방법을 정리한다.

도메인 구매는 hosting.kr 에서 했으며 그 과정은 생략한다.

 

aws에서 ec2 와 도메인을 연결하기 위해선 route53 를 이용 해야한다.

route 53이란 DNS관리, 트래픽 관리, 가용성 모니터링, 도메인 등록 등을 제공하는 aws 서비스이다.

도메인을 ec2 인스턴스로 운영하는 서버에 할당하기 위해서는 크게 다음과 같은 절차를 따르게 된다.

1. 호스팅 영역 생성

2. 레코드 생성 (레코드란 특정 도메인의 트래픽을 어떻게 라우팅 할 것인지에 대한 정보를 담고 있는 객체이다)

3. 네임서버 주소 변경

 

이제 각 단계에 대해 자세히 정리 해보자.

 

호스팅 영역 생성

호스팅 영역이란 레코드의 컨테이너이고 레코드란 특정 도메인과 그 하위 도메인의 트래픽을 어떻게 라우팅 해야 하는지에 대한 정보를 담고 있다.

호스팅 영역을 생성 할때 설정해야 하는 값은 1. 도메인 이름, 2. 유형, 3. 태그 이다.

  • 도메인 이름은 내 서버에 할당한 url 값이다.
  • 유형은 퍼블릭과 프라이빗 두 가지가 있는데 아무나 접속할 수 있게 하기 위해선 퍼블릭을 선택한다.
  • 태그는 aws 리소스에 할당하는 레이블로 각 리소스를 관리하기 편하게 할당하는 이름 이라고 보면된다.

Fig 1. 호스팅 영역 생성 페이지

 

레코드 생성

호스팅 영역을 생성하고 나면 다음과 같은 레코드 정보를 볼 수 있다.

Fig 2. 레코드 정보

여기서 레코드 이름은 등록한 도메인에 해당한다. 이 도메인으로 오는 트래픽을 처리하는 규칙을 정의한 것이다.

유형은 보면 NS와 SOA 두 가지가 있다. 이는 호스팅 영역 생성시 자동으로 생성되는 레코드이다.

NS는  네임서버로 "호스팅 영역에 대한 신뢰할 수 있는 이름 서버 네 개를 나열한다."

네임서버의 역한은 도메인 이름과 IP의 상호변환을 가능하게 해주는 서버이다.

"SOA 레코드는 도메인에 대한 기본 DNS 정보를 식별한다" 라고 하는데 이건 이해가 잘 안간다. 더 이해가 되면 다시 정리 해야겠다.

 

ec2 인스턴스에 도메인을 연결하는게 목적이니 도메인 이름에 해당 하는 ip가 뭔지를 알려주기 위해 레코드를 생성해야 한다.

레코드 생성을 누르고 아래와 같은 화면이 나타나면 "값"을 입력하는 란에 이 도메인을 연결한 ec2 인스턴스의 ip를 입력하면 된다.

Fig 3. 레코드 생성 페이지

DNS 서버 설정

 레코드 생성 까지 했으면 이제 도메인을 구입했던 업체의 홈페이지로 접속해 네임서버를 변경해야 한다. 도메인을 구입하면 각 업체에서 해당 도메인으로 트래픽을 어떻게 처리 할지 쿼리할 네임버서를 자동으로 몇가지 설정하게 된다.

 나는 이렇게 자동으로 등록된 네임 서버가 아니라 aws route53의 DNS를 사용 할 것이므로

"pmanage.info(내 도메인)으로의 트래픽은 aws DNS 로 문의해 어떻게 routing할지 결정하세요"라고 지정하기 위해 이 과정이 필요하다.

 도메인 구입 업체의 웹페이지에 접속해 네임버서 관리 페이지에 접속한다.

나의 경우 hosting.kr 에 접속해 로그인을 하고 "도메인 관리->나의 도메인 -> 네임서버/DNS" 에서 바꿀 수 있다.

바로 위 "레코드 생성" 섹션의 Fig 2에서 NS 유형의 값에 있는 서버 주소를 아래와 같이 입력 한 후 저장하면 된다.

 

Fig 4. DNS 서버 변경 페이지

이렇게 등록 하고 나면 끝이다.

 

다만 바로 해당 도메인으로 접속하면 바로 접속은 안되는데 도메인 구입 후 2~3일이 지나야 한다고 한다.

나는 어제 구입했으니 2틀 뒤 다시 해당 도메인으로 접속해 보고 안되면 디버깅을 해야겠다.

- 끝 -

 

django app 공개 운영을 위해 [Django] 장고 앱 공개 운영 포스트 Fig 1의 nginx, mysql, django app을 하나의 ec2 인스턴스에 각각 도커 컨테이너로 실행 하려고 계획을 하고 서버를 실행했지만 이 방식에 큰 단점이 있어 아키텍쳐를 변경하기로 했다. 

 

이 포스팅은 aws RDS 인스턴스를 생성해 ec2 인스턴스와 연동하는 방법에 대해 정리한다.

 

목표

Fig 1. 아키텍쳐 변경 개요

Fig 1. (a)는 처음 계획한 운영 아키텍쳐로 ec2 instance 하나에 nginx, django app, mysql 3개를 각각 도커 컨테이너로 실행하는 방식이었고 Fig 1.(b)는 변경하고자 하는 아키텍쳐로 ec2 instance에는 nginx, django app만 운영하고 mysql은 aws RDS 인스턴스로 분리 운영 하는 방식이다. 

 

기존 아키텍쳐의 문제

Fig 1.(a) 처럼 아키텍쳐를 설계하는 것에는 다음과 같은 문제 점이 있었다. 

 

1. cpu 성능: 현재 테스트 운영에 사용하고자 하는 aws 프리티어 계정으로 만들수 있는 ec2 인스턴스는 vcpu 1개 , ram 1GB 가 한계 스펙이다. 이 성능으로 (a)와 같이 아키텍쳐를 구성한 결과 심심치 않게 cpu 사용률이 70% 이상으로 치솟는 경우가 발생했다. 

 

2. database backup: 나는 database 전문가가 아니라 EBS를 비휘발성으로 설정해 database backup 설정을 하고 실패 없이 관리한 자신이 없었다. 

 

위와 같은 문제를 해결하기 위해 mysql을 ec2에 설치해 운영 하지 않고 Fig 1. (b) 처럼 별도 RDS인스턴스로 분리하기로 결정했다.

 

Fig 1. (a) 처럼 운영하는 것도 장점은 있다. RDS는 비용이 생각 보다 비싼데 database를 잘알고 백업 보안 schema를 잘 설정 할 수 있다면 ec2 를 이용하는 게 비용적인 측명에서 더 좋다고한다.

 

RDS 인스턴스 생성

RDS 인스턴스 생성을 위해서는 aws console 검색 창에 RDS 를 검색 한후 'rds console -> 데이터베이스 -> 데이터베이스 생성' 을 클릭하면 된다. 

나의 경우 mysql rds 인스턴스를 생성했다. mysql의 경우  라이선스가 GNU v2.0 으로 별도 라이선스 비용이 들어가지 않는다. 아래 그림 처럼 표준 생성에서 '엔진 옵션->Mysql' 을 선택하고 버전을 기존 사용 하던 8.0.31 로 설정했다.

다음으로 아래 그림의 제일 위는 템플릿을 선택하는 과정인데 나는 당연히 월 750시간 사용이 무료인 계정이니 '프리 티어'를 선택했다. '프리 티어' 템플릿을 선택하면 '가용성 및 내구성'은 자동으로 '단일 DB 인스턴스'로 설정된다. 

그 아래에서는 'DB 인스턴스 식별자'를 입력하는데 여기서 입력하는 이름이 'rds console -> 데이터베이스'에 들어가면 나오는 db 인스턴스 식별자이다. 자신의 용도에 맞게 직관적인 이름을 넣으면 된다.

자격증명은 mysql 서버에 접속 할때 사용하는 user id 와 password 이다. 

인스턴스 클래스는 정보는 link에 매우 상세하게 나와있으니 정확한 정보는 링크를 통해 확인하고 여기선 간단히만 정리하자. 

 

  • 스탠다드 클래스 : 컴퓨팅, 메모리 및 네트워크 리소스의 균형을 제공하며 많은 데이터베이스 워크로드에 좋은 선택. 스탠다드 클래스는 대부분의 일반적인 데이터베이스 요구사항을 충족 할수 있는 사양이다.
  • 메모리 최적화 클래스: 메모리에서 대용량 데이터 집합을 처리하는 워크로드의 성능을 가속화합니다. 높은 처리 성능이 요구되는 경우에 적합하다. 메모리를 더 많이 확보하면 더 많은 데이터를 메모리에 저장하고 이는 쿼리 시간 단축으로 이어질 확률이 높으므로..
  • 버스터블 클래스: 기준 수준의 CPU 성능과 함께 기준 수준 이상으로 버스트할 수 있는 기능을 제공합니다. 여기서 버스트란 순간 확장으로 순간적으로 더많은 리소스를 필요로 하는 경우 이를 가능하게 한다는 의미 이다. 

'프리 티어' 계정의 소유자인 나에게 허락된건 버스터블 클래스 이므로 이걸 선택한다. (사실 이거면 나에겐 충분하기도 하다)

스토리지는 범용 ssd로 세팅하고 프리티어에 주어진 20gb 를 할당한다. 스토리지 자동 조정은 할당한 크기 이상의 용량을 어플리케이션이 사용하고자 할때 자동으로 할당량을 조정해 주는 것이다. 즉 비용 증가로 이어질 수 있다.

이제 생성한 rds 인스턴스와 연결할 ec2 리소를 선택한다. ec2 인스턴스 에서 자신이 원하는 어플리케이션이 서버가 동작하는 ec2 인스턴스를 선택하면 된다.  ec2 인스턴스를 선택하면 VPC 는 자동 할당 된다. 

'퍼블릭 엑세스' 에서 '예'

를 선택하면 외부(같은 VPC에 속하지 않은 host)에서 생성할 mysql 서버에 접속할수 있다. "아니오"를 선택하면 이 DB 인스턴스와 같은 VPC 에 속한 ec2 인스턴스에서만 접속 가능하다. 

이 후로도 '데이터베이스 인증' 설정이 있는데 mysql 접속시 사용할 사용자 인증 방식에 대한 설정이다.

RDS와 ec2 인스턴스 연동

RDS 인스턴스 생성시 '퍼블릭 액세스 가능' 을 선택했거나 연동 하고자 하는 ec2 instance와 같은 VPC에 속하도록 세팅 했다면 연동자체는 매우 쉽다. 

 

퍼블릭 액세스 가능 한지 아닌지는 RDS console-> 데이터베이스 -> 인스턴스 상세 정보의 '연결 & 보안' 탭을 보면 알 수 있다. 

아래 그림의 가장 오른 쪽 보안 섹션을 보면 '퍼블릭 액세스 가능' 항목에 '예' 라고 되어 있으면 localhost(본인의 workstation이나 laptop)에서 도 접속이 가능 한 상태 이다. 

 

 

1. 퍼블릭 액세스 가능 선택한 경우

로컬에서 terminal을 열고 접속을 위해 사용했던 ip 대신 위 그림의 '앤드포인트' 밑의 주소를 이용 하면 된다. 

위 그림의 예를 들자면 mysql -h 옵션의 값으로 '앤드포인트' 값을 사용 하고 -P 옵션으로 '포트'를 지정한다. 

-u 옵션로 데이터베이스 생성시 지정한 사용자 id를 입력하면 된다. 

mysql -h product.cie6ndifnblb.ap-northeast-2.rds.amazonaws.com -P 3306 -u admin -p

product.cie6ndifnblb.ap-northeast-2.rds.amazonaws.com

 

2. 퍼블릭 액세스 가능 의 값이 '아니오' 인 경우

퍼블릭 액세스가 불가능한 경우 접속하고자 하는 데이터베이스와 같은  vpc(vitual private cloud)에 속한 ec2 인스턴스에 연결해  

'퍼블릭 액세스 가능' 한경우와 똑같이 '앤드포인트' 정보를 이용해 접속할 수 있다. 

mysql -h product.cie6ndifnblb.ap-northeast-2.rds.amazonaws.com -P 3306 -u admin -p

 

추가 작업

나의 경우 docker-compose 로 서버를 실행 하므로 위의 rds database instance 앤드포인트 정보로 docker-compose.yml 정보를 업데이트 해줘야한다. 환경변수를 선언하는 environment의 DB_HOST_ADDRESS 값에 database 앤드포인트를 할당한다.

(django app 실행 전에 새로 만든 mysql 서버에 django app에서 사용 하는 database를 생성하고 django app에서 database 를 migrate 하는 절차를 반드시 실행해야 한다.)

version: "3.7"
services:
  nginx:
    container_name: web_server
    restart: on-failure
    image: nginx:stable
    volumes:
      - ${PWD}/etc/jnbdrive_nginx:/etc/nginx/sites-enabled/default
      - ${PWD}/etc/nginx.conf:/etc/nginx/nginx.conf:ro
      - ${PWD}/staticfiles:/home/nginx/www/static
    ports:
      - 80:80
    environment:
      DJANGO_HOST: django_app

  django_app:
     container_name: django_app
     build: .
     image: django_app:latest
     ports:
       - 8000:8000
     restart: always
     environment:
       DB_PORT: 3306
       DB_HOST_ADDRESS: product.cie6ndifnblb.ap-northeast-2.rds.amazonaws.com # rds instance endpoint 
     tty: true
     networks:
       - backend
     volumes: 
       - ${PWD}:/home/docker/workspace/django_app
     command: ./start_server.sh

networks:
  backend:
    # Use a custom driver
    driver: bridge

 

- 끝 -

EC2 인스턴스에서 실행 중이던 앱에 접속이 안되어 인스턴스 상태 확인을 해보니 상태검사 1/2개 통과 라는 메시지를 발견해 이를 해결하기 위한 과정을 정리해본다.

-> 시스템 로그의 정확한 분석에 실패해 나의 경우 해결은 아직 못했다.(2023.01.21)

Fig 1.상태 검사 실패 화면

상태 검사

Amazon ec2는 아래 두 가지 상태 확인을 통해 각 ec2 인스턴스 상태를 모니터링한다.

1. 시스템 상태 확인

시스템 상태 확인은 인스턴스가 실행되는 기본 호스트에서의 문제를 탐지합니다. 네트워크, 하드웨어 또는 소프트웨어 문제로 인해 기본 호스트가 응답하지 않거나 이에 연결할 수 없는 경우 이 상태 확인에 실패합니다.

 

2. 인스턴스 상태 확인

인스턴스 상태 확인 실패는 인스턴스의 연결 가능성에 문제가 있음을 나타냅니다. 이 문제는 다음과 같은 운영 체제 수준 오류로 인해 발생합니다.
1. 운영 체제 부팅 실패
2. 올바른 볼륨 탑재 실패
3. CPU 및 메모리 소진
4. 커널 패닉
5. 네트워크가 작동하지 않음

 

위 두 가지중 어떤것이 문제인지 파악하기 위해서는 'ec2 콘솔 -> 인스턴스 -> 상태  검사' 탭을 참조하면 알 수 있다.

아래는 문제가 생긴 내 인스턴스의 상태 검사 탭인데 나의 경우  시스템 상태 검사 : 통과, 인스턴스 상태 검사: 인스턴스 연결성 검사 실패 였다.

Fig 2. 상태 검사 세부정보

 

원인 분석

인스턴스 상태 검사를 통과 하지 못한 경우 원인 분석을 위해 시스템 로그를 확인하고 시스템 로그에 있는 데이터에 따라 그에 맞는 해결 방법을 적용해야 한다.

 

1. 인스턴스 리부트: ec2 console -> 인스턴스 ->인스턴스 상태 -> 인스턴스 재시작

2. 시스템 로그 확인: 재시작 후 인스턴스 상태가 '실행중' 이면 -> 작업 -> 모니터링 및 문제해결 -> 시스템 로그 가져오기

 

Fig 3. 시스템 로그 가져오기 화면

누르면 다음과 같이 로그를 볼 수 있고 다운로드 할 수 도 있다.

Fig 4. system log

 

분석 결과

aws 에서는 친절하게도 위 로그에서 발견 할수 있는 대표적인 error 들을 정리해  분석시 참조 할 수 있게 제공한다.

link: Troubleshoot system log errors for Linux-based instances 

 

하지만 아쉽게도 내 시스템 로그에는 위에 해당 하는 에러는 없었다. 의심 가는 로그는

'GRUB failed boot detection' 라는 문구 인데 직접적인 관련이 있는지는 아직 모르겠다.

더 분석해 봐야겠다.

 

 

참고 자료: https://aws.amazon.com/ko/premiumsupport/knowledge-center/ec2-linux-status-check-failure/

 

연결할 수 없는 EC2 Linux 인스턴스의 상태 확인 실패 문제 해결

닫기 Gurkamal 씨의 동영상을 보고 자세히 알아보기(9:28)

aws.amazon.com

 

이 포스트는 aws ec2 인바운드 규칙 변경 방법을 정리한다. 

 

상황:

ec2 인스턴스에 nginx 서버를 띄우고 'wget my.ip.address' 로 통신 확인을 하니 응답이 오지 않고 timeout 이 발생해서 해결방법을 알아 보다 aws ec2 보안 그룹이 80번 포트를 오픈 하지 않아서 라는 이유를 발견하고 이에 대한 해결책으로 본 포스팅을 작성한다.

 

인바운드 규칙 변경:

aws ec2 는 보안그룹 설정이 있다. 'ec2 -> 인스턴스->보안 텝'에 가면 아래와 같은 정보를 볼수 있다. 이때 인바운드 규칙을 보면 22, 443 번 포트만 open되어 있는 것을 확인 할 수 있다.

Fig 1. ec2 인스턴스 보안 그룹 정보

아래 처럼 입력 하면 기본 http 서버 즉 80 번 포트로 접속을 시도 하기 때문에 허용되지 않은 포트라 페이지를 가져 오지 못한것이다. (내가 참고한 블로그에서는 aws 가 기본적으로 80번 포트를 오픈 해놨다고 했는데 잘못된 정보 였나 보다. )

wget 192.168.0.5

테스트를 위해 보안 그룹 인바운드 규칙에 80번 포트 허용을 추가 하자.

인바운드 규칙 추가를 위해 Fig 1. 에서 '보안 그룹' 밑에 있는 파란 글자 'sg-01c149~~~~'를 클릭하면 아래와 같은 화면이 나온다. 이 화면에서 우측하단에 보면 '인바운드 규칙 편집' 이라는 버튼이 있다.

클릭 하자.

Fig 2. 보안 그룹 정보

그럼 아래와 같은 화면이 나온다.

Fig 3. 인바운드 규칙 편집 창

좌측 하단에 규칙 추가를 클릭해서 '유형' Http를 검색해 추가 한 후 '소스' 에 0.0.0.0/0 을 추가 하면 아래와 같이 된다.

규칙 저장을 클릭 하면 변경 사항이 적용 된다.

Fig 4. 인바운드 규칙에 http 를 추가한 화면

저장 하고 보안 그룹의 인바운드 규칙을 보면 아래 그림과 같이 80번 포트를 허용이 추가된 것을 볼 수 있다.

Fig 5. 80 번 포트가 추가된 인바운드 규칙

 

wget 을 이용해 다시 테스트 해보니 이번엔 아래와 같이 응답을 받았다. 다만 gateway 에러가 났다.

일단 timeout이 아니라 응답을 받긴 했으니 이제 nginx 설정을 디버깅 해야겠다.

 - 끝 -

 

nginx 와 django app의 container를 분리 하기 위해 작업을 하던 중 발생한 이슈 상황과 해결 방법 정리

 

사용 docker compose file

version: "3.7"
services:
  nginx:
    container_name: web_server
    restart: on-failure
    image: nginx:stable
    volumes:
      - ${PWD}/etc/jnbdrive_nginx:/etc/nginx/sites-enabled/default
      - ${PWD}/etc/nginx.conf:/etc/nginx/nginx.conf:ro
      - ${PWD}/staticfiles:/home/nginx/www/static
    ports:
      - 80:80
    environment:
      DJANGO_HOST: django_app

  django_app:
     container_name: django_app
     build: .
     image: django_app:latest
     ports:
       - 8000:8000
     restart: always
     environment:
       DB_PORT: 3306
       DB_HOST_ADDRESS: mysql
     tty: true
     networks:
       - backend
     volumes: 
       - ${PWD}:/home/docker/workspace/django_app
     command: ./start_server.sh

networks:
  backend:
    # Use a custom driver
    driver: bridge

 

nginx 설정 파일

upstream app {
    server ${DJANGO_HOST}:8000;
}
server {
        listen 80;
        server_name 192.168.0.5; ##client 가 접속하는 도메인네임, 장고 app 의 서버 주소

        location = /favicon.ico { access_log off; log_not_found off; }

        location /static {
                autoindex on;
                alias /home/nginx/www/static;
        }

        location / {
                include proxy_params;
                proxy_pass http:app;
        }
}

 

발생 문제

issue 1. wget 192.168.0.5  명령시 nginx server에서 proxy server 로 보내는 요청에 대해 timeout 발생

aws ec2 인스턴스에서 기본적으로 80번 포트를 막고 있기 때문에 발생하는 상으로 보안그룹 설정에서 인바운드 규칙 변경하면 해결 가능.

아래 페이지 참조 [aws] 인바운드 규칙 변경

 

[aws] 인바운드 규칙 변경

이 포스트는 aws ec2 인바운드 규칙 변경 방법을 정리한다. 상황: ec2 인스턴스에 nginx 서버를 띄우고 'wget my.ip.address' 로 통신 확인을 하니 응답이 오지 않고 timeout 이 발생해서 해결방법을 알아 보

pajamacoder.tistory.com

 

issue 2. proxy_params  파일 없음 에러

web_server                  | nginx: [emerg] open() "/etc/nginx/proxy_params" failed (2: No such file or directory) in /etc/nginx/sites-enabled/default:13

nginx:latest docker 이미지를 사용 했는데 이 도커 이미지에는 /etc/nginx/proxy_params 파일이 존재 하지 않기 때문에 발생한는 에러이다.

/etc/nginx/proxy_params 파일은 pip install nginx 로 설치할 경우 자동으로 생성되었는데 이 도커 이미지에는 없어서 아래 방법으로 파일을 container 에 마운트 했서 해결했다.

issue 2 해결 방안: docker compose volumes 에 ' - /path/to/proxy_params:/etc/nginx/proxy_params' 옵션 추가

 

- 끝 -

django app을 공개 하기 위해 aws 계정을 만들고 프리티어 계정을 이용해 ec2 인스턴스에 환경 세팅을 하던 중 nginx 와 django app을 별도의 컨테이너로 운영 하고 싶어져 해당 내용을 정리 해본다.

 

즉 nginx,, django app, db server 를 각각 하나의 컨테이너로 분리해 아래 그림과 같이 container 1, container 2, container 3 으로 나누어 운영하는 것이다. 

(이외에도 분리 과정 중에 격었던 에러와 해결 방법을 [Django] nginx 와 django container 분리 에러 해결 페이지에 추가 정리 했다.)

Fig 1. 운영 개요도

 

 

이렇게 하려고 하다 보니 생기는 문제가 static 파일들을 어떻게 nginx 와 django app이 실행되는 container 에 모두 연결 할수 있는가 였다. 사실 어려운 문제는 아니지만 웹 운영에 익숙치 않는 나의 얕은 지식에서 비롯된 문제 였다.

 

내가 처음 헷갈렸던 문제는 다음과 같다.

이슈 1. container 1(nginx)와 container 2(django app)이 접근 또는 사용 하는 static 파일들은 물리적으로 같은게 좋은건가? 각각 동일한 파일들을 복사해서 따로 사용 하는게 좋은 걸까?

Answer: 실제 운영 환경에서 어떤지는 잘 모르겠다. 다만 static 파일이 다르면 django app에서 물리 파일이 추가/변경 될때 마다 nginx가 참조 하는 static 파일들을 django app의 최신 파일들과 싱크를 맞추는 과정이 필요하다.

 

이슈 2. container 1(nginx) 와 container 2(django app) 내에서 static 파일들의 절대 경로가 같아야 하는가?

Answer: 이럴 필요 전혀 없었다.

nginx 를 실행 하는 container 상의 staticfile 위치와 django app 실행 하는 container 내의 staticfile 위치는 달라도 된다.

 

 

Container 분리를 위한 과정 및 설정

1. django app settings.py(내 경우 config/settings/prod.py 파일) 에 STATIC_ROOT=./staticfiles 를 파일 맨 밑에 추가.

django 에서 static 파일과 관련된 django setting.py 내의 변수들은 대략 5가지 인데 3가지만 정리 우선 정리 하면
1. STATIC_URL: 웹페이지에서 사용할 정적 파일들의 최상위 URL 경로. 실제 파일들의 물리적인 위치가 아니며 개념적인 경로로이고 반드시 '/'로 끝나야 한다.
2. STATICFILES_DIRS: 개발 단계에서 사용하는 정적(static)파일이 존재 하는 위치하는 경로를 설정하는 항목. 운영시에도 django app은 여기 정의된 위치에서 static 파일을 참조 한다고 한다.
3. STATIC_ROOT:django app에서 사용하는 모든 정적파일들이 모여 있는 디렉토리로 아래 collectstatic 명령 사용시 정적파일들이 복사 되는 위치이기도 하다.

2. 아래 명령을 실행해 static 파일들을 한 directory 에 모은다.

 python manage.py collectstatic

 

3. 이 directory 를 nginx container로 mount 하고 nginx server 설정 파일(django_app_server)에서 내 서버로 들어오는 요청이 static 파일 참조가 필요할 경우 mount한 위치에서 static 파일을 찾도록 아래와 같이 내용 변경.

upstream django_app{
        server 192.168.0.102:8000;
}
server {
        listen 80;
        server_name 192.168.0.102; ##client 가 접속하는 도메인네임, 장고 app 의 서버 주소

        location = /favicon.ico { access_log off; log_not_found off; }

        location /static {
                alias /home/nginx/www/static; ##docker compose 에서 volume 마운트 한 static 파일의 위치를 여기에 설정
        }

        location / {
                include proxy_params;
                proxy_pass http://django_app; # static 이 아닌 요청은 jnbdrive_app upstream 으로 요청 포워딩
        }
}

 

아래는 docker-compose.yml 파일이다. django_app_server 설정 파일과 staticfiles 파일의 마운트 위치를 잘 살펴 보자.

staticfiles은 nginx container의 /home/nginx/www/static 위치에 마운트 했고 이 이 위치를 django_app_server 설정에서 참조하도록 했다.

version: "3.7"
services:
  nginx:                 
    container_name: nginx
    restart: on-failure
    image: nginx:stable
    volumes:
      - ${PWD}/etc/django_app_server:/etc/nginx/sites-enabled/default # django app server 설정파일
      - ${PWD}/etc/nginx.conf:/etc/nginx/nginx.conf:ro
      - ${PWD}/etc/proxy_params:/etc/nginx/proxy_params  
      - ${PWD}/staticfiles:/home/nginx/www/static # <--- 이 라인이 static 파일을 마운트 하는 라인이다.
       
    ports:
      - 80:80
      - 443:443
    environment:
      DJANGO_HOST: jnb_web
    depends_on:
      - jnb_web

- 끝-

 

문제

django app 운영을 위해 aws ec2 인스턴스를 생성시 2개의 볼륨을 생성 후 인스턴스에 접속해 df -h 를 입력해 보니 아래와 같이 생성한 EBS 볼륨이 마운트 되지 않는 것을 발견했다.

Fig 1.

해결

ec2-> 볼륨 정보에 들어가서 생성한 볼륨 정보를 보니 아래와 같이 '/dev/sdb' 라는 볼륨이 있는 것을 확인 할수 있다.

Fig 2.

ec2 인스턴스에서 'ls /dev/sd?' 라고 검색해도 아무 것도 안나오는데

위의 볼륨 /dev/sdb 는 ec2 인스턴스내에서 /dev/xvdb 라는 dev 이름을 가지고 있기 때문이다.

aws 를 처음 접하는 나로서는 볼륨 정보 탭에 나온 정보와 인스턴스 내부의 이름이 달라 당황스럽지만 어쨋든 찾았다.

/dev/xvdb 에 대한 정보를 위해 fdisk 를 이용해 아래와 같이 8GB 가 할당된 볼륨임을 확인했다.

Fig 3.

lsblk 라는 명령으로도 볼륨 정보를 확인 할수 있다.  결과는 아래 처럼 나온다. (아래 결과는 내가 /xvda, /xvdb 봄륨의 용량을 각각 15GB, 10GB 로 수정 한 후의 결과이다.)

Fig 4.

파일 시스템 생성 및 마운트

위 정보를 보면 /xvdb 볼륨은 아직 파일시스템도 없고 접근가능한 마운트 위치도 없기 떄문에 사용이 불가능 하다.  이제 파일시스템을 생성하고 마운트 시켜 보자.

 

1. 파일 시스템 생성

나는 ext4 파일시스템을 생성 하기 위해 아래와 같은 명령을 사용했다. '/dev/xvdb'는 파일시스템을 생성하기 위한 타겟 볼륨명이다.

lsblk 나 fdisk 로 확인 가능 하다.

sudo mkfs -t ext4 /dev/xvdb

2. 마운트 위치 생성.

데이터 백업용으로 위 볼륨을 사용할 것이기 때문에 /mnt 아래 backup_storage 라는 폴더를 만들었다.

sudo mkdir /mnt/backup_storage

3. 마운트

sudo mount /dev/xvdb /mnt/backup_storage/

파일시스템과 마운트 위치가 위 설정 대로 되었는지 확인 하기 위해 아래 명령을 입력 한다. 

옵션  -T 는 파일시스템을 확인 하기 위해, H 는 사람이 읽기 편한 볼륨 크기를 표시하기 위해 사용했다.

df -TH

Fig 5.

위 결과를 보면 Fig 1 과 다르게 /dev/xvdb 가 ext4 라는 파일시스템을 가지고 있고 /mnt/backup_storage 에 마운트 된것을 확인 할 수 있다.

 

- 끝 -

Dockerfile 로 이미지 생성시 apt 을 이용해 패키지를 설치 하다 보면 time zone 설정을 위한 유저 인풋을 요구하는 경우가 있다.

이런 경우 이미지 생성을 위해 사용자가 처음부터 끝까지 대기 해야 하는 불편 함이 생긴다.

나의 경우 아래 이미지와 같은 사용자 입력을 요구하는 경우가 생겼다.

 

해결방법

timezone 관련 사용자 입력을 disable 하기 위해서는 DEBIAN_FRONTEND=noninteractive 을 추가해 주면 된다. 

전체 명령은 아래와 같다.

RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y libglib2.0-0 libsm6 libxrender-dev libxext6 git-all \
 && apt-get clean \
 && rm -rf /var/lib/apt/lists/

- 끝 -

+ Recent posts