Docker 배포 정리
Django 프로젝트 Docker 배포 정리
1. 서버 접속하기
로컬 PC에서 서버에 SSH로 접속한다.
1
ssh 사용자id@접속IP
ex)
1
ssh ubuntu@123.123.123.123
접속하면 서버 안에서 프로젝트 폴더를 만들거나, 기존 프로젝트 폴더로 이동해서 작업하면 된다.
2. 현재 서버에서 실행 중인 포트 확인하기
서버에서 이미 사용 중인 포트를 확인한다.
1
netstat -ntlp
이 명령어를 실행하면 현재 실행 중인 포트번호를 확인할 수 있다.
예를 들어 7000번 포트를 사용할 예정인데 이미 다른 프로그램이 사용 중이라면
Docker 실행 시 다른 포트를 사용해야 한다.
1
docker run -d -p 7001:8000 --env-file .env --name 컨테이너명 이미지명
3. 프로젝트 폴더 구조 확인하기
Django 프로젝트는 보통 아래와 같은 구조가 되어야 한다.
1
2
3
4
5
6
7
8
9
project/
├── chat/
├── config/
├── source/
├── .env
├── Dockerfile
├── main.py
├── manage.py
└── requirements.txt
중요한 점은 Dockerfile, manage.py, requirements.txt, .env 파일이 같은 프로젝트 폴더 안에 있어야 한다는 것이다.
예를 들어 project 폴더 안에 manage.py가 있다면
반드시 project 폴더 안에서 Docker 이미지를 빌드해야 한다.
4. requirements.txt 작성하기
Dockerfile에서 아래 명령어로 패키지를 설치하기 때문에 requirements.txt 파일이 필요하다.
1
RUN pip install --no-cache-dir -r requirements.txt
pyproject.toml을 사용하는 프로젝트라면
pyproject.toml의 dependencies 항목을 보고 requirements.txt에 작성하면 된다.
5. Dockerfile 만들기
프로젝트 폴더 안에 Dockerfile 파일을 만든다.
1
Dockerfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
FROM python:3.11-slim
# 컨테이너 내 작업 디렉토리 설정
WORKDIR /app
# requirements.txt 복사 후 패키지 설치
COPY requirements.txt /app/
RUN pip install --no-cache-dir -r requirements.txt
# 프로젝트 전체 파일 복사
COPY . /app/
# Django 개발 서버 실행
# 컨테이너 내부에서는 8000번 포트로 실행
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
이 Dockerfile의 의미는 다음과 같다.
1
FROM python:3.11-slim
Python 3.11이 설치된 가벼운 Linux 이미지를 기반으로 사용한다.
1
WORKDIR /app
컨테이너 내부의 작업 위치를 /app으로 설정한다.
1
2
COPY requirements.txt /app/
RUN pip install --no-cache-dir -r requirements.txt
requirements.txt를 컨테이너 안으로 복사한 뒤 필요한 Python 패키지를 설치한다.
1
COPY . /app/
현재 프로젝트 폴더의 모든 파일을 컨테이너 내부 /app으로 복사한다.
1
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
컨테이너가 실행되면 Django 서버를 실행한다.
6. settings.py 수정하기
Django는 기본적으로 허용된 호스트에서만 접속할 수 있다.
따라서 서버 IP를 ALLOWED_HOSTS에 추가해야 한다.
1
2
3
# config/settings.py
ALLOWED_HOSTS = ['서버접속IP', 'localhost', '127.0.0.1']
1
ALLOWED_HOSTS = ['123.123.123.123', 'localhost', '127.0.0.1']
만약 이 설정을 하지 않으면 브라우저에서 접속했을 때 DisallowedHost 오류가 발생할 수 있다.
7. Docker 이미지 빌드하기
Docker 이미지는 프로젝트 폴더 안에서 빌드해야 한다.
1
docker build -t 이미지명 .
ex)
1
docker build -t docker-image .
또는 프로젝트 이름을 넣어서 작성할 수 있다.
1
docker build -t overwatch-image .
여기서 마지막의 .은 현재 폴더를 기준으로 Docker 이미지를 만들겠다는 의미이다.
따라서 반드시 Dockerfile, manage.py, requirements.txt가 있는 폴더에서 실행해야 한다.
8. Docker 컨테이너 실행하기
이미지를 빌드했다면 컨테이너를 실행한다.
1
docker run -d -p 7000:8000 --env-file .env 이미지명
1
docker run -d -p 7000:8000 --env-file .env docker-image
컨테이너 이름까지 지정해서 실행하는 방식:
1
docker run -d -p 7000:8000 --env-file .env --name 컨테이너명 이미지명
1
docker run -d -p 7000:8000 --env-file .env --name docker-container docker-image
포트 의미 :
1
-p 7000:8000
왼쪽 7000은 서버 외부에서 접속할 포트이고 오른쪽 8000은 컨테이너 내부 Django 서버 포트이다.
즉, 브라우저에서는 아래처럼 접속한다.
1
http://서버접속IP:7000
ex)
1
http://123.123.123.123:7000
9. 실행 중인 Docker 컨테이너 확인하기
컨테이너가 정상적으로 실행 중인지 확인한다.
1
docker ps
실행 중이라면 컨테이너 목록에 방금 실행한 컨테이너가 보여야 한다.
만약 아무것도 나오지 않는다면 컨테이너가 실행되었다가 바로 꺼졌을 가능성이 있다.
이 경우 꺼진 컨테이너까지 전부 확인한다.
1
docker ps -a
10. Docker 로그 확인하기
컨테이너가 왜 꺼졌는지 확인하려면 로그를 확인한다.
1
docker logs 컨테이너명
ex)
1
docker logs docker-container
또는 컨테이너 ID로 확인할 수도 있다.
1
docker logs 컨테이너ID
오류가 발생했을 때는 거의 항상 docker logs에서 원인을 확인할 수 있다.
11. 오류 1: manage.py 파일을 찾을 수 없는 경우
Docker 실행 후 아래와 같은 오류가 나올 수 있다.
1
python: can't open file '/app/manage.py': [Errno 2] No such file or directory
이 오류는 컨테이너 내부의 /app 위치에 manage.py가 없다는 뜻이다.
대부분의 원인은 프로젝트 폴더가 아닌 홈 디렉토리에서 Docker 이미지를 빌드했기 때문이다.
현재 위치 확인:
1
pwd
ex)
1
/home/ubuntu
만약 현재 위치가 홈 디렉토리라면 프로젝트 폴더로 이동해야 한다.
ex)
1
cd project
그다음 다시 빌드한다.
1
docker build -t 이미지명 .
ex)
1
docker build -t docker-image .
정리하면, 아래 파일들이 있는 위치에서 빌드해야 한다.
1
2
3
4
Dockerfile
manage.py
requirements.txt
.env
12. 오류 확인 기본 순서
오류가 발생하면 아래 순서로 확인한다.
1단계: 실행 중인 컨테이너 확인
1
docker ps
2단계: 꺼진 컨테이너까지 확인
1
docker ps -a
3단계: 로그 확인
1
docker logs 컨테이너명
ex)
1
docker logs docker-container
4단계: 현재 폴더 위치 확인
1
pwd
5단계: 프로젝트 파일 확인
1
ls
Dockerfile, manage.py, requirements.txt, .env가 있는지 확인한다.
13. 수정 후 다시 빌드하기
코드를 수정한 뒤 다시 Docker 이미지에 반영하려면 기존 컨테이너를 삭제하고 이미지를 다시 빌드해야 한다.
1
2
3
4
5
6
7
8
# 기존 컨테이너 삭제
docker rm 컨테이너명
# 다시 빌드
docker build -t 이미지명 .
# 다시 실행
docker run -d -p 7000:8000 --env-file .env --name 컨테이너명 이미지명
ex)
1
2
3
docker rm docker-container
docker build -t docker-image .
docker run -d -p 7000:8000 --env-file .env --name docker-container docker-image
14. 오류 2: 실행 중인 컨테이너는 삭제할 수 없는 경우
컨테이너를 삭제하려고 했을 때 아래와 같은 오류가 나올 수 있다.
1
cannot remove container : container is running: stop the container before removing or force remove
이 오류는 컨테이너가 아직 실행 중이기 때문에 바로 삭제할 수 없다는 뜻이다.
해결 방법 1: 정지 후 삭제
1
docker stop 컨테이너명 && docker rm 컨테이너명
ex)
1
docker stop docker-container && docker rm docker-container
해결 방법 2: 강제 삭제
1
docker rm -f 컨테이너명
ex)
1
docker rm -f docker-container
이후 다시 빌드하고 실행하면 된다.
1
2
docker build -t 이미지명 .
docker run -d -p 7000:8000 --env-file .env --name 컨테이너명 이미지명
ex)
1
2
docker build -t docker-image .
docker run -d -p 7000:8000 --env-file .env --name docker-container docker-image
15. 수정할 때마다 다시 빌드하는 것이 불편한 경우
Docker 이미지는 기본적으로 빌드 시점의 파일을 컨테이너 안에 복사한다.
따라서 코드를 수정하면 다시 빌드해야 반영된다.
하지만 개발 중에는 아래처럼 -v 옵션을 사용하면
현재 프로젝트 폴더를 컨테이너 내부 /app과 연결할 수 있다.
이렇게 하면 파일 수정, 파일 추가, 파일 삭제 모두 컨테이너에 실시간으로 반영된다.
단, requirements.txt에 패키지를 추가했을 때는 빌드를 다시 해야 한다.
Linux 서버에서는 절대경로를 사용해야 한다.
현재 절대경로는 pwd 명령어로 확인한다.
1
2
pwd
# 예) /home/ubuntu/project
1
docker run -d -p 7000:8000 --env-file /home/ubuntu/project/.env -v /home/ubuntu/project:/app --name 컨테이너명 이미지명
ex)
1
docker run -d -p 7000:8000 --env-file /home/ubuntu/project/.env -v /home/ubuntu/project:/app --name docker-container docker-image
이미 같은 이름의 컨테이너가 있다면 먼저 삭제해야 한다.
1
docker rm -f 컨테이너명
ex)
1
docker rm -f docker-container
그 후 다시 실행한다.
1
2
3
docker run -d -p 7000:8000 --env-file /home/ubuntu/project/.env \
-v /home/ubuntu/project:/app \
--name docker-container docker-image
참고:
.env파일은 컨테이너 시작할 때만 읽히기 때문에.env를 수정하면 반드시 컨테이너를 재시작해야 한다. 볼륨 마운트와 무관하게 항상 재시작이 필요하다.
16. 오류 3: django_session 테이블이 없는 경우
-v 옵션으로 볼륨 마운트를 처음 사용할 때 아래와 같은 오류가 발생할 수 있다.
1
django.db.utils.OperationalError: no such table: django_session
이 오류는 DB 마이그레이션이 안 된 상태이기 때문이다.
기존에 -v 없이 실행했을 때는 docker build 시점에 복사된 DB가 컨테이너 안에 있었지만,
-v 옵션으로 로컬 폴더를 연결하면 로컬에 DB가 없어서 테이블도 없는 상태가 된다.
해결 방법은 컨테이너 안에서 migrate를 실행하면 된다.
1
docker exec 컨테이너명 python manage.py migrate
ex)
1
docker exec docker-container python manage.py migrate
컨테이너 재시작 없이 바로 반영되며, 로컬 폴더에 DB 파일이 생성되므로 이후에는 다시 실행할 필요가 없다.
migrate가 필요한 경우 정리:
-v볼륨 마운트를 처음 사용할 때- 로컬에 DB 파일이 없을 때
- 새로운 모델을 추가했을 때
17. 자주 사용하는 Docker 명령어 정리
이미지 빌드
1
docker build -t 이미지명 .
ex)
1
docker build -t docker-image .
컨테이너 실행
1
docker run -d -p 7000:8000 --env-file .env --name 컨테이너명 이미지명
ex)
1
docker run -d -p 7000:8000 --env-file .env --name docker-container docker-image
실행 중인 컨테이너 확인
1
docker ps
꺼진 컨테이너까지 확인
1
docker ps -a
로그 확인
1
docker logs 컨테이너명
ex)
1
docker logs docker-container
컨테이너 정지
1
docker stop 컨테이너명
ex)
1
docker stop docker-container
컨테이너 삭제
1
docker rm 컨테이너명
ex)
1
docker rm docker-container
실행 중인 컨테이너 강제 삭제
1
docker rm -f 컨테이너명
ex)
1
docker rm -f docker-container
이미지 목록 확인
1
docker images
이미지 삭제
1
docker rmi 이미지명
ex)
1
docker rmi docker-image
컨테이너 내부 명령어 실행
1
docker exec 컨테이너명 명령어
ex)
1
docker exec docker-container python manage.py migrate
18. 전체 배포 흐름 요약
전체 흐름은 아래 순서로 진행하면 된다.
1단계: 서버 접속
1
ssh 사용자id@접속IP
ex)
1
ssh ubuntu@123.123.123.123
2단계: 프로젝트 폴더 이동
1
cd project
ex)
1
cd overwatch
3단계: 현재 위치 확인
1
pwd
4단계: 파일 확인
1
ls
아래 파일들이 있는지 확인한다.
1
2
3
4
Dockerfile
manage.py
requirements.txt
.env
5단계: 이미지 빌드
1
docker build -t 이미지명 .
ex)
1
docker build -t docker-image .
6단계: 컨테이너 실행
1
docker run -d -p 7000:8000 --env-file /절대경로/.env -v /절대경로:/app --name 컨테이너명 이미지명
ex)
1
docker run -d -p 7000:8000 --env-file /home/ubuntu/project/.env -v /home/ubuntu/project:/app --name docker-container docker-image
7단계: 실행 확인
1
docker ps
8단계: DB 마이그레이션 (볼륨 마운트 처음 사용 시)
1
docker exec 컨테이너명 python manage.py migrate
ex)
1
docker exec docker-container python manage.py migrate
9단계: 브라우저 접속
1
http://서버접속IP:7000
ex)
1
http://123.123.123.123:7000
10단계: 오류가 있으면 로그 확인
1
docker logs 컨테이너명
ex)
1
docker logs docker-container
19. 최종 예시 명령어
아래는 실제로 가장 많이 사용하는 명령어 흐름이다.
1
2
3
4
5
6
7
8
ssh ubuntu@123.123.123.123
cd project
pwd
ls
docker build -t docker-image .
docker run -d -p 7000:8000 --env-file /home/ubuntu/project/.env -v /home/ubuntu/project:/app --name docker-container docker-image
docker ps
docker exec docker-container python manage.py migrate
오류가 발생하면:
1
2
docker ps -a
docker logs docker-container
수정 후 다시 실행하려면:
1
2
3
docker rm -f docker-container
docker build -t docker-image .
docker run -d -p 7000:8000 --env-file /home/ubuntu/project/.env -v /home/ubuntu/project:/app --name docker-container docker-image
.env 수정 후 재시작하려면:
1
2
docker rm -f docker-container
docker run -d -p 7000:8000 --env-file /home/ubuntu/project/.env -v /home/ubuntu/project:/app --name docker-container docker-image