[Docker] 장고에 도커 적용하기 (1) - 도커 설치, 개발환경 셋팅

itisny·2024년 3월 9일
0
post-thumbnail

do it! 장고+부트스트랩 파이썬 웹 개발의 정석 책을 참고하며 작성한 포스팅입니다.

도커란?

도커는 다른 하드웨어와 운영체제에서 작업하더라도 동일한 환경을 갖출 수 있도록 도와주는 기술입니다.

작동원리

도커 설정 파일에는 웹 사이트 배포에 필요한 환경설정 정보를 모두 지정합니다.
예를 들자면 운영체제, 파이썬 버전, 라이브러리, 소스 코드, 이미지 파일 등이 있습니다.

도커를 실행하면, 도커 설정 파일에서 지정한 대로 서버 전체를 온전히 복제한 컨테이너 이미지가 생성됩니다.
그리고, 컨테이너 이미지를 작동시키면 컨테이너가 실행되면서 기존과 동일한 상태로 웹사이트 서버를 실행합니다.

도커 설정 -> 도커 실행 -> 컨테이너 이미지 생성 -> 컨테이너 이미지 실행 -> 컨테이너 실행 -> 웹 사이트 서버 실행

컨테이너 이미지에는 서버 전체가 온전히 담기기 때문에, 다른 컴퓨터에서 도커를 설치하고 이미지를 복제해서 작동하기만 하면, 기존과 동일한 상태로 웹사이트 서버 실행이 가능합니다.

도커 설치하기

