개발하는 자몽

[AWS] EC2 인스턴스 내 Docker 설치와 Django 프로젝트 설정 본문

Architecture & Tool/AWS

[AWS] EC2 인스턴스 내 Docker 설치와 Django 프로젝트 설정

jaamong 2024. 3. 23. 09:21

🔖 이 글에서는 아래의 주제를 다룹니다.

  • 인스턴스 내 Docker 설치
  • 프로젝트 클론
  • 파이썬 설치
  • 가상환경(venv) 설치
  • 패키지(requirements.txt) 설치 
  • 서버 실행 (docker compose)

 

Notice EC2 AMI - Ubuntu 22.04 LTS 기준 작성

 

인스턴스 내 Docker 설치

Ubuntu에서 Docker를 설치하는 방법은 Docker 공식 홈페이지에 있는 Ubuntu 설치를 보고 따라 하면 된다.

 

  1. 인스턴스에 접속한다. 접속 방법은 vscode나 터미널 등으로 하면 된다. vscode로 접속하는 방법은 여기를 참고!
  2. 접속(서버 연결)이 완료됐다면 터미널에 아래와 같이 입력하여 우분투 시스템 패키지를 업데이트한다.
    $ sudo apt-get update
  3. Docker의 `apt` 레포지토리를 설정한다.
    # Add Docker's official GPG key:
    $ sudo apt-get update
    $ sudo apt-get install ca-certificates curl
    $ sudo install -m 0755 -d /etc/apt/keyrings
    $ sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
    $ sudo chmod a+r /etc/apt/keyrings/docker.asc
    
    # Add the repository to Apt sources:
    $ echo \
      "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
      $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
      sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
    $ sudo apt-get update
  4. Docker 패키지를 설치한다. 설치 시 가장 최신 버전을 원하는 경우 아래와 같이 입력한다.
    $ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
  5. 마지막으로 잘 설치됐는지 확인하기 위하여 아래 명령어를 입력한다.
    $ sudo docker run hello-world
  6. 입력 후 터미널에 나오는 문구가 아래와 같다면 정상적으로 설치가 완료된 것이다.
    Unable to find image 'hello-world:latest' locally
    latest: Pulling from library/hello-world
    c1ec31eb5944: Pull complete 
    Digest: sha256:4bd78111b6914a99dbc560e6a20eab57ff6655aea4a80c50b0c5491968cbc2e6
    Status: Downloaded newer image for hello-world:latest
    
    Hello from Docker!
    This message shows that your installation appears to be working correctly.
    
    To generate this message, Docker took the following steps:
     1. The Docker client contacted the Docker daemon.
     2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
        (amd64)
     3. The Docker daemon created a new container from that image which runs the
        executable that produces the output you are currently reading.
     4. The Docker daemon streamed that output to the Docker client, which sent it
        to your terminal.
    
    To try something more ambitious, you can run an Ubuntu container with:
     $ docker run -it ubuntu bash
    
    Share images, automate workflows, and more with a free Docker ID:
     https://hub.docker.com/
    
    For more examples and ideas, visit:
     https://docs.docker.com/get-started/

번외.

