Django 2.4 서버 구축 및 연결 - 배포 스크립트 작성

Kwon, Hyojin·2021년 3월 7일
1

Django

목록 보기
7/9
post-custom-banner

매번 작업물이 변경될 때마다 직접 도커를 올리고 받고 실행하기가 번거로울 것입니다.

여러 가지 방법이 있겠지만, 여기서는 배포 스크립트(Python)를 작성하여 파일을 실행시키면 바로 배포가 되도록 만들어 보겠습니다.

  1. velog/deploy.py 파일 생성

    #!/usr/bin/env python3  	# python3으로 동작하는 스크립트를 실행시킬 셔뱅(shebang) 
    import os
    import subprocess		# 다른(새로운) 프로세스를 실행하기 위한 모듈
    from pathlib import Path
    
    from decouple import config
    
    HOME = str(Path.home())
    IDENTITY_FILE = os.path.join(HOME, '.ssh', 'id_rsa')  	# ssh key 생성 필요
    SERVER_NAME = config('SERVER_NAME')  			# velog/.env 파일에서 값 불러옴
    SERVER_HOST = config('SERVER_HOST')
    DOCKER_IMAGE = config('DOCKER_IMAGE')
    DOCKER_NAME = config('DOCKER_NAME')
    AWS_ECR_REGION = config('AWS_ECR_REGION')
    AWS_ECR_USER = config('AWS_ECR_USER')
    AWS_ECR_URI = config('AWS_ECR_URI')
    
    # Docker 실행시 줄 옵션들
    DOCKER_OPTIONS = [
        ('--rm', ''),  			# 컨테이너 종료시 파일 시스템 제거
        ('-d', ''),  			# 데몬 실행, 데몬 종료시 컨테이너 제거
        ('-it', ''),  			# tty 할당
        ('-p', '80:80'),  		        # 컴퓨터 포트:컨테이너 포트
        ('--name', 'velog'),  		# 도커 컨테이너 이름 지정
    ]
    
    
    # 로컬에서 실행
    def run(cmd, ignore_error=False):
        process = subprocess.run(cmd, shell=True)  # args로 설명된 명령 실행
    
        if not ignore_error:
            process.check_returncode()
    
    
    # ssh 이용해 서버에서 실행
    def ssh_run(cmd, ignore_error=False):
        run(f'ssh -o StrictHostKeyChecking=no -i {IDENTITY_FILE} {SERVER_NAME}@{SERVER_HOST} -C {cmd}',
            ignore_error=ignore_error)
    
    
    # Docker 이미지 생성 및 푸쉬
    def local_build_push():
        run(f'poetry export -f requirements.txt > requirements.txt')  	# poetry 라이브러리들을 서버에서 pip로 설치하기 위한 파일 생성
        run(
            f'aws ecr get-login-password --region {AWS_ECR_REGION} '  	# AWS ECR을 통해 Docker 로그인
            f'| docker login --username {AWS_ECR_USER} --password-stdin {AWS_ECR_URI}'
        )
        run(f'docker build -t {DOCKER_IMAGE} .')  				# Docker 이미지 생성
        run(f'docker tag {DOCKER_IMAGE} {AWS_ECR_URI}')  			# Docker 이미지 태그 생성
        run(f'docker push {AWS_ECR_URI}')  					# Docker 이미지 태그에 푸쉬
    
    
    # Docker 이미지 풀 및 컨테이너 실행
    def server_pull_run():
        ssh_run(
            f'aws ecr get-login-password --region {AWS_ECR_REGION} '
            f'| docker login --username {AWS_ECR_USER} --password-stdin {AWS_ECR_URI}'
        )
        ssh_run(f'sudo docker stop {DOCKER_NAME}', ignore_error=True)  	# 기존 Docker 이미지 중지 (원래 없을 경우 에러 무시)
        ssh_run(f'sudo docker pull {AWS_ECR_URI}')  			# Docker 이미지 풀
        ssh_run('sudo docker run {options} {tag}'.format(  			# Docker 컨테이너 실행
            options=' '.join(
                f'{key} {value}' for key, value in DOCKER_OPTIONS
            ),
            tag=AWS_ECR_URI,
        ))
    
    
    # .env파일(.dockerignore에 포함) 따로 복사
    def copy_env():
        run(f'scp .env {SERVER_NAME}@{SERVER_HOST}:/tmp', ignore_error=True)  	# 프로젝트 .env파일 서버에 복사
        ssh_run(f'sudo docker cp /tmp/.env {DOCKER_NAME}:/srv/{DOCKER_NAME}')  	# 서버에서 Docker 컨테이너로 .env파일 복사
    
    
    # Docker 컨테이너에 들어가 runserver 실행
    def server_exec():
        ssh_run(  # Docker 컨테이너 내에서 Django 프로젝트 실행
            f'sudo docker exec -d {DOCKER_NAME} python manage.py runserver --settings=config.settings.prod 0.0.0.0:80'
        )
    
    
    if __name__ == '__main__':
        try:
            print('---- 배포 시작!! ----')
            local_build_push()
            server_pull_run()
            copy_env()
            server_exec()
            print('---- 배포 완료!! ----')
        except subprocess.CalledProcessError as e:
            print('---- 배포 실패!! ----')
            print('cmd >> ', e.cmd)
            print('returncode >> ', e.returncode)
            print('output >> ', e.output)
            print('stdout >> ', e.stdout)
            print('stderr >> ', e.stderr)
  2. deploy.py 실행 권한 추가

    # velog/
    chmod +x deploy.py
  3. velog/.env 파일에서 필요한 값 추가

    # ~/.env
    # ...
    SERVER_NAME=hg
    SERVER_HOST=61.72.40.137
    DOCKER_IMAGE=raccoonhj33/velog
    DOCKER_NAME=velog
    AWS_ECR_REGION=ap-northeast-2
    AWS_ECR_USER=AWS
    AWS_ECR_URI=<repositoryUri>
    • 호스트 ip(SERVER_HOST) 경우, 사용하는 공유기에 따라 이전 포스트와 다를 수 있습니다!
  4. 파일 실행 확인

    # velog/
    ./deploy.py
    
    # ---- 배포 시작!! ----
    # WARNING! Your password will be stored unencrypted in /home/hyojin/.docker/config.json.
    # Configure a credential helper to remove this warning. See
    # https://docs.docker.com/engine/reference/commandline/login/#credentials-store
    # 
    # Login Succeeded
    # Sending build context to Docker daemon  56.32kB
    # Step 1/8 : FROM        python:3-slim
    #  ---> ce689abb4f0d
    # Step 2/8 : RUN         apt -y -qq update & apt -y -qq dist-upgrade && apt -y -qq autoremove
    #  ---> Using cache
    #  ---> 540ab9a5b905
    # Step 3/8 : RUN         pip install --upgrade pip
    #  ---> Using cache
    #  ---> 79b39330431b
    # Step 4/8 : COPY        ./requirements.txt /tmp/
    #  ---> Using cache
    #  ---> 122384ba9ec4
    # Step 5/8 : RUN         pip install -r /tmp/requirements.txt
    #  ---> Using cache
    #  ---> a0a7d91122a5
    # Step 6/8 : COPY        . /srv/velog
    #  ---> Using cache
    #  ---> 518b5c224729
    # Step 7/8 : WORKDIR     /srv/velog
    #  ---> Using cache
    #  ---> e99ff2adb47c
    # Step 8/8 : CMD         /bin/bash
    #  ---> Using cache
    #  ---> 5eb1640aa0a9
    # Successfully built 5eb1640aa0a9
    # Successfully tagged raccoonhj33/velog:latest
    # Using default tag: latest
    # The push refers to repository [****************.dkr.ecr.ap-northeast-2.amazonaws.com/velog]
    # 53976ff8ef86: Layer already exists 
    # 5a87dc8aa4f6: Layer already exists 
    # 9cd3b3af222a: Layer already exists 
    # c129e97d95e7: Layer already exists 
    # 9f819dd1bdc7: Layer already exists 
    # fe796314f3f4: Layer already exists 
    # a642096e6e01: Layer already exists 
    # b327e713d8e9: Layer already exists 
    # c38160dfb10e: Layer already exists 
    # 9eb82f04c782: Layer already exists 
    # latest: digest: sha256:bc851c3a23b76090f835739657588b80b2071cf4f963610dc6c29210a8ff7226 size: 2417
    # 로컬에서 도커 build & push 완료
    # WARNING! Your password will be stored unencrypted in /home/hyojin/.docker/config.json.
    # Configure a credential helper to remove this warning. See
    # https://docs.docker.com/engine/reference/commandline/login/#credentials-store
    # 
    # Login Succeeded
    # velog
    # Using default tag: latest
    # latest: Pulling from velog
    # Digest: sha256:bc851c3a23b76090f835739657588b80b2071cf4f963610dc6c29210a8ff7226
    # Status: Image is up to date for ****************.dkr.ecr.ap-northeast-2.amazonaws.com/velog:latest
    # ****************.dkr.ecr.ap-northeast-2.amazonaws.com/velog:latest
    # 76f682c41fd66f62347baab3c3f9fa425b8dbe6c500fa07b93fc0f2109e21481
    # 서버에서 도커 pull & run 완료
    # .env                                                                           100%  449    57.5KB/s   00:00    
    # .env 파일 복사 완료
    # 서버에서 도커 exec 완료
    # ---- 배포 완료!! ----
  5. ip 접속 확인

! 하면서 알게 된 사실

  • 서버 주소는 외부 ip(61.72.40.137)를 써야 하지만, DB 호스트 주소는 내부 ip(192.168.0.4)로도 연결 가능!
  • 공유기마다 접속할 서버 ip는 바뀌는데 DB가 있는 서버 ip는 바꾸지 않아도 배포 성공!
profile
파이썬 웹 백엔드 개발자
post-custom-banner

0개의 댓글