윈도우 기준 설명입니다.

  1. 컴퓨터가 가상화 기능을 지원하는지 확인합니다.
    Ctrl+Alt+Del를 누르고 작업 관리자 창을 연 후, [성능] 탭의 CPU에서 가상화가 사용으로 되어있는지 확인합니다.

  2. 도커 사이트(https://www.docker.com/)에 들어갑니다.

  3. 도커를 설치합니다.

  1. 설치후 파란버튼을 눌러 윈도우를 재시작합니다.

  2. 도커가 잘 설치되었지 확인하기위해, 도커 버전을 확인해줍니다.

도커 파일 생성하기

  1. pip freeze > requirements.txt명령어로 가상환경에 설치한 라이브러리들을 리스트로 만들어 저장합니다.

  2. 프로젝트 폴더 안에 Dockerfile 파일 생성하기
    도커 설정 파일의 파일명은 기본적으로 Dockerfile로 약속되어 있습니다.
    저는 편집하기 쉽게, VS Code에서 Docker 익스텐션을 설치했습니다.

    아래와 같이 코드를 작성해줍니다.

    # pull official base image
    FROM python:3.12.0-alpine
    
    # set work directory
    WORKDIR /usr/src/app
    
    # set environment variables
    ENV PYTHONDONTWRITEBYTECODE 1
    ENV PYTHONUNBUFFERED 1
    
    RUN apk update
    RUN apk add postgresql-dev gcc python3-dev musl-dev zlib-dev jpeg-dev
    
    COPY . /usr/src/app/
    # install dependencies
    RUN pip install --upgrade pip
    RUN pip install -r requirements.txt
  • 도커는 파이썬이 설치되어 있는 이미지를 기본으로 제공하는데, 이 이미지를 FROM을 통해 불러옵니다.
  • 프로젝트 작업 폴더를 /usr/src/app으로 지정합니다.
  • 파이썬은 종종 소스 코드를 컴파일해서 확장자가 .pyc인 파일을 생성합니다. 도커를 이용할때는 이 파일이 필용하지 않으므로 PYTHONDONTWRITEBYTECODE 1을 설정해서 .pyc 파일이 생성하지 않도록 합니다.
  • PYTHONUNBUFFERED 1을 설정해서 파이썬 로그가 버퍼링 없이 즉각적으로 출력하게 만듭니다.
  • COPY {복사하고 싶은 폴더위치} {복사될 폴더 위치}로 로컬 컴퓨터에서 Dockerfile이 있는 위치에 있는 파일을 모두 작업 폴더(WORKDIR)로 복사합니다. 그러면 장고 프로젝트는 도커 이미지에 담깁니다.
  • RUN pip install -r requirements.txtrequirements.txt에 나열된 라이브러리를 설치합니다.
  1. 프로젝트 폴더 안에 docker-compose.yml 파일 생성하기
    도커 컴포즈 파일을 사용하면 컨테이너 여러 개를 한 번에 실행시킬 수 있고, 컨테이너를 실행시킬 때 옵션도 줄 수 있습니다.
    도커 컴포즈 파일의 파일명은 기본적으로 docker-compose.yml로 약속되어 있습니다.

    아래와 같이 코드를 작성해줍니다. (개발 환경 버전)

    version: '3'
    
    services:
      web:
        build: .
        command: python manage.py runserver 0.0.0.0:8000
        volumes:
          - ./:/usr/src/app/
        ports:
          - 8000:8000     
        env_file:
          - ./.env.dev
  • version에는 도커 컴포즈 파일 포맷 버전을 넣어줍니다.
  • web이라는 서비스 하나가 실행됩니다.
  • build: .는 현재 폴더를 빌드한다는 뜻입니다. Dockerfile이 있는 위치를 지정하여 컨테이너 이미지를 만듭니다.
  • volumes로 로컬 컴퓨터의 폴더와 도커 폴더를 연결합니다. 여기서는 현재 폴더를 /usr/src/app 폴더와 연결하고 있습니다.
  • env_file을 따로 명시함으로써 오류 페이지가 다른 사람에게 보이지 않도록 개발환경(.env.dev)과 배포환경(.env.prod)로 나누어 관리합니다. 현재 배포용이 없으므로 개발환경 파일(.env.dev)만 지정했습니다.
  1. settings.py 수정 후, 개발환경 파일 생성하기

    • settings.py 수정
      프로젝트에서 개발환경 파일(.env.dev)을 활용할 수 있도록 settings.py를 수정합니다. 로컬과 배포환경에서 settings.py를 다르게 적용하기 위해 수정하는 것입니다.
      os.environ.get()으로 개발환경 파일에서 값을 읽어올 수 있을 때는 그 값을 사용하고, 없을 때는 두 번째 매개변수 값을 활용합니다.
    import os
    from pathlib import Path
    
    BASE_DIR = Path(__file__).resolve().parent.parent
    
    SECRET_KEY = os.environ.get(
        "SECRET_KEY", "*****장고시크릿키******"
    )
    
    # SECURITY WARNING: don't run with debug turned on in production!
    DEBUG = os.environ.get("DJANGO_DEBUG", "") != "False"
    
    if os.environ.get("DJANGO_ALLOWED_HOSTS"):
        ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS").split(" ")
    else:
        ALLOWED_HOSTS = []
    
    # Set CSRF trusted origins to allow any app on Railway and the local testing URL
    CSRF_TRUSTED_ORIGINS = ["https://*.railway.app", "https://*.pythonanywhere.com"]
    
    # 생략...
    • SECRET_KEY : '*****'에는 프로젝트에서 적혀진 부분을 그대로 사용합니다.
    • DEBUG
      로컬에서 개발할때는 DEBUG가 True로 설정되어 디버그 모드를 활성화하고, 배포 환경에서는 DEBUG를 False로 설정하여 보안을 강화하겠습니다.
    • ALLOWED_HOSTS
      HOST로 허용하는 주소를 적어두는 곳입니다. 서비스로 공개할 때는 보안을 위해 서버가 될 URL만 남겨놔야합니다. 반대로, 개발할때는 127.0.0.1이나 localhost로 장고에 접근할 수 있어야 합니다. 그래서 env 파일에서 DJANGO_ALLOWED_HOSTS를 읽어올 수 있으면 그 값을 사용하고, 없다면 이전과 동일하게 되도록 설정합니다.
    # 개발환경 파일 생성
    
    SECRET_KEY="*****장고시크릿키*******"
    DJANGO_DEBUG=True
    DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1]
    • DJANGO_ALLOWED_HOSTS에는 개발할 때 활용할 주소를 적었습니다.
  2. 도커 컨테이너 실행
    터미널에서 docker-compose build 명령어로 이미지를 만들고, docker-compose up으로 컨테이너를 실행합니다.

    (venv) $ docker-compose build
    (venv) $ docker-compose up

    docker-compose up을 했을때 잘 실행 되는 것을 확인했고, 127.0.0.1:8000에도 잘 접속되는 것을 확인했습니다.
    서비스를 멈출 때는 Ctrl+c를 눌러줍니다.

    docker-compose up -d 명령어를 입력하면, 로그없이도 웹 접속이 가능한 것을 확인할 수 있습니다.

    추가로, Vs Code 익스텐션을 통해 이미지 생성과 콘테이너가 실행되는 것을 확인할 수 있습니다.

  3. 잘 실행되는 것을 확인했으니, docker-compose down 명령어로 컨테이너 중단을 해줍니다. 그러면 실행중인 컨테이너가 삭제된 것을 확인할 수 있습니다.

DB 사용하기

장고는 기본적으로 sqlite3로 데이터베이스를 제공합니다.
파일을 이용한 데이터베이스이기 때문에 특별한 설정 없이도 간편하게 사용할 수 있다는 장점이 있습니다.
하지만, 프로젝트 규모가 커지거나 사용자가 많을 경우 충분한 성능을 기대하기 어렵다는 단점이 있습니다.
그래서, 따로 데이터베이스를 두어 웹사이트를 실행해보겠습니다.
이번에 사용할 데이터베이스는 PostgreSQL입니다.

