댓글

  • 대댓글(무한) 가능하게 구성
  • 게시글의 댓글을 가져올 때, 중복되지 않게 가져오기
  • url 최대한 깔끔하게 사용하기

 

# ================================
urlpatterns = [
    path("<int:place_id>/comment/", views.PlaceCommentView.as_view(),
         name='place_commment_view'),
    path("<int:place_id>/comment/<int:place_comment_id>/", views.PlaceCommentDetailView.as_view(),
         name='place_commment_detail_view'),
]


# ================================
class PlaceCommentView(APIView):

    # (프론트) 해당 게시글 댓글 가져오기
    # 중복 없이 가져오기
    def get(self, request, place_id):  # ✔️
        place = get_object_or_404(Place, id=place_id)
        
        query = place.place_comment_place.filter(main_comment=None)
        serializer = PlaceCommentSerializer(query, many=True)
            
        return Response(serializer.data)
        

# ================================
# 댓글 출력을 위한 오버라이딩
class RecursiveSerializer(serializers.Serializer):
    def to_representation(self, instance):
        serializer = self.parent.parent.__class__(instance, context=self.context)
        return serializer.data


# place 댓글 시리얼라이저
class PlaceCommentSerializer(serializers.ModelSerializer):
    reply = serializers.SerializerMethodField()
    # slug_field : Place 모델의 id
    place = serializers.SlugRelatedField(queryset=Place.objects.all(), slug_field='id')
    
    class Meta:
        model = PlaceComment
        fields = ['id', 'user', 'place', 'content', 'main_comment', 'created_at', 'updated_at', 'reply']
        
    def get_reply(self, instance):
        serializer = self.__class__(instance.reply, many=True)
        serializer.bind('', self)
        return serializer.data

 

 

 

역할 분담

 

 

오늘의 커밋

 

[Feat] : place 대댓글 기능 추가
 

-views 생성 : 댓글, 대댓글, 좋아요 기능 추가
-views 추가 : 상세보기 댓글 시리얼라이저 추가
-views 수정 : 권한 수정 (is_admin -> is_staff), Response 컨벤션 맞춰 변경
-models 수정 : category, like 테이블 추가, image -> PlaceImage 모델로 분리
-serializers 수정 : 이미지 시리얼라이저, 대댓글 시리얼라이저 추가 및 필드 순서 변경
-urls 제거 : 대댓글 urls 제거

 

 

+) 내일 할 일

  • 다중 이미지 수정
  • 댓글 삭제시 하위 댓글(대댓글)은 삭제되지 않게 수정

postgresql이란?

  • 오픈 소스 데이터베이스로 무료로 사용 가능합니다.
  • 또한 장고에서는 기본 데이터베이스로 postgresql을 사용하는 것을 권장하고 있습니다.
  • docker에서 사용 가능한 이미지들은 https://hub.docker.com 에서 제공하고 있습니다.

