💻 VM 환경 : Ubuntu 18.04.5 LTS (버전 확인하기 : cat /etc/issue
)
윈도우나 맥은 도커 데스크탑을 설치하면 되니까 간편한데, 우분투에서는 패키지 매니저를 통해 도커 엔진을 설치해줘야 한다. 도커 엔진을 설치하기 위해서는 도커 레포지토리 세팅부터 해야 한다.
1) 의존 패키지 설치하기
sudo apt update
sudo apt install \
apt-transport-https \
ca-certificates \
curl \
gnupg \
lsb-release
2) 도커 공식 레포지토리 설치를 위한 GPG key 추가하기
GPG key는 두 주체 사이의 안전한 통신을 보장해주는 거라고 설명이 나와있는데, 설치를 안전하게 하기 위해 추가된 단계인 것 같다.
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
3) 도커 레포지토리 설치하기
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable"
4) 우분투 디폴트 레포지토리 말고 도커 레포지토리에서 설치하도록 설정하기
sudo apt update
apt-cache policy docker-ce
아래처럼 뜨는지 확인한다.
docker-ce:
Installed: (none)
Candidate: 18.03.1~ce~3-0~ubuntu
Version table:
18.03.1~ce~3-0~ubuntu 500
500 https://download.docker.com/linux/ubuntu bionic/stable amd64 Packages
Installed가 none으로 뜨는 것은 아직 docker-ce를 설치하기 않았기 때문이다.
5) 도커 엔진 설치하기
sudo apt install docker-ce
6) 도커 실행 확인하기
sudo systemctl status docker
1) 도커 컴포즈 설치하기
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
2) 도커 컴포즈가 설치된 경로에 실행 권한 주기
sudo chmod +x /usr/local/bin/docker-compose
3) 도커 및 도커 컴포즈 설치 확인하기
docker version
docker-compose version
각각 개발용, 배포용으로 분리했다.
Dockerfile.dev & Dockerfile.prod
docker-compose.dev.yml & docker-compose.prod.yml
1) requirements.txt에 Gunicorn 추가하기
gunicorn==20.0.4
2) djangoapp 컨테이너의 command를 gunicorn 명령어로 수정하기
# docker-compose.prod.yml
# gunicorn project_name.wsgi:app_name --bind 0.0.0.0:8000
command: gunicorn closet.wsgi:application --bind 0.0.0.0:8000
배포용 도커 파일의 경우 개발용과 크게 달라진 부분은 없는데, 유저를 생성해서 권한을 제한하는 게 아무래도 좋을 것 같다. 그래서 우선은 개발용과 배포용을 분리해놓았고, 유저 관련 부분을 차후 추가할 예정이다. 우선은 건너뛰었다.
배포용 컴포즈 파일의 경우 build context를 Dockerfile.prod로 명시해주고, 개발용이 아니기 때문에 volume 부분이 필요없으므로 지워준다.
service:
djangoapp:
build:
context: .
dockerfile: Dockerfile.prod
command: gunicorn closet.wsgi:application --bind 0.0.0.0:8000
ports:
- "8000:8000"
depends_on:
- db
배포용 컴포즈 파일에 Nginx 컨테이너를 다음과 같이 추가해준다.
nginx:
build: ./nginx
ports:
- "80:80"
depends_on:
- djangoapp
다음의 구조로 Nginx용 도커 파일과 Nginx 설정 파일을 추가해준다.
└── nginx
├── Dockerfile
└── nginx.conf
Nginx Dockerfile
FROM nginx:1.19.0-alpine
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d
Nginx 환경설정 파일
upstream <backend> {
server djangoapp:8000;
}
server {
listen 80;
location / {
proxy_pass http://<backend>/;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
}
도커 컨테이너끼리만 내부적으로 포트를 열어주면 되므로 ports → expose로 바꾼다.
service:
djangoapp:
build:
context: .
dockerfile: Dockerfile.prod
command: gunicorn closet.wsgi:application --bind 0.0.0.0:8000
expose:
- "8000"
depends_on:
- db
컨테이너 실행시키기
docker-compose -f docker-compose.prod.yml up --build -d
DB migrate하기
docker exec backend_djangoapp_1 python manage.py migrate
로그 확인하기
docker logs backend_djangoapp_1
80번이 열려있으므로 그냥 DNS로 접속해보면 장고 서버 페이지가 뜨면 된다. 그런데 /admin/으로 접속해보니 CSS가 깨져있었다. 원인을 찾아보니 static file 관련 작업을 안해줘서 그런 것이었다.
STATIC_URL = "/static/"
STATIC_ROOT = os.path.join(BASE_DIR, "static")
djangoapp과 nginx가 동일한 static volume(/backend/static) 디렉토리를 공유하도록 설정
djangoapp:
volumes:
- static_volume:/backend/static
nginx:
volumes:
- static_volume:/backend/static
docker compose는 volume file을 마운트할 때 root user로 작업하는데, root user로 작업하면 상관없지만 non-root user로 접근하면 /static이라는 디렉토리를 만들 때 존재하지 않는 디렉토리를 만들려고 하면 permission denied가 뜰 수 있기 때문에 관련 코드 한 줄을 추가해준다.
ENV APP_HOME=/backend
RUN mkdir $APP_HOME
RUN mkdir $APP_HOME/static
WORKDIR $APP_HOME
upstream <backend> {
server djangoapp:8000;
}
server {
listen 80;
location / {
proxy_pass http://<backend>/;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
location /static/ {
alias /backend/static/; <- static file 경로
}
}
docker exec backend_django_1 python manage.py collectstatic --no-input --clear
collectstatic
은 static root 디렉토리에 static file을 복사하는 명령어이다.
clear 옵션은 static root 경로에 이미 static file이 존재하는 경우 싹 다 지우고 다시 복사하는 옵션이다. 앱이 삭제된다든지 하는 경우 쓸모없는 static file이 존재할 수도 있기 때문에 collectstatic
을 여러번 하게 되면 같이 붙여주면 좋다.
이제 다시 admin 페이지나 swagger, redoc 페이지로 접근하게 되면 css가 잘 적용되는 것을 확인할 수 있다!
https://testdriven.io/blog/dockerizing-django-with-postgres-gunicorn-and-nginx