서비스를 만들면서 어려운 점을 순위 매겨본다면 배포는 분명 세 손가락안에 들 것이다. 개발을 시작한지 얼마되지 않아서 클론 코딩이나 게시판 같은 어플리케이션을 만든 후 마주하는 암흑어둠의 흑막인 킹제네럴갓충무공카이사르알렉산더 악당같은 검은 터미널 창이 앞으로 길이 쉽지 않을 것을 보여주는 것 같다. 물론 배포가 어려운 것은 웹서버나 WAS의 내부적인 동작을 명확히 알지 못하기 때문일 것이다. 이런 어려움을 제외하더라도 배포는 결코 쉬운 과정이 아니다.
이번 포스팅은 배포의 어려움을 덜어줄 방법에 대해 소개할 것이다. 바로 도커를 이용한 Django(WAS) + Nginx(Web server) 배포다. 물론 도커가 배포의 어려움만을 덜어주는 기술은 아니다. 여러 장점 중 하나가 쉽게 배포할 수 있게 해주는 것이다. 도커를 이용한 배포를 익힐 겸 그리고 배포의 부담을 덜 겸해서 오늘의 주제를 다뤄보도록 하겠다. 이 포스팅을 다 읽는다면 여러분도 이제 도커 주니어로서 새 삶이 시작될 것이다.
1. Django 어플리케이션 만들기
첫번째 과정은 간단한 장고 어플리케이션을 만들어보겠다. 만약 이미 제작한 어플리케이션이 있으신 분은 이 단계를 건너 뛰어도 된다. 먼저 디렉토리를 하나 만들고 해당 프로젝트의 가상환경을 만들어주고 장고를 받아주자. 나는 pipenv를 사용할 것이다. 다른 가상환경 툴을 사용하는 사람도 있겠지만 pipenv 좋은 툴중에 하나이니 사용해보는 것을 추천한다.
pip install pipenv
pipenv shell
pipenv install django
test_page라는 이름의 프로젝트를 만들어줄 것이며 아래 명령어를 사용하면 된다.
django-admin startproject test_page
#test_page에 원하는 프로젝트 이름을 적으면 된다.
#가상환경에 받은 패키지를 requirements.txt에 저장
pipenv run pip freeze > requirements.txt
이 명령어를 작성하면 장고가 자동으로 폴더를 하나 만드는데 아래처럼 생겼다.test_page안에 다시 test_page라는 이름과 manage.py가 들어가 있는데 우리는 test_page안에 있는 폴더랑 파일을 밖으로 꺼내주도록하자.
이제 우리는 배포의 첫단계를 마쳤다. 이제 몇가지 설정을 진행하도록 하겠다.
첫번째로 test_page/settings.py의 ALLOWED_HOSTS에 "0.0.0.0"과 "website"를 추가해주자
두번째로 동일한 파일에 STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')를 추가해주자.
ALLOWED_HOSTS = ['0.0.0.0', "website"]
import os
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
2. Nginx 설정 파일
자 이제 test_page 폴더안에 nginx라는 폴더을 만들어주고 default.conf라는 ㅜ을 하나 생성해주자. default.conf는 Nginx의 동작을 을 설정하는 파일이다. 생성한 default.conf에 아래 내용을 붙여넣어주도록 하자. 설정에 대한 자세한 내용은 나중에 다루도록 하겠다. 만약 아직 Nginx 즉 WebServer가 어떤 일 하는지 모른다면 아래 포스팅을 참고하자.
upstream website {
server web:8000;
}
server {
client_max_body_size 16M;
# static 파일을 제공해야할 경우
location /static/ {
autoindex on;
alias /code/staticfiles/;
}
# media 파일 제공
location /media/ {
autoindex on;
alias /code/media/;
}
# 프록시 설정, nginx 뒤에 WAS가 있을 경우
location / {
proxy_pass http://website/;
}
# 포트 설정
listen 80;
server_name localhost;
}
3. Docker 설정
아니 언제 도커를 쓰는거야 라고 생각한 당신. 오랫동안 기다리느라 고생했다. 이제 도커 설정을 해보자. 먼저 도커를 설정하기전 이미지와 컨테이너 개념에 대해서 알아야하는데 모른다면 아래 포스팅을 통해 확인하자. 머리가 좋은 사람은 자신이 아는 것이라도 의도적으로 지식의 노출 횟수를 늘려 자신의 지식을 곤고히 한다고 한다.
자 이제 이미지와 컨테이너에 대해 이해했다면 이제 우리가 사용할 도커 컴포즈에 대해 알아보자. 도커 컴포즈는 여러개의 이미지를 한번에 손쉽게 빌드하거나 실행시킬 수 있도록 도와주는 프로그램이다. 우리는 이 배포에서 python 이미지와 nginx 이미지 두 이미지를 사용할 것이며 nginx 이미지는 그대로 사용하지만 python 이미지는 DockerFile를 이용해 커스텀화 해서 사용할 것이다.
3.1 DockerFile 작성하기(python)
먼저 manage.py가 있는 디렉토리에 DockerFile를 만들어주자. 각 명령어별로 주석을 달아놓았다.
#아래 적힌 이미지를 베이스 이미지로 한다.
#이 명령어가 실행되면 Dockerhub에서 해당 이미지를 pull한다.
FROM nikolaik/python-nodejs:python3.8-nodejs14
#mkdir 명령어를 실행한다.
RUN mkdir /code
#동작 디렉토리를 /code로 옮긴다.
WORKDIR /code
#requirement.txt를 code 아래로 옮긴다.
ADD ./requirements.txt /code/requirements.txt
RUN pip install -r /code/requirements.txt #requirement.txt를 읽어서 필요한 패키지를 다운받는다
RUN pip install gunicorn #python과 nginx를 연결해주는 interface
ADD . /code #현재 디렉토리를 /code에 복사해서 넣겠다
RUN ["chmod", "+x", "start.sh"] # bash script 권한 설정
ENTRYPOINT ["sh","./start.sh"] # bash script 실행, 이 스크립트는 다음 챕터에서 만들겠다
위에서 나온 start.sh는 아래와 같이 같은 디렉토리에 작성해주면 된다. 배포를 자동화하기 위한 세팅이다.
#!/bin/sh
echo "==> Migration 파일 생성"
yes | python manage.py makemigrations --settings=config.deploy.settings
echo "==> Migrate 실행"
python manage.py migrate --settings=config.deploy.settings --fake-initial
echo "==> collectstatic 실행"
python manage.py collectstatic --settings=config.deploy.settings --noinput -v 3
echo "==> 패키지 다운로드"
pip install -r /code/requirements.txt
echo "==> 배포!"
gunicorn -b 0.0.0.0:8000 --env DJANGO_SETTINGS_MODULE=test_page.settings test_page.wsgi:application
3.2 docker-compose.yml 작성하기
위에서 우리는 파이썬 이미지에 대한 DockerFile를 작성했다. 이제 파이썬 이미지와 Nginx 이미지를 한번에 실행하도록 하는 docker-compose 설정 파일 docker-compose.yml를 작성하겠다. manage.py와 같은 디렉토리에 docker-compose.yml를 만들고 아래와 같이 작성해주자. 각 부분에 대한 설명은 주석으로 남겼다.
version: '3' #docker-compose 버전을 나타냄
services:
nginx: #nginx라는 이름으로 container 실행
image: nginx:latest #베이스 이미지가 nginx:latest
ports: #해당 컨테이너의 포트를 호스트(배포할 서버) 포트와 연결
- "80:80"
#컨테이너 디렉토리와 호스트 디렉토리를 연결 시켜준다.
volumes:
- .:/code #현재 위치와 /code(django 어플리케이션이 있는 위치)
- ./test_page/nginx:/etc/nginx/conf.d #niginx 설정파일이 있는 위치
depends_on: #컨테이너 의존관계를 의미한다.
- web #아래 적혀있음
web: #web이라는 이름으로 container 실행
build:
context: .
dockerfile: Dockerfile #아까 작성한 DockerFile를 바탕으로 이미지 빌드
volumes: #디렉토리 연결
- .:/code
ports: #호스트 포트와 컨테이너 포트를 연결
- "8000:8000"
env_file:
- .env
4. 배포하기
자 고생 많았다. 이제 배포를 진행해보자. 먼저 깃허브에 repository를 만들어주고 깃허브에 올린 후 배포할 서버에서 pull 해주도록 하겠다. 배포할 서버는 AWS EC2를 사용할 것이고 EC2 인스턴스를 여는 과정과 github에 올리는 방법은 다른 분들의 글을 참고하길 바란다.
https://mine-it-record.tistory.com/115
서버를 열었으면 아래 명령어들을 통해 docker, git 등을 받아주고 작성한 코드를 깃허브에서 당겨오자. 아래 깃허브에서 clone해서 사용해도 된다. https://github.com/junha6316/django-docker 그리고 당겨온 디렉토리로 이동하자.
sudo yum update
sudo yum install -y docker git
sudo systemctl enable docker.service
sudo systemctl start docker.service
sudo systemctl status docker.service
#docker-compose 다운로드
sudo curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
#권한 변경
sudo chmod +x /usr/local/bin/docker-compose
#심볼릭 링크 생성
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
git clone https://github.com/junha6316/django-docker
cd django-docker
이제 마법의 세 단어를 적어보자. 중간중간에 permission denied나 command not found가 뜰 수 있는데 아래를 참고하자.
https://stackoverflow.com/questions/38775954/sudo-docker-compose-command-not-found
sudo docker-compose up
#백그라운드에서 실행시키고 싶다면
sudo docker-compose up -d
정상적으로 진행되었다면 크롬에서 해당 주소로 접근하면 아래와 같은 창이 뜰 것이다. 만약 계속 로딩중이라면 포트나 AWS의 경우에는 보안그룹을 확인해보면 될 것이다. 만약 본인이 생성한 프로젝트로 이 과정을 진행하다면 경로확인을 꼭 하길 바란다.
'Web Programming > Docker' 카테고리의 다른 글
[docker] DockerFile cheetsheet (0) | 2022.10.17 |
---|---|
[Docker] Trouble Shooting (0) | 2021.07.13 |
[Docker] Docker Pull 명령어 사용하기 (0) | 2020.12.26 |