# 백업하기
mkdir backup
sudo mv ./* ./backup/
# 전체 삭제
sudo rm -rf ./*
ls -l
sudo docker ps -a
sudo docker rm -f 24 36  #숫자는 컨테이너 id
sudo docker volume prune
# 사용되지 않는 모든 것을 삭제
sudo docker system prune -a
vi docker-compose.yml
version: '3.8'

volumes:
  postgres: {} # postgresql에서 사용 할 볼륨 지정

services:
  postgres:
    container_name: postgres
    image: postgres:14.5
    volumes:
      - postgres:/var/lib/postgresql/data/
    environment: # postgresql 컨테이너에서 사용할 환경변수 지정해주기
      - POSTGRES_USER=user # 데이터베이스 사용자 지정
      - POSTGRES_PASSWORD=P@ssw0rd # 사용자 비밀번호 지정
      - POSTGRES_DB=django # 데이터베이스 이름 지정
    restart: always
sudo docker compose up -d

 

 

 

 

 

gunicorn이란?

  • django 프로젝트를 실행할 때 사용되는 runserver와 같이, 사용자의 요청을 받아 django에 작성한 코드를 실행시켜 주도록 하는 역할을 해줍니다.
  • 단순하게 생각해서 배포용으로 사용되는 runserver라고 생각해도 무관합니다.
  • 기본적으로 runserver는 배포용이 아닌 개발용으로 사용되는 명령어이며, 공식 문서에서도 runserver로 배포하는 것을 권장하지 않고 있습니다.
  • runserver는 기본적으로 싱글 스레드에서 동작하지만, gunicorn은 멀티 스레드로 동작하도록 설정할 수 있기 때문에 많은 요청을 더 효율적으로 처리할 수 있습니다.
mkdir backend
cd backend/
git clone https://github.com/sparta-course/drf-project.git ./django
# 경로 변경시 추후에 docker compose 파일에서 볼륨을 잡아줄 때 수정이 필요함
vi django/drf_project/settings.py
# 아래 코드로 변경
ALLOWED_HOSTS = ['*']
STATIC_ROOT = BASE_DIR / "static"
# timezone 변경
sudo ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime
date
vi Dockerfile
# python 3.10.8버전 이미지를 사용해 빌드
# 프로젝트와 일치시키는 것을 권장
FROM python:3.10.8

# .pyc 파일을 생성하지 않도록 설정합니다.
ENV PYTHONDONTWRITEBYTECODE 1

# 파이썬 로그가 버퍼링 없이 즉각적으로 출력하도록 설정합니다.
ENV PYTHONUNBUFFERED 1

# /app/ 디렉토리를 생성합니다.
RUN mkdir /app/

# /app/ 경로를 작업 디렉토리로 설정합니다.
WORKDIR /app/

# requirments.txt를 작업 디렉토리(/app/) 경로로 복사합니다.
COPY ./django/requirements.txt .

# 프로젝트 실행에 필요한 패키지들을 설치합니다.
RUN pip install --no-cache-dir -r requirements.txt

# gunicorn을 사용하기 위한 패키지를 설치합니다.
RUN pip install gunicorn
cd ..
vi docker-compose.yml
version: '3.8'

services:
  backend:
    container_name: backend
    build: ./backend/
    # drf_project.wsgi는 프로젝트 경로에 맞게 지정해야 합니다.
    entrypoint: sh -c "python manage.py collectstatic --no-input && python manage.py migrate && gunicorn drf_project.wsgi --workers=5 -b 0.0.0.0:8000"
    ports:
      - 80:8000
    volumes:
      - ./backend/django/:/app/
      - /etc/localtime:/etc/localtime:ro # host의 timezone 설정을 컨테이너에 적용합니다.
      # ro 은 읽기 전용(read only) 속성으로 볼륨을 설정하는 것을 의미합니다.
    restart: always

 

entrypoint의 명령어는 아래와 같이 나눠서 해석할 수 있습니다.

더보기

sh -c : 컨테이너에서 뒤에 작성한 명령어를 실행시킬 수 있도록 해줍니다.

&& : 특정 명령어를 실행한 이후 다음 명령어를 실행시켜 줍니다.

python manage.py collectstatic --no-input : 배포를 위해 static 파일을 모아줍니다. 해당 명령어를 실행시키기 위해서는 settings.py에 STATIC_ROOT가 정의되어 있어야 합니다.

python manage.py migrate : django에 연결된 db를 migrate 해줍니다.

gunicorn project_name.wsgi --workers=5 -b 0.0.0.0:8000 : gunicorn을 사용해 django 프로젝트를 실행시킵니다.

  • project_name : django 프로젝트 이름을 입력합니다. 이름을 다르게 입력할 경우 에러가 발생합니다.
  • --workers=5 : django를 실행시킬 process 갯수를 입력합니다. 일반적으로 cpu 코어 갯수 * 2 + 1만큼 지정해줍니다.(ex - 2코어라면 2*2+1=5)
  • -b 0.0.0.0:8000 : 8000번 포트로 실행시킵니다.
sudo docker compose up -d
sudo docker compose logs -f

 

 

 

 

 

nginx란?

  • nginx는 클라이언트의 request 요청을 처리해주는 웹 서버(web server)입니다.
  • reverse proxy, 로드밸런싱, 캐싱 등의 기능을 지원하며, 클라이언트의 요청을 nginx가 받은 후 service(django) 데이터를 넘겨주는 역할을 해줍니다.
  • 로드밸런싱을 활용해 트래픽을 분산할 수 있습니다.
  • SSL 기능을 사용해 데이터를 안전하게 전달할 수 있습니다.
  • reverse proxy 기능을 통해 client에서 서버에 직접적으로 접근하는 것을 막아줍니다.
  • 콘텐츠를 캐싱하여 동일한 요청에 대해 더 빠른 속도로 처리할 수 있게 해줍니다.

 

 

 

vi docker-compose.yml
version: '3.8'
services:
  nginx:
    container_name : nginx
    image: nginx:1.23.2
    ports:
      - "80:80" # http 포트포워딩
      - "443:443" # https 포트포워딩
    restart: always
sudo docker compose up -d

# 장고가 이미 80번 포트를 사용하고 있으므로 에러가 남
sudo docker ps
sudo docker rm -f c8 92  # 숫자는 본인 컨테이너 ID
sudo docker compose up -d
sudo docker compose logs -f

 

 

 

 

 

nginx / postgresql / django 연동하기

mkdir nginx
vi nginx/default.conf
server {
  listen 80;
  server_name _; # 모든 도메인 혹은 ip로 들어오는 요청에 대해 처리해 줍니다.

  location / { # nginx로 요청이 들어왔을 때
    proxy_pass http://backend:8000/; # backend 컨테이의 8000번 포트로 전달합니다.
  }

  location /static/ { # 브라우저에서 /static/ 경로로 요청이 들어왔을 때
    alias /static/; # /static/ 경로에 있는 파일들을 보여줍니다.
  }

  location /media/ { # 브라우저에서 /media/ 경로로 요청이 들어왔을 때
    alias /media/; # /media/ 경로에 있는 파일들을 보여줍니다.
  }
}
vi backend/django/drf_project/settings.py
# 해당부분 수정하기
import os

# 환경변수에 따라 DEBUG모드 여부를 결정합니다.
DEBUG = os.environ.get('DEBUG', '0') == '1'

# 접속을 허용할 host를 설정합니다.
ALLOWED_HOSTS = ['backend', ]

# postgres 환경변수가 존재 할 경우에 postgres db에 연결을 시도합니다.
POSTGRES_DB = os.environ.get('POSTGRES_DB', '')
if POSTGRES_DB:
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql',
            'NAME': POSTGRES_DB,
            'USER': os.environ.get('POSTGRES_USER', ''),
            'PASSWORD': os.environ.get('POSTGRES_PASSWORD', ''),
            'HOST': os.environ.get('POSTGRES_HOST', ''),
            'PORT': os.environ.get('POSTGRES_PORT', ''),
        }
    }

# 환경변수가 존재하지 않을 경우 sqlite3을 사용합니다.
else:
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': BASE_DIR / 'db.sqlite3',
        }
    }

# CORS 허용 목록에 ec2 ip를 추가합니다.
CORS_ORIGIN_WHITELIST = ['http://$ec2_public_ip']
# ex) CORS_ORIGIN_WHITELIST = ['http://43.201.72.190']

# CSRF 허용 목록을 CORS와 동일하게 설정합니다.
CSRF_TRUSTED_ORIGINS = CORS_ORIGIN_WHITELIST
sudo docker compose down
sudo docker ps -a
vi docker-compose.yml
version: '3.8'

volumes:
  postgres: {}
  django_media: {}
  django_static: {}

services:
  postgres:
    container_name: postgres
    image: postgres:14.5
    volumes:
      - postgres:/var/lib/postgresql/data/
    environment:
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=P@ssw0rd
      - POSTGRES_DB=django
    restart: always

  backend:
    container_name: backend
    build: ./backend/
    entrypoint: sh -c "python manage.py collectstatic --no-input && python manage.py migrate && gunicorn drf_project.wsgi --workers=5 -b 0.0.0.0:8000"
    volumes:
      - ./backend/django/:/app/
      - /etc/localtime:/etc/localtime:ro
      - django_media:/app/media/ # nginx에서 media를 사용할 수 있도록 volume을 지정해줍니다.
      - django_static:/app/static/ # nginx에서 static을 사용할 수 있도록 volume을 지정해줍니다.
    environment: # django에서 사용할 설정들을 지정해줍니다.
      - DEBUG=1
      - POSTGRES_DB=django
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=P@ssw0rd
      - POSTGRES_HOST=postgres
      - POSTGRES_PORT=5432
    depends_on:
      - postgres
    restart: always

  nginx:
    container_name : nginx
    image: nginx:1.23.2
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
      - django_media:/media/ # django의 media를 사용할 수 있도록 volume을 지정해줍니다.
      - django_static:/static/ # django의 static 사용할 수 있도록 volume을 지정해줍니다.
    depends_on:
      - backend
    restart: always
vi backend/Dockerfile
# 수정하기
RUN pip install gunicorn psycopg2
sudo docker compose up -d --build
sudo docker compose logs -f
sudo docker exec -it backend /bin/bash
python manage.py createsuperuser
python manage.py shell
from django.db import connections
from pprint import pprint
pprint(connections.databases)

 

 

배포 환경의 통신 구조

가장 먼저 사용자는 EC2의 nginx에 request 요청을 하게 됩니다.

nginx에서는 사용자의 요청을 받아 .conf 파일에서 설정한 서버로 요청을 전달합니다.

이후 gunicorn에서는 django로, django에서는 필요에 따라 데이터베이스에 쿼리를 날려 개발자가 작성한 코드를 실행하게 됩니다.

 

 

 

 

 

env 작성하기

vi .env
DEBUG=1
POSTGRES_DB=django
POSTGRES_USER=user
POSTGRES_PASSWORD=P@ssw0rd
POSTGRES_HOST=postgres
POSTGRES_PORT=5432
vi docker-compose.yml
# 해당 부분의 environment만 수정하기
services:
  postgres:
    environment:
      - POSTGRES_USER
      - POSTGRES_PASSWORD
      - POSTGRES_DB

  backend:
    environment: # 
      - DEBUG
      - POSTGRES_DB
      - POSTGRES_USER
      - POSTGRES_PASSWORD
      - POSTGRES_HOST
      - POSTGRES_PORT
sudo docker compose up -d
vi .env

# DEBUG=0 으로 바꾸고 페이지가 달라지는지 확인하기

 

 

 

 

 

slim 이미지

  • 이미지마다 지원하는 버전은 차이가 있습니다.
  • 동일한 docker 이미지라 하더라도 태그에 따라 이미지의 용량이 달라집니다.
  • 가령 python 이미지의 경우 가장 큰 이미지와 가장 작은 이미지의 용량이 300mb 이상 차이납니다.
  • 용량이 작은 이미지를 사용할 때는 외부 패키지를 설치할 때 필요한 의존성 파일들이 존재하지 않아 에러가 발생할 수 있습니다.
  • 내가 사용하는 이미지에 어떤 종류의 태그가 존재하는지 확인이 필요할 때는 https://hub.docker.com/ 이미지 페이지의 tags에서 확인 가능합니다.

 

 

이미지의 태그별 특징

  • buster, jessie, stretch
    • debian에서 만든 linux를 기반으로 만들어진 이미지입니다.
    • buster, jessie, stretch는 os의 codename입니다. (링크)
    • python:3.8과 python:3.8-buster는 동일합니다. (약 300~350mb)
  • slim
    • 실행에 필요한 환경만 만들어둔 이미지입니다.
    • 이미지가 기본이미지에 비해서는 작습니다. (약 40~50mb)
    • 보통 python 실행환경에서 가장 많이 쓰이는 이미지
  • alpine
    • 용량이 작고, 보안에 집중한 alpine-linux 기반으로 만들어진 이미지입니다.
    • 보통 이미지들 중에서 가장 작다는 특징을 가지고 있습니다. (약 15~20mb)
    • python기준으로 봤을 때, pip install을 할 때 불리한 점이 있습니다.
vi backend/Dockerfile
# python 3.10.8-slim버전 이미지를 사용해 빌드
FROM python:3.10.8-slim

ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

RUN mkdir /app/
WORKDIR /app/

# slim 이미지에서 postgresql 패키지를 설치하기 위해 필요 명령어 추가
RUN apt update && apt install libpq-dev gcc -y

COPY ./django/requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
RUN pip install gunicorn psycopg2
vi docker-compose.yml
services:
  postgres:
    image: postgres:14.5-alpine  # alpine으로 수정
  nginx:
    image: nginx:1.23.2-alpine  # alpine으로 수정
sudo docker compose up -d --build
sudo docker images

# 필요없는 이미지 삭제
sudo docker rmi aa c7  # 숫자는 none이라고 쓰인 이미지ID
sudo docker image prune -a  #컨테이너에서 사용중인 이미지 이외에 모두 삭제

 

 

 

 

 

도메인 배포 서버에 연결

AWS, 가비아, freenom 등 마음에 드는 곳에서 구매하면 됩니다.

freenom의 경우 무료이지만 오류가 많습니다.

도메인이 등록되는데 최대 24시간까지 걸리기도 합니다.

ex) 소셜로그인 오류, xxx.tk 등 도메인 전체 주소를 입력해야 하는 오류 등

 

레코드 2개 생성

 

www를 강제로 붙여주는 작업

 

vi nginx/default.conf
server {
  listen 80;
  server_name www.spartacodingclub.tk; # www.spartacodingclub.tk 도메인으로 들어오는 요청을 처리해줍니다.

  location / {
    proxy_pass http://backend:8000/;
  }

  location /static/ {
    alias /static/;
  }

  location /media/ {
    alias /media/;
  }
}

server {
  listen 80;
  server_name spartacodingclub.tk; # www가 없는 url로 요청 했을 때
  return 301 http://www.spartacodingclub.tk$request_uri; # www를 붙인 url로 redirection 해줍니다.
}
sudo docker compose restart nginx

 

 

 

 

 

 

https 란?

  • 웹 서버에서 데이터를 전송하기 위한 http 프로토콜에 보안을 의미하는 secure를 붙여 http 통신을 더 안전하게 할 수 있도록 해주는 프로토콜입니다.
  • 보안적인 특성 때문에 배포를 하는 서비스에는 https를 필수적으로 적용하게 됩니다.
  • https를 적용하기 위해서는 SSL 인증서를 발급받고 웹서버에서 인증서를 지정해주는 과정이 필요합니다.

 

 

 

 

 

vi backend/django/drf_project/settings.py
CORS_ORIGIN_WHITELIST = ['https://www.winterakoon.shop',]
sudo docker compose restart backend

 

 

 

'503 Service Temporarily Unavailable' 에러가 발생하는 경우 로드밸런싱 대상 그룹에 Healthy 부분을 잘 체크하자.  인스턴스 가용영역을 서브넷에서 설정하지 않은 경우 unused라고 나타나며 에러가 발생하기도 한다. 이 경우 로드벨런서 서브넷 편집에서 해당 가용영역을 추가하면 해결할 수 있다.

 

※ 보안 그룹 선택할 경우 생성후 인바운드 규칙을 바로 추가해주거나, 애초에 SSH, HTTPS, HTTP 포트 허용한 걸로 선택하자. 

'aws' 카테고리의 다른 글

02.5 [Docker] putty  (0) 2023.05.31
2주차 [Docker] docker  (0) 2023.05.31
1주차 [Docker] Linux  (0) 2023.05.30
11. [aws] EBS(Elastic Beanstalk) & http를 https로 리다이렉트  (0) 2023.05.26
10. [aws] CDN  (0) 2023.05.26

putty로 ssh 접속하기

 

cmd로 ssh 연결시 아래와 같은 오류로 putty로 접속하였습니다.

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0744 for '/home/geek/.ssh/id_rsa' are too open.
It is recommended that your private key files are NOT accessible by others.
This private key will be ignored.
bad permissions: ignore key: /home/geek/.ssh/id_rsa

 

 

'aws' 카테고리의 다른 글

3주차 [Docker] 배포  (0) 2023.05.31
2주차 [Docker] docker  (0) 2023.05.31
1주차 [Docker] Linux  (0) 2023.05.30
11. [aws] EBS(Elastic Beanstalk) & http를 https로 리다이렉트  (0) 2023.05.26
10. [aws] CDN  (0) 2023.05.26

docker란?

  • django, db, web server 등 다양한 어플리케이션을 컨테이너 환경에서 테스트 및 배포할 수 있는 소프트웨어 플랫폼입니다.
  • 컨테이너 환경은 가상 머신(Virtual machine)에서 사용되는 가상 환경과 비슷하지만 다른 구조를 가지고 있습니다.
  • docker를 사용할 경우 다양한 어플리케이션을 쉽고 빠르게 배포할 수 있습니다.
  • 컨테이너는 각각 독립적인 환경에서 구동되기 때문에 안정적인 운영이 가능합니다.
  • docker 이미지를 통해 동일한 환경을 가진 컨테이너를 쉽게 생성하고 관리할 수 있습니다.

도커 = 가상 머신 - os

 

 

 

 

docker 이미지란?

  • 가상 머신에서 윈도우를 설치할 때, 윈도우 ISO를 사용해 설치하는 것처럼 docker 컨테이너는 docker 이미지를 기반으로 생성됩니다.
  • 이미지는 docker 컨테이너가 생성될 때 실행되는 실행파일, 설정 등을 가지고 있습니다. 예를 들어, docker postgresql 이미지는 컨테이너가 실행됐을 때 postgresql을 실행시키기 위한 패키지들이 기본적으로 설치되어 있습니다.

 

 

 

 

docker 설치하기

docker 패키지 설치

sudo apt install docker.io -y  # 설치과정 중 선택지가 나오면 자동 yes
# 만약 아래와 같은 에러가 발생한다면
# E: Package 'docker.io' has no installation candidate
# sudo apt update 명령어 실행 후 docker 패키지를 다시 설치해주세요

 

docker 설치 확인

sudo docker --version # 도커 버전이 출력되는지 확인합니다.
# Docker version 20.10.12, build 20.10.12-0ubuntu2~20.04.1 - 정상
# command not found: docker 와 같은 문구가 출력될 경우 docker가 설치되었는지 확인해야 합니다.

 

docker 컨테이너 생성하기

sudo docker run -d -p 80:80 httpd:latest
# run : 이미지를 사용해 컨테이너를 실행시킵니다.
# -d : 컨테이너를 데몬(백그라운드)으로 실행시킵니다.
# 80:80 : 80번 포트로 접속했을 때 컨테이너에 접근할 수 있도록 포트포워딩 설정을 해줍니다.
# httpd:latest : httpd의 가장 최신 이미지를 사용해 컨테이너를 생성합니다.

 

실행중인 컨테이너 확인하기

sudo docker ps # 실행중인 컨테이너 목록 확인하기
# CONTAINER ID : 컨테이너가 가지고 있는 고유한 id
# IMAGE : 컨테이너가 생성될 때 사용된 이미지
# COMMAND : 컨테이너가 생성될 때 실행되는 명령어
# CREATED : 생성 후 경과 시간
# STATUS : 컨테이너 상태
# PORTS : 사용중인 포트

sudo docker ps -a
# -a : 중지된 컨테이너 목록까지 포함해서 모두 확인하기

 

다운받은 이미지 확인하기

sudo docker images
# REPOSITORY : 이미지 저장소 이름
# TAG : 이미지 버전
# IMAGE ID : 이미지의 고유한 id
# CREATED : 이미지 생성일(마지막 업데이트 일)
# SIZE : 이미지 용량

 

컨테이너 내부로 들어가보기

sudo docker exec -it $container_id /bin/bash
# $containser_id : sudo docker ps를 쳤을 때 확인되는 container_id를 입력합니다.
# /bin/bash : 컨테이너에 접속할 때 사용되는 쉘을 입력합니다.
# 이미지에 따라 /bin/bash라는 쉘이 존재하지 않을 수 있는데, 이 경우에는 /bin/sh를 사용해 접속합니다.

# 종료 : exit

 

 

 

 

docker-compose란?

  • docker-compose는 docker 2개 이상의 컨테이너를 더욱 간편하게 관리하기 위해 사용되는 툴입니다.
  • docker-compose를 사용할 때에는 docker-compose.yml (혹은 .yaml)이라는 파일에 컨테이너에서 사용 될 이미지, 옵션 등을 작성한 후 사용하게 됩니다.
  • 이를 통해 docker 명령어만 사용할 때보다 여러 컨테이너를 더 간편하고 직관적으로 컨테이너를 관리할 수 있습니다.

 

sudo mkdir -p /usr/lib/docker/cli-plugins
# /usr/lib/docker 경로에 cli-plugins라는 디렉토리를 생성합니다.
# -p : 만약 상위 디렉토리가 없다면 함께 생성합니다.

sudo curl -SL https://github.com/docker/compose/releases/download/v2.11.2/docker-compose-linux-x86_64 -o /usr/lib/docker/cli-plugins/docker-compose
# github에 release 된 docker-compose 파일을 /usr/lib/docker/cli-plugins/ 경로에 다운로드 받습니다.
# v2.11.2는 docker-compose의 버전이며, 최신 버전은 여기서 확인 가능합니다.

sudo chmod +x /usr/lib/docker/cli-plugins/docker-compose
# 다운받은 docker-compose 파일에 실행 권한을 부여해 줍니다.

sudo docker compose version
# docker-compose가 정상적으로 설치되었는지 확인합니다.
# Docker Compose version v2.11.2 정상적으로 설치 된 경우 버전이 출력됩니다.

※ docker-compose.yml 파일이 존재하지 않는 경로에서 docker compose 명령어를 실행시킬 경우 다음과 같은 에러가 발생할 수 있습니다.

 

 

 

 

 

docker-compose로 컨테이너 생성하기

  • 💡 docker 명령어가 아닌 docker-compose를 활용해 컨테이너를 생성하는 방법을 알아보겠습니다.

 

 

docker 컨테이너 삭제하기

sudo docker ps -a # docker에 존재하는 컨테이너 목록을 확인합니다.
# CONTAINER ID   IMAGE          COMMAND              CREATED        STATUS        PORTS                               NAMES
# 54445308314d   httpd:latest   "httpd-foreground"   23 hours ago   Up 23 hours   0.0.0.0:80->80/tcp, :::80->80/tcp   sweet_engelbart

sudo docker rm -f $container_id # 컨테이너의 실행중 여부와 관계 없이 강제로 삭제합니다.

 

docker-compose.yml 작성해보기

vi docker-compose.yml
version: '3.8' # docker-compose.yml에 사용될 문법 버전을 정의
# 즉 위의 version에 따라 밑의 services의 형식, 문법이 변함

services:
  example: # 서비스 이름을 지정합니다. 서비스 이름은 컨테이너끼리 통신할 때 사용
    container_name: example # 컨테이너 이름을 지정
    image: 'httpd:latest' # 컨테이너를 생성할 때 사용될 이미지를 지정
    restart: always # 컨테이너가 종료됐을 때 다시 실행

 

컨테이너 실행시켜보기

# docker compose 명령어는 docker-compose.yml 파일이 존재하는 자리에서 실행해야 합니다.

sudo docker compose up -d
# up : docker-compose.yml 파일을 읽어 정의된 서비스들을 실행시킵니다.
# -d : 컨테이너를 데몬(백그라운드)으로 실행시킵니다.

sudo docker ps

 

컨테이너 중지시키기

 

1. stop

sudo docker compose stop

sudo docker ps -a  # 중지 상태의 컨테이너 확인 가능
# docker ps는 동작 중인 컨테이너만 보여줌

sudo docker compose start  # 재시작

 

 

 

2.down

sudo docker compose down

sudo docker ps -a

sudo docker compose up -d  # 재생성시 컨테이너 id가 변경됨

※ aws 인스턴스 중지와 종료 차이와 유사

 

 

 

 

 

컨테이너 포트 포워딩 설정

 

포트 포워딩(port forwarding)이란?

 

포트 포워딩이라는 이름과 같이, 외부에서 서버의 특정 포트에 접근했을 때 지정한 서비스로 전달해 주는 것을 의미합니다.

예를 들어 특정 컨테이너의 포트포워딩 설정을 80:8000과 같이 해줬다면, 외부에서 80 포트로 접속했을 때 해당 컨테이너의 8000번 포트로 접속하겠다는 의미입니다.

 

 

※ http 프로토콜은 기본적으로 80 포트를 사용하고 https 프로토콜은 443 포트를 사용하게 되며 이는 웹 브라우저에 주소를 입력할 때 생략됩니다.

 

docker-compose.yml 수정하기

vi docker-compose.yml
version: '3.8' # docker-compose.yml에 사용될 문법 버전을 정의합니다.

services:
  example: # 서비스 이름을 지정합니다. 서비스 이름은 컨테이너끼리 통신할 때 사용됩니다.
    container_name: example # 컨테이너 이름을 지정합니다.
    image: 'httpd:latest' # 컨테이너를 생성할 때 사용될 이미지를 지정합니다.
    ports: # 포트포워딩을 설정해줍니다.
     - 80:80 # 외부에서 80 포트로 접속했을 때 컨테이너의 80 포트로 연결해줍니다.
    restart: always # 컨테이너가 종료됐을 때 다시 실행시켜 줍니다.

 

변경사항 적용하기

sudo docker compose up -d

 

컨테이너 로그 확인하기

sudo docker compose logs

sudo docker compose logs -f  # 실시간 로그 확인

# 종료 : ctrl + c

 

 

 

 

 

volume을 사용해 데이터 보존하기

    ❓ volume을 사용하지 않으면?

sudo docker exec -it example /bin/bash
# docker container에 접속할 때 container id 대신 container name을 사용할 수도 있습니다.

echo "test" >> /usr/local/apache2/htdocs/index.html  # echo 문자열 : 문자열을 출력해줌

exit

sudo docker compose down
sudo docker compose up -d

 

  • docker 컨테이너는 컨테이너가 종료될 때 변경된 데이터는 모두 초기화 된다는 특징을 가지고 있습니다.
  • volume은 컨테이너에 저장되는 데이터의 일부를 host와 공유해 주는 역할을 합니다.
  • host에 저장 된 데이터는 사용자가 직접 삭제하지 않는 이상 계속해서 유지되며, 때문에 컨테이너가 종료된다 하더라도 데이터는 유실되지 않습니다.
  • volume은 컨테이너 내부에서 변경되는 내용들을 유지해야 할 때 주로 사용됩니다.

 

docker volume 종류

docker volume의 종류는 docker volume, bind mount, tmpfs mount방식이 있으며 docker volume 방식이 주로 사용됩니다.

docker volume

  • docker 엔진이 관리하는 volume을 생성하는 방식입니다.
  • docker volume 방식을 사용해 생성된 volume은 host의 /var/lib/docker/volumes/ 경로에 저장됩니다.
  • docker에서 가장 권장하는 방식입니다.
vi docker-compose.yml
version: '3.8' # docker-compose.yml에 사용될 문법 버전을 정의합니다.

volumes:
  example_http_code: {} # docker volume을 정의합니다.

services:
  example: # 서비스 이름을 지정합니다. 서비스 이름은 컨테이너끼리 통신할 때 사용됩니다.
    container_name: example # 컨테이너 이름을 지정합니다.
    image: 'httpd:latest' # 컨테이너를 생성할 때 사용될 이미지를 지정합니다.
    ports: # 포트포워딩을 설정해줍니다.
      - 80:80 # 외부에서 80 포트로 접속했을 때 컨테이너의 80 포트로 연결해줍니다.
    volumes: # volume을 성정해줍니다.
      - example_http_code:/usr/local/apache2/htdocs/
      # 위에서 정의한 볼륨: 컨테이너 폴더를 mount
    restart: always # 컨테이너가 종료됐을 때 다시 실행시켜 줍니다.
sudo docker compose up -d
sudo docker exec -it example /bin/bash
echo "test" >> /usr/local/apache2/htdocs/index.html
exit
sudo docker compose down
sudo docker compose up -d

# 볼륨 정보 확인
sudo docker volume ls
sudo docker volume inspect ubuntu_example_http_code

 

 

bind mount

  • docker volume 방식과 매우 유사합니다.
  • docker container를 생성할 때 사용자가 지정한 경로에 데이터가 저장됩니다.
  • docker 엔진의 관리를 받지 않는 영역이기 때문에 사용자가 직접 파일을 추가/수정/삭제 할 수 있다는 특징이 있습니다. docker 공식 문서에서는 이러한 특징으로 인해 운영에 영향을 미칠 수 있기 때문에 유사한 기능인 docker volume 방식을 사용하는 것을 권장하고 있습니다.
vi docker-compose.yml
version: '3.8' # docker-compose.yml에 사용될 문법 버전을 정의합니다.

services:
  example: # 서비스 이름을 지정합니다. 서비스 이름은 컨테이너끼리 통신할 때 사용됩니다.
    container_name: example # 컨테이너 이름을 지정합니다.
    image: 'httpd:latest' # 컨테이너를 생성할 때 사용될 이미지를 지정합니다.
    ports: # 포트포워딩을 설정해줍니다.
      - 80:80 # 외부에서 80 포트로 접속했을 때 컨테이너의 80 포트로 연결해줍니다.
    volumes: # volume을 성정해줍니다.
      - ./example_http_code/:/usr/local/apache2/htdocs/ # 정의한 volume의 mount할 경로를 지정합니다.
      # host 경로 : 컨테이너 경로를 볼륨으로 정의
    restart: always # 컨테이너가 종료됐을 때 다시 실행시켜 줍니다.
cat docker-compose.yml
sudo docker compose up -d
ls -l example_http_code/
# 폴더가 비어있음

sudo vi example_http_code/index.html
bind mount
# 컨테이너 수정
sudo docker exec -it example /bin/bash
echo "test" >> /usr/local/apache2/htdocs/index.html
exit
cat example_http_code/index.html

 

 

tmpfs mount

  • 기존의 방식들이 ssd 혹은 hdd와 같은 저장장치에 데이터를 저장한다면, tmpfs mount 방식은 휘발성 메모리인 RAM에 데이터를 저장합니다.
  • 파일로 저장하면 안 되는 민감한 정보를 다룰 때 사용됩니다.

 

언제 어떤 방식의 volume을 사용해야 할까?

  • docker volume은 주로 컨테이너간 파일을 공유하거나 중요도가 높은 파일들을 사용자가 쉽게 수정/삭제 하지 못하도록 할 때 주로 사용합니다.
  • bind mount는 설정파일 혹은 소스코드를 프로젝트와 서버가 공유할 때 주로 사용됩니다.
  • tmpfs mount는 많은 양의 데이터를 임시로 저장할 때, 혹은 보안적으로 중요한 데이터를 저장할 때 주로 사용됩니다.
  • 자세한 내용은 docker 공식 문서에서 확인할 수 있습니다.

 

도커 볼륨 삭제하기

docker compose down 혹은 docker rm 명령어로 컨테이너를 삭제해도, docker volume은 삭제되지 않고 남아있게 됩니다.

 

sudo docker compose down
# 사용하지 않는 볼륨을 일괄적으로 삭제
sudo docker volume prune
sudo docker volume ls

 

 

 

 

 

이미지 직접 빌드하기

 

Dockerfile 이란?

  • docker 의 이미지를 직접 생성하기 위한 용도로 작성하는 파일입니다.
  • Dockerfile을 작성할 때는 기본이 되는 이미지를 지정한 후, 특정 패키지를 설치하거나 파일을 추가하는 등의 작업을 통해 사용자가 직접 이미지를 빌드하고 사용할 수 있습니다.
  • 사용자가 개발한 프로젝트 혹은 설정파일 등을 이미지에 포함시키거나 이미지에 기본적으로 특정 패키지를 설치하고싶을 때 등 다양한 용도로 사용됩니다.

 

 

Dockerfile 작성하기

vi Dockerfile
# 빌드할 때 사용할 이미지를 지정해줍니다.
FROM httpd:latest

# 현재 경로에 존재하는 index.html 파일을 컨테이너 내부로 복사합니다.
# 컨테이너 내부에 이미 존재하는 경우 덮어쓰기
# 없는 경우 새로 생성
COPY ./index.html /usr/local/apache2/htdocs/index.html
vi docker-compose.yml
version: '3.8' # docker-compose.yml에 사용될 문법 버전을 정의합니다.

services:
  example: # 서비스 이름을 지정합니다. 서비스 이름은 컨테이너끼리 통신할 때 사용됩니다.
    container_name: example # 컨테이너 이름을 지정합니다.
    build: . # 현재 경로에 있는 Dockerfile을 사용해 이미지를 생성합니다.
    ports: # 포트포워딩을 설정해줍니다.
      - 80:80 # 외부에서 80 포트로 접속했을 때 컨테이너의 80 포트로 연결해줍니다.
    restart: always # 컨테이너가 종료됐을 때 다시 실행시켜 줍니다.
vi index.html
docker file
sudo docker compose up -d
sudo docker compose down

※ Dockerfile로 빌드된 이미지가 없을 경우, --build 옵션을 추가하지 않더라도 이미지를 빌드 하게 됩니다. 하지만, 기존에 빌드된 이미지가 있을 경우에는 새로 빌드하지 않고 기존에 빌드 된 이미지를 사용합니다. 때문에, Dockerfile을 수정하고 이미지를 새로 빌드해야 할 때는 --build 옵션을 추가해서 사용해야 합니다.

sudo docker compose up --build -d

 

 

 

 

entrypoint란?

  • docker 컨테이너가 생성될 때 기본적으로 실행 할 명령어를 지정해 주는 옵션입니다.
  • 데이터베이스를 실행시키기 위해 만든 이미지는, 컨테이너가 생성될 때 데이터베이스 서비스를 실행시켜야 합니다. 이 때 사용되는 옵션이 entrypoint입니다.
  • entrypoint는 Dockerfile과 docker-compose.yml 모두 작성할 수 있습니다.
  • 만약 Dockerfile, docker-compose.yml 모두 entrypoint가 작성되어 있다면 Dockerfile의 entrypoint는 무시되고 docker-compose.yml의 명령어가 우선적으로 수행됩니다.

 

vi Dockerfile
FROM python:3.9.15

# .pyc 파일을 생성하지 않도록 설정합니다.
# 파이썬 사용할 때 거의 필수 옵션
ENV PYTHONDONTWRITEBYTECODE 1

# 파이썬 로그가 버퍼링 없이 즉각적으로 출력하도록 설정합니다.
# 파이썬 사용할 때 거의 필수 옵션
ENV PYTHONUNBUFFERED 1

# /app/ 디렉토리를 생성합니다.
RUN mkdir /app/

# /app/ 경로를 작업 디렉토리로 설정합니다.
WORKDIR /app/

# main.py 파일을 /app/ 경로로 복사합니다.
COPY ./main.py /app/
vi docker-compose.yml
version: '3.8' # docker-compose.yml에 사용될 문법 버전을 정의합니다.

services:
  example: # 서비스 이름을 지정합니다. 서비스 이름은 컨테이너끼리 통신할 때 사용됩니다.
    container_name: example # 컨테이너 이름을 지정합니다.
    build: . # 현재 경로에 있는 Dockerfile을 사용해 이미지를 생성합니다.
    entrypoint: sh -c "python3 main.py" # 작업 디렉토리에 존재하는 main.py 파일을 실행시킵니다.
    # sh -c 뒤에 파일을 실행시킴
    restart: always # 컨테이너가 종료됐을 때 다시 실행시켜 줍니다.
vi main.py
from time import sleep
for i in range(100):
    print(f"print number : {i}")
    sleep(1)
# 도커 파일 수정한 후에도 빌드해야 함
sudo docker compose up --build -d
sudo docker compose logs -f
sudo docker ps  #entrypoint command 도 확인가능

 

 

 

 

 

 

컨테이너를 두 개 이상 띄워보기

💡주의사항💡

  • 컨테이너가 1개일 때와 2개 이상일 때 docker-compose.yml을 작성하는 방법은 기존과 크게 다르지 않습니다.
  • 다만, ports 혹은 서비스 이름 등 중복되면 안되는 몇몇 옵션이 존재하기 때문에 중복되는 값이 있는지 확인해야 하며 만약 특정 값이 중복되어 들어간다면 컨테이너가 정상적으로 생성되지 않거나 생성하는 과정에서 에러가 발생할 수 있습니다.

(위의 dockerfile을 그대로 사용)

vi docker-compose.yml
version: '3.8'

services:
  example1:
    container_name: example1
    image: 'httpd:latest'
    ports:
      - 80:80
    restart: always
    
  example2: # 서비스 이름이 동일하면 컨테이너가 정상적으로 생성되지 않을 수 있습니다.
    container_name: example2 # 컨테이너 이름이 동일하면 컨테이너 생성 시 에러가 발생합니다.
    build: .
    entrypoint: sh -c "python3 main.py"
    restart: always
sudo docker compose up -d
sudo docker ps
sudo docker rm -f example

 

  • docker-compose.yml에 두 개 이상의 컨테이너를 생성하도록 작성한 경우, 기본적으로는 작성 한 순서대로 컨테이너가 실행됩니다.
  • 하지만 경우에 따라 특정 컨테이너가 먼저 실행되어야 하는 경우가 있습니다.
  • 이 때, depends_on 옵션을 사용해 컨테이너간 실행 순서를 컨트롤 할 수 있습니다.
vi docker-compose.yml
version: '3.8'

services:
  example1:
    container_name: example1
    image: 'httpd:latest'
    ports:
      - 80:80
    depends_on:
      - example2 # 해당 컨테이너보다 먼저 실행되어야 하는 컨테이너를 지정합니다.
    restart: always
    
  example2: # 서비스 이름이 동일하면 컨테이너가 정상적으로 생성되지 않을 수 있습니다.
    container_name: example2 # 컨테이너 이름이 동일하면 컨테이너 생성 시 에러가 발생합니다.
    build: .
    entrypoint: sh -c "python3 main.py"
    
    restart: always
sudo docker compose up -d

'aws' 카테고리의 다른 글

3주차 [Docker] 배포  (0) 2023.05.31
02.5 [Docker] putty  (0) 2023.05.31
1주차 [Docker] Linux  (0) 2023.05.30
11. [aws] EBS(Elastic Beanstalk) & http를 https로 리다이렉트  (0) 2023.05.26
10. [aws] CDN  (0) 2023.05.26

Linux란?

  • 기본적으로 무료 입니다.
  • Linux는 오픈소스입니다. 소스코드를 자유롭게 보고 수정할 수 있다는 오픈소스의 특성 덕분에 수많은 종류의 Linux 기반 OS가 존재합니다.
  • 가볍고 안정적입니다.
  • 마우스 / 키보드를 사용해 조작하는 GUI(Graphical User Interface) 환경의 Windows, Mac과는 다르게 기본적으로 CLI(Command Line Interface) 환경에서 사용됩니다.

 

Linux에서 사용되는 명령어와 옵션의 구조는 아래와 같습니다.

더보기

현재 단계에서 아래 명령어들이 어떤 것을 의미하는지 몰라도 괜찮습니다.

Linux의 명령어는 명령어 -옵션 의 구조로 이루어져 있습니다.
ls    # 파일 목록을 보여주는 명령어
ls -l # -l : 파일 목록을 더 자세히 보여주는 옵션
ls -a # -a : 숨김 파일까지 보여주는 옵션

2개 이상의 옵션을 한번에 사용할 수도 있습니다.

ls -al # 옵션의 순서는 무관합니다.

일부 명령어는 source와 destination의 구조로 이루어져 있습니다.

cp a.txt a_copy.txt # a.txt를 a_copy.txt로 복사
cp -r folder folder_copy # folder를 복사 할 때는 -r 옵션이 필요합니다.

 

 

 

ssh 연결하기

(cmd)

ssh -i {키페어 경로} ubuntu@{퍼블릭 IPv4}

 

 

 

 

 

파일과 디렉토리 다뤄보기

  • 상대경로와 절대경로란?
    • 리눅스에서는 디렉토리를 이동하거나 파일을 지정할 때, 상대경로 혹은 절대경로를 사용하게 됩니다.
    • 절대경로를 사용할 경우 현재 위치와 관계 없이 절대적인 경로를 입력하여 사용합니다.
      • ex) cd /home/user/example/dir/
    • 상대경로는 내 현재 위치를 기준으로 경로를 지정하게 됩니다.
      • ex) cd ./dir/ 현재 위치에 존재하는 dir 디렉토리로 이동
      • ex) cd ../ 현재 위치를 기준으로 상위 디렉토리로 이동
  • 리눅스에서 숨김 파일을 취급하는 방법
    • 리눅스에서는 파일 혹은 디렉토리 이름이 .으로 시작할 경우 숨김 파일로 취급됩니다.
      • ex) touch test : test라는 이름의 파일 생성 touch .test : .test라는 이름의 숨김 파일 생성
  • wild card(*)란?
    • 특정 파일이나 디렉토리를 지정할 때, 이름을 지정해 줘야 하는 경우가 있습니다. 이 때 wild card(*)를 사용하면 원하는 파일을 더 빠르게 탐색하거나 실행시킬 수 있습니다.
ls -l ./*.txt  # 현재경로에 있는 .txt로 끝나는 모든 파일 목록 출력하기

 

 

 

 

 

기본 명령어

# 폴더 생성하기
mkdir ./test # 현재 경로에 test 디렉토리 생성하기
mkdir ./test/test2 # test 디렉토리 안에 test2 디렉토리 생성하기
mkdir /home/ubuntu/test3 # /home/user 경로에 test3 디렉토리 생성하기

# 현재 경로 확인하기
pwd

# 경로 이동하기
cd ./test # 현재 경로의 test 디렉토리로 이동
cd ./test/test2 # test 디렉토리 안에 test2 디렉토리로 이동
cd ../test3 # 상위 디렉토리의 test3 디렉토리로 이동
cd /home/user/test4 # /home/user/test4 디렉토리로 이동

# 파일 목록보기
ls # 현재 위치에 파일 목록 보기
ls ./test # test 경로에 파일 목록 보기
ls -l # 현재 위치에 파일 목록을 더 자세히 보기
ls -a # 현재 위치에 숨겨짐 파일을 포함해서 보기
ls -al # 현재 위치에 숨겨진 파일을 포함해서 목록을 더 자세히 보기
# 이외에도 다양한 옵션들이 존재하며, ls --help 명령어로 확인 가능합니다.

# 파일 생성하기
touch test.txt # test.txt 파일 생성하기

# 파일 복사하기
cp test.txt test_copy.txt # test.txt 파일을 test_copy.txt라는 이름으로 복사하기
cp -r directory directory_copy # 폴더를 복사할 경우 -r 옵션 사용

# 파일 이동하기
mv ./directory1/test.txt ./ # directory1 경로의 test.txt 파일을 현재 경로로 이동

# 파일명 변경
mv test.txt text2.txt # test.txt 파일의 이름을 test2.txt로 변경

# 파일 삭제하기
rm test.txt # test.txt 파일 삭제
rm -r directory # 디렉토리를 삭제하기 위해서는 -r 옵션을 붙여줘야 합니다.
rm -rf ./* : 현재 위치 모든 파일을 에러가 나도 강제로(-f) 삭제

 

 

 

 

 

파일 편집

# insert mode
i  # 현재 위치에서 insert mode 진입
a  # 현재 위치에서 커서를 한 칸 뒤로 이동 후 insert mode 진입
shift + a  # 현재 위치에서 가장 마지막 텍스트로 이동 한 후 insert mode 진입
o  # 현재 위치에서 한칸 개행 한 후 insert mode 진입
shift + o  # 커서 한줄 위에서 insert mode 진입

esc  # insert mode 나가기

h,j,k,l  # 방향 키



# commend mode
u  # undo
ctrl + r  # redo

gg  # 커서를 가장 처음으로 옮김
shift + g  # 커서를 마지막 줄로 옮김

dd  # line 잘라내기
[숫자]dd  # 커서위치부터 몇줄 삭제 ex. 5dd
yy  # line 복사
p  # 붙여넣기

:se nu  # 라인 줄 표시
:숫자  # 숫자 번째 라인으로 이동

/word  # word라는 단어를 검색
/\cwird  # 대소문자를 구분하지 않고 word라는 단어를 검색 (ex - /\cword)
n  # 다음 단어 검색
shift + n  # 이전 단어 검색
cw  # 단어 변경
dw  # 단어 삭제 ex.test 12 중 test 안에서 커서를 두고 사용시 test 라는 단어 삭제
w  # 다음 단어 앞부분으로 이동

:q!  # 수정내역이 있어도 저장하지 않고 강제로 나가기



# 파일 내용 확인

# 파일 내용 보기
cat test.txt # test.txt

# 파일의 시작 부분 보기
head test.txt # test.txt 파일의 첫 10줄 내용 보기
head -50 test.txt # text.txt 파일의 첫 50줄 내용 보기

# 파일의 끝 부분 보기
tail text.txt # text.txt 파일의 마지막 10줄 내용 보기
tail -50 text.txt # text.txt 파일의 마지막 50줄 내용 보기

 

 

 

 

 

자주 사용되는 명령어

# 특정 문자열이 포함 된 파일 찾기
grep word ./*  # 현재 경로의 모든 파일을 대상으로 word라는 단어가 포함된 파일 찾기
grep word ./* -r  # -r 옵션을 붙이면 디렉토리 내부까지 모두 탐색합니다.


# 특정 조건의 파일 찾기
find / -name "*txt*"  # 최상위 경로에서 test가 포함된 모든 파일
find ./ -type d  # 현재 경로에서 모든 디렉토리 검색
find ./ -type f -name "*.txt"  # 현재 경로에서 .txt로 끝나는 파일 검색


# 명령어 기록 출력하기
history


# 리소스 사용량 확인하기
htop


# 남은 디스크 용량 확인하기
df -h


# 특정 파일 혹은 폴더가 사용중인 디스크 용량 확인하기
du -sh ./*  # 현재 경로의 파일 및 디렉토리가 차지하는 용량 확인하기


# ip 주소를 포함해 다양한 네트워크 정보를 확인
ifconfig

 

 

 

'aws' 카테고리의 다른 글

02.5 [Docker] putty  (0) 2023.05.31
2주차 [Docker] docker  (0) 2023.05.31
11. [aws] EBS(Elastic Beanstalk) & http를 https로 리다이렉트  (0) 2023.05.26
10. [aws] CDN  (0) 2023.05.26
09. [aws] S3 (긴 글, 반복 주의)  (0) 2023.05.26

EBS(Elastic Beanstalk) 등장배경

  1. Public Subnet: 로드 밸런서
  2. Private Subnet: 비즈니스 로직을 처리하는 레이어입니다. 보통 웹 애플리케이션 서버
  3. Data Subnet: 데이터를 저장하는 레이어입니다. 보통 데이터베이스 서버, 파일 서버 등이 사용

    대부분의 웹앱은 같은 아키텍처를 가지고 있습니다.

 

    ❓ 그런데 서비스를 만들때마다 같은 인프라를 만들어야 한다면?

 

EBS는 개발자 관점으로 AWS를 접근합니다.

  • DB설정, 로드밸런서 자동 설정
  • 자동으로 스케일링(확장성)을 지원

    3-tier 아키텍처는 애플리케이션의 확장성과 유연성을 향상시키고, 높은 가용성과 성능을 제공합니다. 각 레이어를 독립적으로 확장할 수 있으며, 부하 분산과 장애 극복 기능을 쉽게 추가할 수 있습니다. 또한, 애플리케이션의 유지보수와 업그레이드가 용이하며, 보안성이 높습니다. 

    배포 프로세스를 자동으로 처리하며, 필요한 인프라 자원을 프로비저닝하고, 로드 밸런싱과 오토스케일링 등의 기능을 제공합니다.

 

 

 

 

EBS 개념

  • Application
    • 애플리케이션 코드, 구성 및 관련 파일
    • Elastic Beanstalk는 다양한 프로그래밍 언어와 프레임워크를 지원합니다
  • Environment
    • Amazon EC2 인스턴스, 데이터베이스 인스턴스, 로드 밸런서 등 인프라

 

 

 

 

 

EBS 생성하기

언급되지 않은 것은 기본값으로 세팅

(EC2) 인스턴스, 로드 밸런서, Auto Scaling, S3 등에 자동으로 추가된 것을 확인 할 수 있습니다.

 

https://db.도메인/  으로 접속하기
리스너와 보안에 HTTPS 설정이 빠졌다면 각각 HTTPS 추가하기

 

 

 

 

 

 

HTTP를 HTTPS로 리다이렉트

 

 

'aws' 카테고리의 다른 글

2주차 [Docker] docker  (0) 2023.05.31
1주차 [Docker] Linux  (0) 2023.05.30
10. [aws] CDN  (0) 2023.05.26
09. [aws] S3 (긴 글, 반복 주의)  (0) 2023.05.26
08. [aws] VPC  (0) 2023.05.26

Cloudfront

Content Delivery Network(CDN)

시간과 비용을 절약하기 위해 static한 파일들을 Edge Locations에 캐싱을 한다.

수평적 확장성에 해당한다.

 

장점

  • 향상된 속도 : 지리적으로 가까운 서버에 캐싱된 데이터를 갖고 오기 때문에 무척 빠르다.
  • 안전 : CDN 서비스를 해주는 업체에서 방화벽을 제공할 뿐만 아니라 DDoS 공격(트래픽 공격)이 와도 서버가 분산되어 있고 캐시기능으로 오리진 서버 트래픽은 늘어나지 않는다.

단점

  • 캐시 : 최신 동적 컨텐츠를 제공해야하는 경우에 적합하지 않다.
  • 비용이 추가 발생한다

 

 

 

Cloud front 생성하기

 

이경우 버킷 이름이 동일하지 않아도 된다.

버킷 이름만 설정하고 나머지는 기본값으로 세팅한다.

새로 만든 버킷에 index.html을 업로드
원본 도메인에 새로 만든 버킷을 등록

 

 

 

 

S3 정책 업데이트 방법 1.

 

S3 정책 업데이트 방법2.

복사한 정책을 붙여넣고 저장

 

 

 

 

 

 

 

 

캐싱 인델리데이션

(index.html 수정 적용하기)

 

case1.

https://cdn.도메인/ 으로 접속하기

 

 

 

 

case2. (1이 작동 안 할 때)

https://cdn.도메인/ 으로 접속하기

 

 

 

 

'aws' 카테고리의 다른 글

1주차 [Docker] Linux  (0) 2023.05.30
11. [aws] EBS(Elastic Beanstalk) & http를 https로 리다이렉트  (0) 2023.05.26
09. [aws] S3 (긴 글, 반복 주의)  (0) 2023.05.26
08. [aws] VPC  (0) 2023.05.26
07. [aws] 도메인 HTTPS 연결  (0) 2023.05.26

Amazon Simple Storage Service(S3)

    인터넷 스토리지 서비스입니다. 이 서비스는 개발자나 IT 운영자가 웹 규모 컴퓨팅 작업을 수행하는 데 필요한 데이터 저장 공간을 제공합니다. Amazon S3는 웹 사이트 호스팅, 온라인 백업, 데이터 아카이브, 기업 애플리케이션, Big Data 분석 등 다양한 용도로 사용됩니다. 콘솔창에서 region 상관없이 S3를 모두 확인할 수 있습니다.

* 프론트엔드 - 정적 웹사이트 호스팅 /  백엔드 - 동적 웹사이트 호스팅

 

 

S3 서비스의 사용 예

  • 웹 사이트 호스팅
  • 멀티미디어 파일 저장 및 스트리밍
  • 애플리케이션 데이터 저장
  • 백업 및 복원
  • 아카이브

S3 서비스의 장점

  • 높은 내구성, 가용성 및 안정성
  • 손쉬운 사용 및 관리
  • 보안성
  • 높은 확장성

 

EBS는 단일 인스턴스에 대한 고성능 스토리지 서비스가 필요한 경우. Read/ Write가 빈번한 경우 사용한다.

S3는 비교적 저렵한것이 장점. 정적 웹 사이트도 지원하므로 여러개의 정적 HTML 페이지를 호스팅해야 하는 경우 사용. Write once Read many times 파일 수정 불가(덮어쓰기)

 

EFS EBS S3
NFS 파일 시스템 Block Storage object(객체) Storage
비쌈 평균
빈번한 Read / Write  빈번한 Read / Write  Write once Read many times
여러 AZ에 중복 저장 단일 AZ에 중복 저장 여러 AZ에 중복 저장
파일 수정 가능 파일 수정 가능 덮어쓰기
대규모 사용 사례에 적합  데이터베이스, ERP 시스템, 메일 서버, 쉐어포인트, 웹 서버, 디렉터리 서버, DNS 서버 또는 미들웨어에 적합 정적 웹사이트(프론트) 호스팅에 적합

 

 

Buckets?

버킷이란 데이터를 저장하는 가장 상위 레벨의 폴더 형태의 컨테이너입니다!

S3에 저장되는 파일들을 ‘객체’ 라고 부르고 모든 객체는 ‘키’(디렉토리)로 식별됩니다.

prefix/delimiter/object-name

s3://my-bucket/my_folder/my_file.txt

Amazon S3에서 버킷은 다음과 같은 목적으로 사용됩니다.

  • 데이터를 저장하는 컨테이너 역할
  • 객체에 대한 공용 또는 개인적인 접근 권한을 설정하기 위한 위치
  • 객체에 대한 특별한 이벤트 알림을 설정하기 위한 위치
  • AWS 계정에서 버킷 및 객체 사용에 대한 비용 추적 및 모니터링을 위한 위치

 

버킷 네이밍 컨벤션

  • 대문자 금지, 언더스코어 금지
  • 버킷 이름은 3자(최소)에서 63자(최대) 사이여야 합니다.
  • 버킷 이름은 소문자, 숫자, 점(.) 및 하이픈(-)으로만 구성될 수 있습니다.
  • 버킷 이름은 문자 또는 숫자로 시작하고 끝나야 합니다.
  • 버킷 이름에 두 마침표를 나란히 붙여 사용하면 안 됩니다.
  • 버킷 이름은 IP 주소 형식(예: 192.168.5.4)을 사용하지 않습니다.

 

 

버킷 생성하고 파일 업로드

모든 퍼블릭 액세스 차단 체크 해제

※ 버킷 이름과 apex 도메인 이름이 같아야 한다.

열기로 접속시 작성한 html이 보이지만 object URL 접속시 Access Denied

 

 

 

 

버킷폴리시

  • IAM과 유사하며 JSON 형식의 문서입니다.
  • 버킷의 모든 객체에 대한 액세스를 제어할 수 있습니다.
  • 특정 객체 또는 객체 그룹에 대한 액세스를 제어할 수 있습니다.
  • 특정 객체 또는 객체 그룹에 대한 액세스를 제어할 수 있습니다.
  • 액세스를 허용하는 IP 주소 또는 범위를 지정할 수 있습니다.
  • 액세스할 수 있는 리소스의 범위를 제한할 수 있습니다.
  • 암호화된 연결을 사용하도록 강제할 수 있습니다.

 

폴리시 예시

  • Resource : 버킷 혹은 오브젝트
  • Effect: Allow 혹은 Deny
  • Principal : 대상 유저
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowUserToGetBucket",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::ACCOUNT-ID:user/USERNAME"
            },
            "Action": "s3:GetBucketLocation",
            "Resource": "arn:aws:s3:::BUCKET-NAME"
        }
    ]
}

이 정책은 IAM 사용자 "USERNAME"이

GetBucketLocation 작업을 수행할 수 있도록

지정된 버킷 "BUCKET-NAME"에 대한 액세스를 허용합니다.

 

 

 

버킷 폴리시 설정하기

ARN에 aws Bucket ARN 붙여넣기
Resource 끝에 /*을 붙여 저장

 

 

 

 

 

ARN

  • AWS에서 사용하는 고유한 식별자로 AWS의 모든 리소스에 대한 고유한 식별자 역할을 합니다.
arn:partition:service:region:account-id:resource-id
arn:partition:service:region:account-id:resource-type/resource-id
arn:partition:service:region:account-id:resource-type:resource-id

//예시
arn:aws:iam::123456789012:user/johndoe
arn:aws:s3:::my_corporate_bucket/
arn:aws:ec2:us-east-1:123456789012:vpc/vpc-0e9801d129EXAMPLE
  • ARN은 다음과 같은 형식으로 구성됩니다.
    • arn: AWS 리소스 이름을 가리키는 고정 문자열
    • aws: 리소스가 AWS에서 호스팅되는 것을 나타내는 고정 문자열
    • service: AWS 서비스 이름을 나타내는 문자열 (예: s3, lambda, ec2 등)
    • region: AWS 리전 이름을 나타내는 문자열 (예: us-east-1, ap-northeast-2 등)
    • account-id: AWS 계정 ID를 나타내는 숫자
    • resource-id: 해당 리소스의 고유 식별자 (예: S3 버킷 이름, Lambda 함수 이름 등)

 

 

 

 

html 작성후 버킷에 업로드

<--index.html 파일로 아래 내용을 생성-->
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>프론트엔드</title>
</head>

<body>
    <h1>S3에 베포한 내 정적 사이트</h1>
</body>

</html>

저장

 

 

https://docs.aws.amazon.com/AmazonS3/latest/userguide/WebsiteAccessPermissionsReqd.html

 

<!--policy에 아래 코드 붙여넣기-->
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": [
                "이부분에 버킷 ARN 붙여넣기/*"
            ]
        }
    ]
}

 

 

 

 

 

 

S3에 도메인 네임 적용하기

버킷 이름과 도메인 이름은 반드시 동일해야합니다.

※ 보통 프론트에 apex 도메인(기본 도메인 ex. xxx.com)을 할당

※ 예시에서는 버킷과 도메인에 front. 를 앞에 붙여 생성했습니다.

위와 동일
버킷의 속성
레코드 이름 = 버킷 이름

※ 레코드 이름으로 접속은 돼는데 https:// 접속이 안됨.

'aws' 카테고리의 다른 글

11. [aws] EBS(Elastic Beanstalk) & http를 https로 리다이렉트  (0) 2023.05.26
10. [aws] CDN  (0) 2023.05.26
08. [aws] VPC  (0) 2023.05.26
07. [aws] 도메인 HTTPS 연결  (0) 2023.05.26
06. [aws] DNS, CNAME vs Alias  (0) 2023.05.23

Virtual Private Cloud(VPC)란?

    AWS에서 제공하는 클라우드 컴퓨팅 리소스를 사용할 수 있는 가상의 사설 네트워크입니다. 사용자는 VPC 내에서 IP 주소 범위, 라우팅 테이블, 서브넷 및 보안 그룹을 설정할 수 있습니다. 또한, VPC를 사용하면 사용자는 가상 서버, 스토리지 및 데이터베이스와 같은 다양한 AWS 리소스를 시작하고 관리할 수 있습니다. 

 

 

 

 

  • EC2, 로드밸런스 생성시 자동으로 VPC가 생성된다.
  • 하나의 VPC는 하나의 Region 안에 있다.
  • VPC 안에는 여러개의 AZ가 존재한다.
  • AZ 안에 서브넷이 존재한다.

 

 

 

 

서브넷, 게이트웨이, NAT

 

    ❓ 서브넷이란?

 

    VPC 내에서 IP 주소 범위를 지정하는 가상의 네트워크입니다. 서브넷은 라우팅 테이블에 연결되며, 각 서브넷은 하나의 라우팅 테이블에만 연결될 수 있습니다. 서브넷을 사용하면 VPC 내에서 다른 서브넷과 격리된 가상 네트워크를 생성할 수 있습니다. 이를 통해 다양한 서비스를 실행하는 데 필요한 보안 요구 사항을 충족시킬 수 있습니다.

 

  • 퍼블릭 서브넷은 인터넷 게이트웨이와 연결된 서브넷으로, 인터넷에 직접 연결되어 있는 서브넷입니다. 퍼블릭 서브넷을 사용하면 인터넷에서 직접 액세스할 수 있는 인스턴스를 실행할 수 있습니다. 이러한 인스턴스는 공인 IP 주소를 사용하며, 인터넷 게이트웨이를 통해 인터넷으로 트래픽을 보낼 수 있습니다.
  • 프라이빗 서브넷은 인터넷과 직접 연결되지 않는 가상의 네트워크입니다. 이러한 서브넷에서 실행되는 인스턴스는 인터넷에 직접 액세스할 수 없습니다. 대신, NAT 게이트웨이를 사용하여 인터넷을 통해 인스턴스에 연결하거나, VPC 피어링 등을 사용하여 다른 VPC와 연결할 수 있습니다.

 

    VPC의 라우팅 테이블(쉽게 말해 서브넷 안의 주소록)은 VPC 내에서 트래픽이 전달되는 방법을 제어하는 데 사용됩니다. 라우팅 테이블은 서브넷과 연결되며, 각 서브넷에는 하나의 라우팅 테이블이 있어야 합니다. 라우팅 테이블은 목적지 IP 주소와 대상 게이트웨이 또는 NAT 게이트웨이와 같은 대상을 매핑합니다. 라우팅 테이블은 여러 개의 라우팅 규칙을 포함할 수 있으며, 이를 사용하여 서브넷에서 트래픽을 전달하는 방법을 제어할 수 있습니다.

 

 

  • IGW (Internet Gateway)
    • VPC와 인터넷 간의 통신을 가능하게 하는 게이트웨이입니다.
    • 인터넷을 통해 인터넷 게이트웨이를 통해 VPC 내부로 들어오는 트래픽을 받아 해당 VPC에 연결된 서브넷으로 라우팅합니다.
  • NAT (Network Address Translation) Gateway
    • 프라이빗 서브넷에서 아웃바운드 인터넷 트래픽을 가능하게 하는 서비스입니다.
    • NAT 게이트웨이는 프라이빗 서브넷 내 인스턴스가 인터넷으로 나가는 트래픽을 대신하여 공인 IP 주소를 사용하고, 인터넷 게이트웨이로부터 들어오는 트래픽을 프라이빗 서브넷으로 라우팅합니다.

'aws' 카테고리의 다른 글

10. [aws] CDN  (0) 2023.05.26
09. [aws] S3 (긴 글, 반복 주의)  (0) 2023.05.26
07. [aws] 도메인 HTTPS 연결  (0) 2023.05.26
06. [aws] DNS, CNAME vs Alias  (0) 2023.05.23
05.5 [aws] Sqlectron  (0) 2023.05.23

HTTPS 연결

 

 

로드 벨런서 보안에 https 추가가 안되어있으면 추가
Status가 pending에서 success로 바뀜

'aws' 카테고리의 다른 글

09. [aws] S3 (긴 글, 반복 주의)  (0) 2023.05.26
08. [aws] VPC  (0) 2023.05.26
06. [aws] DNS, CNAME vs Alias  (0) 2023.05.23
05.5 [aws] Sqlectron  (0) 2023.05.23
05. [aws] RDS  (0) 2023.05.14

+ Recent posts