
졸업 작품으로 장고를 이용한 치매 예방 어플리케이션을 만드는 도중
나는 그래프 데이터 베이스인 neo4j 의 기능 구현을 맡아서 개발을 진행하고 있었다.
기능구현이 끝나고 develop 브랜치로 머지를 했더니 pull 을 받은 팀원이 장고가 제대로 실행되지 않았다.
이유는 내 로컬에 있던 neo4j 와 연동되던 기능들이 팀원 환경에서는 데이터베이스가 존재 하지않아 문제가 발행한 것이었다.
도커를 이용한 개발환경 통일을 한다는 것은 이미 알고 있었지만 이렇게 직접 개발환경 통일이 필요한 적은 처음이라 이렇게 블로그를 작성하게 되었다.
일단 장고에서 사용중인 데이터베이스는 두가지이다.
위 두가지 데이터 베이스와 장고 어플리케이션이 실행되어야 하니 여러개의 컨테이너를 실행시켜주는 도커 컴포즈를 이용하게 되었다.
아래는 docker-compose.yml 의 파일이다. (프로젝트 이름이 DP임)
version: '3'
services:
django:
build:
context: .
dockerfile: Dockerfile
container_name: dp
networks:
- dp
restart:
on-failure
depends_on:
- mysql
- neo4j
neo4j:
container_name: neo4j
image: neo4j:latest
networks:
- dp
mysql:
container_name: mysql
image: mysql
networks:
- dp
command:
- --character-set-server=utf8
- --collation-server=utf8_general_ci
networks:
dp:
driver: bridge
특이 사항으로는
network를 지정해 같은 네트워크 상에서 도커 컨테이너 이름으로 통신이 가능하게 해줬다는 점이다.
이제 위 docker-compose 파일을 상속받으며 추가 설정을 정의한 docker-compose-dev.yml 을 보자
services:
django:
volumes:
- .:/app
ports:
- "8000:8000"
environment:
- NEO4j_PASSWORD=neo4j1234
- MYSQL_DATABASE=dp
- MYSQL_HOST=mysql
- MYSQL_PASSWORD=1234
- JWT_SECRET=secret
env_file:
- .env-s3
command:
- /bin/bash
- -c
- |
python3 manage.py makemigrations
python3 manage.py migrate
python3 manage.py runserver 0.0.0.0:8000
neo4j:
ports:
- "7474:7474"
- "7473:7473"
- "7687:7687"
volumes:
- ./neo4j-volume/data:/data
- ./neo4j-volume/logs:/logs
environment:
NEO4J_AUTH: neo4j/neo4j1234
mysql:
volumes:
- ./mysql-volume/mysql:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=1234
- MYSQL_DATABASE=dp
ports:
- "3306:3306"
특이사항으로는
각 데이터 베이스의 도커 볼륨을 프로젝트안 폴더들로 잡아줬다는 것과
개발단계에서만 사용되는 비밀 변수들을 환경변수로 직접 넣어줬다는 것이다.
위 docker-compose.yml 을 상속받으며 docker-compose-dev.yml 파일 설정을 추가한 도커 컴포즈 파일을 실행하는 명령어는 아래와 같다.
docker-compose -f docker-compose.yml -f docker-compose-dev.yml up -d —build
만약 docker-compose 에도 있고 docker-compose-dev.yml 에도 있는 설정이라면
위 명령어에서 뒤에있는 설정파일이 설정을 덮어쓴다.
위 명령어에선 docker-compose.yml 의 설정을 docker-compose-dev.yml 이 덮어쓰는 것이다.
위 장고 컨테이너에서는 mysql, neo4j 에 의존성을 두고 restart-on-failure로 재실행을 하고 있지만
mysql, neo4j가 아직 서버가 돌지 않을때 마다 재시작을 할것이다.
위 문제점을 해결하고자 도커 네트워크 안에서 mysql 과 neo4j를 기다리는 명령어를 만들어보았다.
wait-for-services.sh
#!/bin/bash
# Wait for MySQL
while ! nc -z mysql 3306; do
sleep 0.5
done
# Wait for Neo4j
while ! nc -z neo4j 7687; do
sleep 0.5
done
# Now execute the main command
exec "$@"
위 명령어파일을 이용해 mysql, neo4j를 기다리며 명령어를 수행가능하게 장고의 커맨드 라인을 바꾸어 보았다.
command:
- /bin/bash
- -c
- |
./wait-for-services.sh python3 manage.py makemigrations
python3 manage.py migrate
python3 manage.py runserver 0.0.0.0:8000
위 wait-for-services.sh 파일을 mac에서 만들고 그대로 github에 올려 window를 사용하는 팀원에게 도커 컴포즈를 실행해 보라고 해보았다.
그랬더니 Window의 도커 빌드에서 에러를 내뿜었다…
(에러 사진은 없지만 대충 LF 등.. 문자들이 보였었음)
github의 개행문자 정책이었다.github에서는 mac에서 pull 을 받으면 유닉스의 개행문자 타입으로 pull 받고 window에서 pull을 받으면 window의 개행문자 타입으로 pull 받는다.
mac에서는 개행문자가 LF 뿐이지만
window는 CRLF 이기 때문에
리눅스 환경인 도커 컨테이너에서 CRLF으로 작성된 명령어 파일을 실행 시켰기 때문에 오류가 났던것이다.
window환경에서도 실행이 가능하게 바꾸어야 했다.
문제를 해결하기 위해
CRLF의 문자를 LF로 바꾸어주는 dos2unix 소프트웨어를 찾았다.
장고컨테이너에 dos2unix 를 깔아 주었고
RUN apt-get install dos2unix -y
명령어를 실행하기전 wait-for-services.sh 파일을 LF로 변환하는 명령을 수행해 주었다.
command:
- /bin/bash
- -c
- |
dos2unix /app/wait-for-services.sh
./wait-for-services.sh python3 manage.py makemigrations
python3 manage.py migrate
python3 manage.py runserver 0.0.0.0:8000
위 코드로 window와 mac간 개발환경 통일이 가능하게 되었다!