Post

Docker 배포 정리

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.tomldependencies 항목을 보고 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
This post is licensed under CC BY 4.0 by the author.