1. Docker Secret 생성
이번 글은 간단하다! 기존에 .env 파일로 관리하였지만 방법을 몰라서 그대로 외부에 노출시켰던 django_SECRET 정보와 mariaDB_PASSWORD 정보 등을 Docker SECRET을 통해서 보안처리할 것이다. Docker Secret을 설정하면 Service 내에 있는 Secret 정보가 필요한 Container들에게 SECRET 정보를 제공할 수 있다. 일단 SECRET을 생성한다. Name값과 Secret 정보값을 넣어주자.
나머지 DB 관련 Secret 값들도 넣어주었다.
2. 설정 파일 수정
이제 Stack의 Service들이 상기 생성한 Secret 정보들을 바라볼 수 있도록 Stack의 설정파일인 docker-compose.yml 파일을 수정한다. 그리고 기타 image 관련 및 각 container의 secret 관련 참조 정보들을 변경한다.
Stack 설정파일 수정
docker-compose.yml 파일의 일부
django container와 mariadb container의 정보에 secrets 정보를 추가하였다.
django_container_gunicorn: #network로 묶이기 때문에 name-space 정보로 넣어줘야한다. django로 넣으면 안된다.
image: django_image_test:4
networks:
- network
volumes:
- static-volume:/home/inflearn_study_django_pinterest/staticfiles
- media-volume:/home/inflearn_study_django_pinterest/media
secrets:
- MYSQL_PASSWORD
- DJANGO_SECRET_KEY
mariadb:
image: mariadb:10.5
networks:
- network
volumes:
- maria-database:/var/lib/mysql
secrets:
- MYSQL_PASSWORD
- MYSQL_ROOT_PASSWORD
environment:
MYSQL_DATABASE: django
MYSQL_USER: django
MYSQL_PASSWORD: password1234
MYSQL_ROOT_PASSWORD: password1234
MariaDB 연결 정보
상기 stack의 설정 파일에서 이제 environment로 지정해줬던 값들은 제거하고 secrets 값을 바라보도록 해야한다. 이렇게 하기 위해서는 DockerHub:MariaDB 페이지에서 안내대로 '_FILE' 이라는 이름을 붙여주고 경로를 작성해주면 된다. 이것은 실제로 Secret 내용이 각 container에 각각 파일로 제공되기 때문이기도 하다.
#...중략
environment:
MYSQL_DATABASE: django
MYSQL_USER: django
#MYSQL_PASSWORD: password1234
#MYSQL_ROOT_PASSWORD: password1234
MYSQL_PASSWORD_FILE: /run/secrets/MYSQL_PASSWORD
MYSQL_ROOT_PASSWORD_FILE: /run/secrets/MYSQL_ROOT_PASSWORD
#추가
secrets:
DJANGO_SECRET_KEY:
external: true
MYSQL_PASSWORD:
external: true
MYSQL_ROOT_PASSWORD:
external: true
기타 참조 사항 변경
소스코드의 일부를 변경해줘야한다. 우선 docker-compose.yml의 django image를 5번 버전으로 바꿔놓는다.
django_container_gunicorn:
image: django_image_test:5
settings/deploy.py에서 SECRET_KEY의 참조를 변경해준다. file을 다루기 위해서 새로운 함수를 정의하고 적용한다.
settings/deploy.py
def read_secret(secret_name):
file = open('/run/secrets/' + secret_name)
secret = file.read()
secret = secret.rstrip().lstrip()
file.close()
return secret
# 중략...
# SECURITY WARNING: keep the secret key used in production secret!
# SECRET_KEY = env('SECRET_KEY')
SECRET_KEY = read_secret('DJANGO_SECRET_KEY')
'DJANGO_SECRET_KEY는 docker-compose.yml에 정의해두었고, 'run/secrets/'라는 디렉토리 위치는 dockerhub의 mariaDB에서 secrets를 설명하는 부분에서 볼 수 있다(위 캡쳐 사진 참고). 물론 여기서 다루는 secret key는 django와 관련된 key이나, 아마도 django도 docker의 secrets를 활용하기 위해서는 해당 디렉토리 위치에 key값을 넣어두면 인식한다는 것으로 이해된다. 참고로 rstrip(), lstrip()은 좌우 빈 공백 부분을 제거해주는 메서드이다.
이제 변경된 사항을 image로 반영하기 위해서 git을 push 하고, image를 다시 생성한다. docker에서 인식이 필요하므로 Dockerfile에서 의미없는 주석 부분을 약간 변경한다.
# RUN echo "testing"
RUN echo "testing1234"
그리고 secret key를 다른 곳에서 참조하는 방식이라 곧바로 컨테이너가 구동되지 않을 수 있다. 따라서 Dockerfile의 내용 중 django 내부에서 처리하던 아래 명령어를 CMD 부분으로 뒤로 미루도록 한다. (echo yes 대신 --noinput 옵션을 주었다.)
RUN echo yes | python manage.py collectstatic
CMD ["bash", "-c", "python manage.py collectstatic --noinput && python manage.py migrate --settings=pragmatic.settings.deploy && gunicorn pragmatic.wsgi --env DJANGO_SETTINGS_MODULE=pragmatic.settings.deploy --bind 0.0.0.0:8000"]
3. 이미지 생성 및 스택 적용
이미지 생성
stack 재생성 : docker-compose.yml 파일에 django_image_test:5 정보가 들어있음
정상작동 확인
참조
1. 작정하고 장고! Django로 Pinterest 따라만들기 : 바닥부터 배포까지-박형석님 인프런 강의