Docker 설치 이후 `docker ps` 명령을 입력했을 때 `permission denied` 에러가 발생하는 경우 아래와 같이 진행한다`.

 

  1. docker 그룹에 user 추가
    $ sudo usermod -aG docker {계정명}
    $ cat /etc/group | grep docker
    서버 재접속 후 `docker ps` 확인
  2. 1번 방법으로 해결이 안 된다면 직접 권한을 부여해야 한다.
    $ sudo chmod 666 /var/run/docker.sock
    위 명령어는 /var/run/docker.sock 파일의 소유자, 그룹, 다른 모든 사용자들의 권한을 읽기와 쓰기로 설정한다.

 

프로젝트 클론

클론 전 EC2 인스턴스에 본인의 계정을 추가한다. 관련 방법은 여기 링크에서 번외 중 계정 추가를 참고한다.

레포지토리 클론

클론 전에 EC2 인스턴스에 본인의 계정을 추가했다면 `sudo su {계정명}`으로 계정 스위칭을 진행한다. 그다음 `git config --global`을 이용하여 본인의 버전 관리 시스템(GitHub, Gitea,...) 계정을 추가한다. 자세한 Git 계정 설정은 여기 링크를 참고한다. 

 

이제 클론! 터미널에 아래 명령어를 입력한다. 

$ git clone {git_remote_url}.git

 

서브 모듈이 있다면 아래와 같이 입력한다. 단, 아래 명령어는 Git 2.13 버전부터 가능하니 그전에 `git --version` 명령어로 버전을 확인하자. 

$ git clone --recurse-submodules <remote-repo-url>

버전을 충족하지 않는 경우 여기 글을 참고하자.

디렉터리 위치 옮기기

Ubuntu에서 각 디렉터리의 의미를 확인해 보고, 적절한 곳에 클론 받은 디렉터리/프로젝트를 옮겨보자. 

 

리눅스 디렉토리 종류와 특징

디렉토리란 파일 저장소를 의미하며, 리눅스 디렉토리는 최상위 디렉토리를 기준으로 하위 디렉토리들이 존...

blog.naver.com

 

나는 `/home/`에 위치시켰다. (그냥 root에 놓을 걸 그랬나...)

$ mv {현재 위치}/{repo 이름} /home/

`Permission denied` 에러 발생 시 `mv` 명령어 앞에 `sudo`를 붙여서 다시 실행한다.

 

 

파이썬 설치

파이썬 설치 참고 자료
 🔗 https://mungto.tistory.com/289
 🔗 https://ko.linux-console.net/?p=15722

⚠️ SSL 적용

파이썬 설치 전에 OpenSSL을 설치 및 적용해야 한다. 그렇지 않으면 pip 사용 시 아래와 같은 에러를 만날 수 있기 때문이다...

(.venv) {계정명}@{IP}:/home/{프로젝트명}$ pip install -r requirements.txt
WARNING: pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available.
WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError("Can't connect to HTTPS URL because the SSL module is not available.")': /simple/aiobotocore/
WARNING: Retrying (Retry(total=3, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError("Can't connect to HTTPS URL because the SSL module is not available.")': /simple/aiobotocore/
WARNING: Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError("Can't connect to HTTPS URL because the SSL module is not available.")': /simple/aiobotocore/
WARNING: Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError("Can't connect to HTTPS URL because the SSL module is not available.")': /simple/aiobotocore/
WARNING: Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError("Can't connect to HTTPS URL because the SSL module is not available.")': /simple/aiobotocore/
Could not fetch URL https://pypi.org/simple/aiobotocore/: There was a problem confirming the ssl certificate: HTTPSConnectionPool(host='pypi.org', port=443): Max retries exceeded with url: /simple/aiobotocore/ (Caused by SSLError("Can't connect to HTTPS URL because the SSL module is not available.")) - skipping
ERROR: Could not find a version that satisfies the requirement aiobotocore==2.5.0 (from versions: none)
ERROR: No matching distribution found for aiobotocore==2.5.0
WARNING: pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available.
Could not fetch URL https://pypi.org/simple/pip/: There was a problem confirming the ssl certificate: HTTPSConnectionPool(host='pypi.org', port=443): Max retries exceeded with url: /simple/pip/ (Caused by SSLError("Can't connect to HTTPS URL because the SSL module is not available.")) - skipping
 

SSLError("Can't connect to HTTPS URL because the SSL module is not available.

python3.7을 설치한 후 pip까지 설치가 끝난 후 pip로 모듈을 다운로드 받을려고 할때 아래와 같은 에러가 ...

blog.naver.com

 

만일 벌써 발생했다면, 파이썬을 제거한 후 재설치해야 한다. 인터넷에 나오는 대중적인 방법과 여러 방법을 다 시도했을 때 다 실패해서 재설치했다😇. (아마 찾으면 대부분 ` --trusted-host` 옵션을 알려주는데 보안적으로 좋지 않은 방법이라 별로 추천하고 싶지 않다. 그냥 깔끔하게 재설치하자^^) Ubuntu 환경에서 특정 버전의 파이썬을 제거하는 방법은 여기를 참고하자.

 

이제 OpenSSL 및 관련 라이브러리를 설치한다.

$ sudo apt-get update
$ sudo apt-get install openssl libssl-dev

 

완료했으면 파이썬 설치로 넘어간다!

 

파이썬 설치

  1. 우분투 시스템 패키지를 업데이트한다.
    $ sudo apt-get update
  2. 다음 링크에 들어가서 원하는 버전을 받을 수 있는 주소를 찾는다.
    → 🔗 https://www.python.org/ftp/python/

    예를 들어, 3.8.18 버전이라면 다음과 같은 주소가 된다.
    https://www.python.org/ftp/python/3.8.18/
  3. 우분투에서 2번에서 찾은 경로를 이용하여 다운로드를 진행한다.
    $ sudo wget https://www.python.org/ftp/python/3.8.18/Python-3.8.18.tgz
  4. 다운로드를 완료하면 압축을 풀고 해당 폴더로 이동한다.
    $ sudo tar zxf Python-3.8.18.tgz
    $ cd Python-3.8.18/
  5. 파이썬 설치에 필요한 필수 종속성과 패키지를 설치하기 전에 종속성을 설치하려면 다중 저장소 저장소를 활성화해야 한다고 한다. 아래 주어진 명령을 실행하여 활성화할 수 있다.
    $ sudo apt-add-repository multiverse
  6. 종속성 설치를 진행한다.
    $ sudo apt-get install build-essential checkinstall 
    $ sudo apt-get install libreadline-gplv2-dev libncursesw5-dev libssl-dev libsqlite3-dev tk-dev libgdbm-dev libc6-dev libbz2-dev
  7. 설치가 완료되었으면, 컴파일을 진행한다. 위치는 압축을 해제한 파이썬 디렉터리 안이다.
    $ sudo ./configure --enable-optimizations
  8. 이제 적용하는 단계로, 기존 Python 바이너리를 덮어쓰는 것을 방지한다.
    $ sudo -H make altinstall
  9. 완료 후 파이썬 버전을 확인한다.
    $ python3 --version
    버전이 바뀌지 않았다면 `PATH`를 변경한다. 버전이 바뀌었다면 변경은 넘어가도 된다.

PATH 변경

  1. 아래 명령어로 위치를 찾는다.
    $ which python
    /usr/bin/python3
  2. 해당 경로를 기억하고 설정을 위해 아래 명령어를 입력한다.
    $ vim ~/.bashrc
  3. 파일 맨 하단에 아래와 같이 입력하고 vim을 종료한다. `PATH`와 `=` 사이는 띄어쓰기 없이 입력해야 한다. 
    ...
    
    export PATH={which python 결과}:$PATH

    `PATH`에 1번에서 입력한 명령어의 결과물을 입력한다. 아래는 예시다.
    ...
    
    export PATH=/usr/bin/python3:$PATH
  4. 변경한 내용을 적용하기 위해 아래와 같이 입력한다.
    $ source ~/.bashrc
  5. 버전을 확인한다.
    $ python3 --version

 

가상환경(venv) 설치

  1. 우분투 시스템 패키지를 업데이트한다.
    $ sudo apt-get update
    $ sudo apt-get upgrade
  2. `pip`가 설치되어 있지 않다면, `python3-pip`를 설치한다.
    $ pip --version  # pip 버전 확인
    $ sudo apt-get install python3-pip  # 없으면 설치
  3. 파이썬 가상환경 패키지를 설치한다.
    $ sudo apt-get install python3-venv
  4. 가상환경을 설치할 곳으로 이동하여 다음 명령어를 입력하여 가상환경을 생성한다. 이때 개발 환경에 맞는 파이썬 버전의 가상환경을 생성한다.
    # 터미널에 python을 입력했을 때 나오는 파이썬 버전으로 생성
    $ python3 -m venv {원하는 이름}
    $ python3 -m venv .venv
    
    # 또는 특정 버전의 파이썬 버전으로 생성
    python3.8 -m venv .venv
    꼭 `.venv`로 할 필요는 없으나, 대부분 해당 이름으로 진행한다
  5. 설치가 완료되었으면 가상환경을 활성화할 수 있다.
    $ source .venv/bin/activate  # 활성화
    $ deactivate  # 비활성화

 

패키지(requirements.txt) 설치

위에서 Django 프로젝트를 클론 했을 때 `requirements.txt` 파일이 있을 수 있다. 해당 파일을 이용하여 필요한 패키지들을 설치한다.

$ python3 -m pip install -r requirements.txt
⚠️ `pip` 사용 시 `sudo`를 함께 사용하지 마세요. 나중에 권한 문제가 발생합니다.

pip 에러 관련 1

설치 중에 특정 패키지 구간에서 에러가 난다면, 에러문구를 잘 보고 반드시 구글링 하자. 대부분 필요한 종속성 중에 없는 것을 설치하라고 알려줄 테니, 해당 종속성을 설치하면 된다.

 

pip 에러 관련 2

가상환경에서 패키지 설치 시 아래와 동일한 에러가 나면 권한 설정을 해야 한다.

ERROR: Could not install packages due to an OSError: [Errno 13] Permission denied: '/venv_3.8/lib/python3.8/site-packages/sqlparse'
Check the permissions.

아래 명령어로 권한 설정을 한다.

$ sudo chown -R $(whoami) {가상환경 경로}
$ sudo chown -R $(whoami) /home/{프로젝트명}/.venv/

 

서버 실행 (docker compose)

모든 환경 설정이 완료됐다면, 이전 서버에서 사용했던 그대로 docker compose를 실행하고 오류가 발생하는지 확인하자.

$ docker compose up --build

DB 연결 확인

잘 띄워졌으면 DB 연동에도 문제가 없는 상태일 것이다. 도커 컨테이너를 띄우는 과정에서 DB 연동으로 에러가 발생한다면 아래 항목을 확인한다.

  • 보안 그룹에서 해당 DB를 위한 포트(port)가 열려있는지
  • 해당 DB에 접근 권한이 있는지
  • DB 계정을 정확하게 작성했는지
  • 접근하는 EC2 인스턴스의 IP를 잘 기입했는지

API 호출 확인

모두 해결하고 컨테이너도 잘 띄워졌다면 이번에는 API 호출을 테스트한다. 포스트맨을 이용하여 API를 호출해 보자.

아래 사진은 포스트맨에서 API를 호출한 화면이다. `host_pub_ip` 변수는 EC2 인스턴스의 public IP, `host_port`에는 Django 서버용으로 도커 컨테이너에서 열려있는 port를 의미한다. https 적용 전이므로 http 프로토콜로 요청한다.

 

 

🎉 이제 AWS EC2 인스턴스 생성 및 환경 설정, Django 서버 실행하기까지 모두 끝났다!

 

 

 

Comments