과제를 수행하면서 다음과 같은 조건이 있었다.
[DB 설정]
1. 내장형 DB사용
2. Docker사용 : DB종류 제한 X
내장형 DB의 경우 sqllite를 사용하면 될것 같지만 요새 Docker에 대해 조금 알아보기도 했고, 마침 docker-compose까지 구현해보고 싶었기에 2번의 방법을 사용하기로 하였다. 지옥의 시작
그리고 글을 정리하면서 도움을 받았던 글! : sayxoung님의 블로그
Docker compose란 여러 개의 docker를 정의하고 실행하는 툴을 의미한다. 내가 하려는 것도 docker를 이용해서 API image와 DB image를 하나의 container로 실행하려고 하는 것이다.
이전에 프로젝트 JELLOgram
으로 했던 것은 API를 image로 빌드하여 DB를 제외한 나머지를 모두 도커로 실행하도록 한것이다. 빌드된 이미지를 실행하게 되면 그 안에 저장된 내 로컬DB에 대한 것도 함께 연결되는것이었다.
즉, API = 도커
/ DB = local DB
의 형태였다.
하지만 과제나 배포와 같은 상황에서 API만 도커로 실행하는것은 의미가 없다. (연결된 DB는 작성자의 로컬 디비인데..? 아니면 RDS로?)
RDS 는?
RDS를 사용해 DB를 관리할 수도 있다. 하지만 배포를 할땐 DB에 접속할 비밀번호를 공유해야 한다. 내 비밀번호를 깃헙에 올린순 없다..
따라서 DB도 이미지로 빌드! 그리고 API 이미지랑 같이 실행!하는 방법이 Docker compose인 것이다.
먼저 docker-compose의 설치가 필요하다. 나같은 경우 지난번 Docker를 설치할때 함께 설치해주었었다.
🔥 너무 옛날 버전이면 이후 제대로 실행되지 않는다! 주기적으로 업데이트를 진행해 줄 것!
pip install docker-compose
그리고 나서 API를 위한 Dockerfile
과 docker-compose를 위한 docker-compose.yml
파일을 만들어 준다.
이의 경우 지난번 블로깅을 통해 기록해 놓았다. 이중에서 다른 점은 gunicorn으로 실행하지 않는 것 runserver의 조건은 Dockerfile이 아닌 이후에 작성할 docker-compose.yml에 작성한다.
확장자명 .yml
을 주의하자!
(참고로 yml 파일을 vscode로 열어보면 귀여운 핑크고래가 보인다 ㅎㅎ Dockerfile은 파란고래!)
한줄씩 살펴보자
build: context: . dockerfile: ./Dockerfile
: 적용될 Dockerfile의 위치와 이름command
: Docker이미지가 빌드되고 실행될때 수행될 명령어들이다. 저기에 있는 wait-for-it
에 관한것은 아래에서 다루도록 한다. / mm -> mg -> runserver 해주어서 이미지가 빌드되면 바로 서버가 가동된다.volumes
: 실행되는 위치를 의미한다. 이미지가 실행될때 해당 위치가 형성된다.ports
: 허용하는 포트정보depends_on
: 도커의 이미지들끼리는 서로 인지하지 못한다 때문에 app의 이미지 정보에 db와 관련이 있음을 명시해 주어야 한다. 이때 사용하는 것이 depends_on : db
이다.image
: mysql ver5.7로 이미지를 만든다.environment
: 생성된 mysql의 환경설정이다. 여기서 db의 이름 / db접속 비밀번호를 지정해 준다.command
: DB가 생성될때 실행되는 명령어들이다. 나의 경우 DB의 data들이 한국어이기 때문에 utf8mb4
설정을 진행해 준다.volumes
: DB가 생성될때 sql파일을 사용해 자동으로 data를 채워준다. 따라서 경로에 맞게 최상위 directory에 data
라는 폴더를 만들고 그 안에 sql
파일을 저장한다. (이름은 상관없다! 자동으로 sql파일을 사용해 data를 넣어준다)expose
: port 번호를 의미한다. 도커 내부에서만 실행할 것이기 때문에 ports 8000:8000
으로 작성한것과 차이는 딱히 없는것 같다.이 파일의 경우 작성된 코드들을 건들일 필요는 없다. 이미 잘 작성되어있기 때문에 공유하면 된다.
위에서 우리가 의도한 것은 docker-compose로 app과 db의 이미지를 함께실행하는 것이다. 하지만 app의 이미지가 실행될때 mm, mg를 수행한다. 알다싶이 이를 수행하기 위해선 DB가 먼저 준비되어 있어야 한다.
따라서 이미지가 실행될때 DB의 이미지가 먼저 실행된 후 app의 이미지가 실행되도록 app의 command에 wait-for-it
를 입력했던 것!
위의 파일들을 모두 작성한 후 requirements.txt
도 꼼꼼히 기록한다. => 놓치면 바로 에러난다.
그리고 나서 githup에 코드를 모두 올린 후 새로운 폴더에서 해당 프로젝트를 clone받아 온다.
git clone $프로젝트
cd $프로젝트_최상위_directory
docker-compose up
이거면 끝! 에러가 나지 않는 다면 서버가 가동될 것이고, 빠르게 httpie test로 데이터를 확인해 볼 수 있다!
이거저거 건드리다가 requirements를 제대로 작성하지 않았다. Django를 빼먹은 것. 어쩐지 Django를 실행할 수 없다고 뜨더라.. 잊지말자!
db image는 문제가 없었는데 app image가 제대로 빌드되지 않았다. 계속해서 script와 관련해 permission denied라고 뜨는것.
이를 해결하기 위해선 wait-for-it.sh
파일의 권한을 풀어주어야 하는데 처음에는 docker-compose.yml
의 command에 해당 명령어를 입력했었다.
# docker-compose.yml
command: >
bash -c ” RUN chmod +x ./wait-for-it.sh
&& ./wait-for-it.sh db:3306 -t 15
&& python manage.py makemigrations
&& python manage.py migrate
&& python manage.py runserver 0.0.0.0:8000"
그런데 이렇게 입력하고 나니 RUN 명령어를 인식하지 못한다고 뜬다!
그래서 해당 줄을 제거하고 일단 docker-compose를 실행하기 전 해당 환경에서 직접 권한을 풀어주었다.
# docker 실행할 환경
chmod +x ./ wait-for-it.sh
그리고 나서 실행!
굿!
수정!!!!! 2021.05.19
코드를 수정해서 다시 진행해 보았다.
# docker-compose.yml
command: >
bash -c ”chmod +x ./wait-for-it.sh
&& ./wait-for-it.sh db:3306 -t 15
&& python manage.py makemigrations
&& python manage.py migrate
&& python manage.py runserver 0.0.0.0:8000"
RUN
을 빼고 실행하니 docker가 실행되면서 다음과 같은 메세지가 출력되더라.
forum_1 | wait-for-it.sh: waiting 15 seconds for db:3306
...
#생략
...
forum_1 | wait-for-it.sh: db:3306 is available after 7 seconds
forum_1 | No changes detected
forum_1 | Operations to perform:
forum_1 | Apply all migrations: admin, auth, contenttypes, questions, sessions, users
forum_1 | Running migrations:
forum_1 | No migrations to apply.
forum_1 | Watching for file changes with StatReloader
실행 성공!
DB에 대한 정보를 settings.py 혹은 보안설정으로 my_settings.py 에 기록했던것을 기억하는가!
docker를 이용해 DB도 이미지로 빌드하게 되면 해당 프로젝트의 연결되는 DB는 내 로컬 / RDS 가 아닌 docker image실행으로 만들어진 이미지 속의 DB이다. 때문에 docker-compose파일에서 지정한 DB이름과 비밀번호로 settings.py도 수정한다. 또한 SECRET_KEY의 경우에도 실무에서는 회사 내에서만 공유하겠지만 일단 나는 배포 / 과제제출
용이기 때문에 공개하기로 한다! (임의의 string으로 지정했다.)
docker-compose가 무사히 실행된 화면 & httpie 확인 화면 & docker app으로 보는 container 상태
이후 docker를 종료하고 다시 실행해 보았다. 이때는 터미널에서 실행하려 하니 해당 container가 존재하지 않는다고 해서... 읭? docker app에서 실행해 주었다.
#안됌
❯ docker start labs_forum
Error response from daemon: No such container: labs_forum
Error: failed to start containers: labs_forum
통신 확인 완료!!
docker container로 실행된 db image를 확인해 보자
docker exec -t {db container이름} bash
mysql -u root -p
password > {docker-compose 작성할때 입력한 password 입력}
꼬박 하루가 걸린 docker-compose 였다! 처음 코드를 열어봤을때 진짜 무슨..말이고.. 했는데 하나하나 뜻을 보니 이 코드는 어디서, 왜 필요한지 이해하면서 점점 재밌어 졌다!
이제 DB도 도커로 관리!