만약 도커를 사용하지 않는다면 로컬 컴퓨터에서 PostgreSQL을 설치하고, 서버에서도 또 한 번 설치/설정 작업을 해야합니다. 도커가 있기에 이 작업을 단순화 할 수 있습니다. 도커 짱👍

  1. 기존 docker-compose.yml에 데이터베이스만 담당하는 컨테이너 추가하기
    docker-compose.yml을 이용하면 여러 개의 컨테이너를 한 번에 실행 시킬 수 있는데요, 장고는 web이라는 컨테이너에서 실행하고, 데이터베이스를 담당하는 부분은 db라는 이름의 컨테이너에서 실행하도록 설정하겠습니다.

    # 생략
    
    services:
      web:
        # 생략
        depends_on:
          - db
    
      db:
        image: postgres:12.0-alpine
        volumes:
          - postgres_data:/var/lib/postgresql/data/
        environment:
          - POSTGRES_USER=eatwell_db_user
          - POSTGRES_PASSWORD=eatwell_db_pwd
          - POSTGRES_DB=eatwell_dev
    
    volumes: 
      postgres_data:
    
    • web 컨테이너는 db 컨테이너가 실행된 이후에 시작할 수 있도록 depends_ondb로 설정합니다.
    • 이미지는 도커에서 공식으로 제공하는 postgres:12.0-alpine로 사용했습니다.
    • volumes을 설정해서 컨테이너 실행이 중단되더라도 DB 내용이 사라지지 않도록 합니다.
    • PostgreSQL을 사용하기 위한 사용자명, 암호, DB명을 지정합니다.
      DB명은 개발용이라는 것을 표시하기 위해 eatwell_dev로 구분했습니다.
  2. settings.py에 있는 DB 연결 수정하기
    DB를 Sqlite3로 사용할지, PostgreSQL로 사용할지는 settings.py에 정의되어 있습니다. 장고는 프로젝트를 생성할때 자동으로 데이터베이스에 대한 내용을 설정합니다.

    # settings.py
    
    DATABASES = {
        "default": {
            "ENGINE": os.environ.get("SQL_ENGINE", "django.db.backends.sqlite3"),
            "NAME": os.environ.get("SQL_DATABASE", BASE_DIR / "db.sqlite3"),
            "USER": os.environ.get("SQL_USER",'user'),
            "PASSWORD": os.environ.get("SQL_PASSWORD",'password'),
            "HOST": os.environ.get("SQL_HOST",'localhost'),
            "PORT": os.environ.get("SQL_PORT",'5432'),
        }
    }

    USER, PASSWORD, HOST, PORT는 PostgreSQL을 관리하는데 필요한 내용입니다.

  3. .env.dev 파일 업데이트하기

    # 생략
    SQL_ENGINE=django.db.backends.postgresql
    SQL_DATABASE=eatwell_dev
    SQL_USER=eatwell_db_user
    SQL_PASSWORD=eatwell_db_pwd
    SQL_HOST=db
    SQL_PORT=5432

    PostgreSQL을 프로젝트의 settings.py에서 활용할 수 있도록 .env.dev 파일을 업데이트 합니다.

  4. psycopg2 모듈 설치하기
    psycopg2 모듈은 파이썬에서 PostgreSQL을 사용할 수 있게 해줍니다.
    그리고 pip freeze로 requirements.txt에 psycopg2가 반영된 결과를 반영합니다.
    도커 이미지를 만들어서 활용해야 하므로, requirements.txt에 필요한 모듈을 추가하고 도커 이미지에 반영합니다.

    (venv) $ pip install psycopg2
    (venv) $ pip freeze > requirements.txt
  5. 이미지 빌드하고 실행하기
    docker-compose build로 이미지를 빌드하고, docker-compose up으로 실행합니다.

  6. web 컨테이너에 접속해서 데이터베이스 마이그레이션하기
    도커 컨테이너가 실행되는 상태에서 다른 새로운 터미널을 열어 docker-compose exec web python manage.py migrate을 입력합니다. 도커로 만든 web 컨테이너에 접속해서 python manange.py migrate을 실행하라는 뜻입니다.

  7. 새로운 관리자 계정과 포스트 만들기
    새로 데이터베이스를 만들었기 때문에 데이터들이 존재하지 않습니다.
    그래서 관리자 계정을 먼저 만든 다음 admin 사이트에 들어가서 글 하나를 만들겠습니다.

    • docker-compose 명령을 이용해서 현재 실행 중인 web 컨테이너에 접속해서 superuser을 만들어 줍니다.

      (venv) $ docker-compose exec web python manage.py createsuperuser 
    • admin 사이트에 들어가서 글 하나를 등록해줍니다.

    • 상세 페이지에 들어가면 작성한 글이 보이는 것을 확인할 수 있습니다.

      Ctrl+c를 눌러 컨테이너 실행을 중단시키고 다시 컨테이너를 실행해도 데이터베이스에 저장했던 내용은 사라지지 않고 보존되는 것을 확인할 수 있습니다.

0개의 댓글