TIL - 2021.1.31

Wanna be __·2021년 1월 31일
0

TIL

목록 보기
12/45
post-thumbnail

Today, I Did

오늘 해결한 딜레마
Docker의 Multicontainer 구조 (Django + Nginx + React)를 AWS Elastic Beanstalk를 이용하여 배포하는중에, 진퇴양난의 상황에 처하게 되었다.

내가 원하는 점: django의 image에 SECRET_KEY등의 환경 변수는 포함하지 않은 채 build하고, 이후 EB의 Dockerrun.aws.json에서 environment를 지정하고 나서 해당 env variables로 build한 backend server를 사용한다.

직면한 상황들:
0. Dockerhub의 public repository를 사용하는 이상, 여러 secret key들을 이미지에 포함시켜 방치한다면, 문제가 발생할 소지가 다분하기 때문에, 이를 막아야함.
1. 원래 하던대로, Django image를 만들 때 env variable 없이 migration, collectstatic, gunicorn --bind 등을 실행하는 endpoint를 실행 -> 해당 Image가 후에 Dockerrun.aws.json 파일을 통하여 환경변수를 받게 되더라도, 이미 migration과 collectstatic은 정상적으로 이루어지지 않은 상태로 실행된다.
2. Dockerfile을 사용하여 Django Image를 build한 뒤, 해당 이미지에서 envionment variable을 unset 명령을 통하여 삭제하거나, [ENV_NAME]="" 등을 통하여 빈 값을 저장한다. -> 이 방법이 가장 이상적인 방법으로 보였으나, 실제 이미지를 빌드한 뒤 거기서 env vars 를 제거하는 일은 불가능 하다고 하였다.
3. 1에서 만든 Image를 push하지 않고, 해당 image를 Dockerrun 파일에서 불러와서 지우고자하는 env vars를 unset하거나 빈 값을 저장한다 -> 불가능
4. EB의 .ebextensions의 .config 설정을 통하여, 배포 이후, migration명령어를 다시 실행한다 -> .sh 파일을 작성하고 실행시켜야하는데, 여러 reference들이 #! usr/bin/env bash와 같이 bash 경로를 실행위치로 지정하고 있었는데, 확인결과 django image의 env에는 bash 경로가 따로 지정되어 있지 않았다 -> #! /bin/sh 로 변경
5. container_id=`sudo docker ps -f name="backend" --no-trunc -aq | head -n 1` 과 같은 방법으로 shell script를 통하여 containerid를 얻었고, 이 image의 entrypoint.sh를 재실행 하고자 함 -> 최초 build할 당시 gunicorn --bind 0.0.0.0:8000 명령어에 의해서, 8000 포트는 사용중이였는데, entrypoint를 재실행하면 이미 사용중인 포트를 재사용하고자 하는 문제가 생김 -> 작동은 하는데 error없이 진행된것은 아니므로 eb status를 찍었을때 상태는 RED로 뜸
6. 최초 entrypoint에 gunicorn 명령어를 넣지 않고서, deploy가 끝난 뒤에, entrypoint shell script를 재실행하고, gunicorn명령어를 추가하는 방법 -> gunicorn이 실행되지 않았기 때문에, 해당 이미지는 migrate까지 한 뒤 즉시 exit되어버렸고, 5번의 명령어를 통하여 container_id를 얻었다고 한들, exec 명령어 등으로 이를 실행시킬 수가 없음(exec은 이미 실행중인 container에 할 수 있음)
7. Dockerrun.aws.json의 backend container에 사용한 이미지를 그냥 shell script를 통하여 실행 -> EB가 multicontainer환경을 만들 때 3가지 container를 만들었는데, 새롭게 docker run ~~ 을 통하여 container를 추가하는 셈이 되어 오류 발생
8. exec이 안된다면, exit 된 container를 container_id를 통하여 재시작 하는 방법 -> 재시작(run)할 container를 container_id로 지정하는 것이 불가능 하기 때문에 이는 불가능
9. 다시 entrypoint.sh에 gunicorn 명령어를 추가하고, deploy가 끝나고나서, 우선 동작하고 있는 gunicorn을 종료시킨뒤 (pskill gunicorn) entrypoint.sh 재시작 -> gunicorn 프로세스를 종료하는 순간 해당 container는 종료되고, 그러므로 8번과 같이 exit 된 컨테이너를 id로 살리는일 불가능..
10. gunicorn 명령어를 그대로 두고, pskill로 gunicorn을 종료시키는것이 아니라, container 자체를 restart 함 ->
성공_

사실 dockerhub의 private repository를 이용하나 AWS의 ECS에 환경변수가 포함된 IMAGE를 upload혹은 새로운 EC2에 Docker Image 서버를 만들어 public하게 해당 Image에 접근하는 방법을 차단하는 방법도 있겠지만, 어쩌다보니 배포를 하기위해 shell script 명령어를 찾아보게 되었다.

이러한 시도를 통하여 .ebextensions 내부의 config 파일 구성 및 elasticbeanstalk이 배포를 준비하는 단계, 실행 파일 순서 등에 대한 공부를 많이 하게 되었다.

profile
성장하는 개발자

0개의 댓글