Docker는 가상화 기술의 하나로 container virtualization 이라는 기술을 제공합니다. Docker는 컨테이너라는 가상 실행 환경 위에 application 배포 엔진을 더해 사용자의 코드를 어디서든 빠르고 가볍게 실행시킬 수 있게 해줍니다.
이 Docker를 이용해서 이번에 진행한 프로젝트를 EC2에 배포해보도록 하겠습니다.
프로젝트의 서버를 실행시키려면 도커의 이미지 내에도 gunicorn
이 설치되어야합니다. 다른 프로그램을 쓰시면 다른걸 사용해도 됩니다. 도커에 프로그램을 빌드시킬 때 requirements.txt
에 있는 프로그램들을 설치하기 때문에 여기 안에 gunicorn
을 명시해주면 됩니다. 이 부분은 pip freeze
로 할 수 있는데 아래 글을 보면서 참고해보시면 좋습니다.
>>> pip install gunicorn
Collecting gunicorn
Using cached gunicorn-20.0.4-py2.py3-none-any.whl (77 kB)
Requirement already satisfied: setuptools>=3.0 in /Users/LeeJongMin/conda/envs/danaebang/lib/python3.8/site-packages (from gunicorn) (45.2.0.post20200210)
Installing collected packages: gunicorn
Successfully installed gunicorn-20.0.4
저의 경우에는 my_settings.py
라는 파일 안에 데이터베이스 정보를 작성해뒀는데, 여기에서 도커와 연결할 데이터베이스 정보를 작성해줘야합니다. 본 프로젝트의 데이터베이스는 AWS RDS에 올려뒀기 때문에 세팅 파일 안에 이 정보를 넣어줍니다. 기존에 설정이 되어있다면 Host와 Password 정보만 맞게 넣어주면 됩니다. 제 my_settings.py
설정은 아래 글을 보시면 확인해 보실 수 있습니다.
마지막으로 도커 이미지를 빌드하기 전에 로컬에서 프로젝트 서버가 잘 돌아가는지 확인해봅니다. 여기서 안되면 도커에서도 안됩니다.
>>> python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
March 20, 2020 - 14:50:08
Django version 3.0.3, using settings 'danaebang.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
이제 프로젝트 최상위 디렉터리에 도커 이미지 빌드 설정을 해주는 Dockerfile
을 생성합니다. 확장자명은 없고, 파일명 전체가 Dockerfile
입니다.
파일 안에는 아래와 같은 내용을 채워줍니다.
>>> vi Dockerfile
#./Dockerfile
FROM python:3 [ 1 ]
WORKDIR /usr/src/app [ 2 ]
## Install packages
COPY requirements.txt ./ [ 3 ]
RUN pip install -r requirements.txt [ 4 ]
## Copy all src files
COPY . . [ 5 ]
## Run the application on the port 8080
EXPOSE 8000 [ 6 ]
#CMD ["python", "./setup.py", "runserver", "--host=0.0.0.0", "-p 8080"]
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "example.wsgi:application"] [ 7 ]
[ 1 ] : 기반이 될 이미지 설정
[ 2 ] : 작업 디렉토리 설정(도커 이미지 내의 경로)
[ 3 ] : 현재 패키지 설치 정보를 도커 이미지에 복사
[ 4 ] : requirements.txt를 읽어서 도커 내에 프로그램 설치
[ 5 ] : 현재 프로젝트 최상위 디렉토리의 파일 전체를 도커의 경로에 모두 복사
[ 6 ] : 개방할 도커의 특정 포트번호. 여기서는 8000번 포트를 외부에 개방
[ 7 ] : gunicorn을 사용해서 서버를 실행. example 자리에는 내 프로젝트의 wsgi가 위치한 디렉토리를 명시
이제 Dockerfile이 있는 위치에서 쉘에 아래의 명령어를 쳐서 도커 이미지를 만듭니다. (그 전에 docker login
으로 로그인을 해줍니다.) 이름 앞에 계정명을 안써도 되긴 하는데, 계정명을 안쓰면 가끔 에러가 뜰 수 있다고 해서 전 계정명을 입력했습니다.
마지막에 있는 "."
은 현재 디렉토리에 있는 Dockerfile을 사용하겠다고 명시해주는 역할을 합니다.
docker build -t '도커허브에 가입한 계정명'/'이미지명':'버전' .
ex) docker build -t jongjong/project:0.1.0 .
>>> docker build -t jongjong/project:0.1 .
Sending build context to Docker daemon 97.17MB
Step 1/7 : FROM python:3
---> f88b2f81f83a
Step 2/7 : WORKDIR /usr/src/app
---> Using cache
---> 48b1397fae7d
Step 3/7 : COPY requirements.txt ./
---> f6782e5cb3c7
Step 4/7 : RUN pip install -r requirements.txt
---> Running in 9d6612e02861
Collecting asgiref==3.2.3
Downloading asgiref-3.2.3-py2.py3-none-any.whl (18 kB)
~~~
Step 5/7 : COPY . .
---> 41449b5911cb
Step 6/7 : EXPOSE 8000
---> Running in 52fbf8aa4e42
Removing intermediate container 52fbf8aa4e42
---> 5e2aba021983
Step 7/7 : CMD ["gunicorn", "--bind", "0.0.0.0:8000", "project.wsgi:application"]
---> Running in d81526492674
Removing intermediate container d81526492674
---> 481b7f7169f6
Successfully built 481b7f7169f6
Successfully tagged jongjong/project:0.1
이미지가 빌드된 후 docker images
를 쉘에 쳐보면 만들어진 이미지를 볼 수 있습니다.
>>> docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
jongjong/project 0.1 481b7f7169f6 6 seconds ago 1.1GB
python 3 f88b2f81f83a 3 weeks ago 933MB
-d는 지속적으로 실행하기 위한 옵션이고, -p는 포트포워딩을 한다는 의미입니다. 호스트 포트는 내가 열 포트의 번호이고, 컨테이너 포트는 위에서 Dockerfile
을 만들때 설정한 8000 포트로 설정됩니다.
docker run --name '컨테이너 명' -d '데몬으로 실행하기 위한 옵션' -p '호스트 포트':'컨테이너 포트' '이미지명'
ex) docker run --name jong01 -d -p 8000:8000 jongjong/project:0.1.0
>>> docker run -d -p 8000:8000 jongjong/project:0.1
3d1c79166938fe502a2aebc957a94ede0e59bf940fe168650c2be91a1c3641e2
docker ps
를 사용하면 현재 실행중인 컨테이너를 확인할 수 있습니다.
>>> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3d1c79166938 jongjong/project:0.1 "gunicorn --bind 0.0…" 4 seconds ago Up 3 seconds 0.0.0.0:8000->8000/tcp hungry_beaver
>>> docker stop hungry_beaver
hungry_beaver
>>> docker start hungry_beaver
hungry_beaver
>>> docker stop hungry_beaver
hungry_beaver
docker stop 컨테이너명
으로 컨테이너를 중단할 수 있고, 또 중단한 컨테이너를 docker start 컨테이너명
으로 다시 실행할 수 있습니다. 그리고 컨테이너가 필요없어지면 docker rm 컨테이너명
으로 컨테이너를 삭제할 수 있습니다. 컨테이너를 삭제한다고 빌드한 이미지는 삭제되지 않으니 걱정 마세요!
이제 이미지를 푸시하면 되는데, 깃허브에서 내 코드를 레퍼지토리에 푸시하는 개념과 같다고 생각하면 됩니다. 도커에도 도커 레퍼지토리가 있어서 나의 이미지를 올려놓을 수 있습니다.
>>> docker push '이미지명'
>>> docker push jongjong/project:0.1.0
터미널에서 docker login
을 입력하면 계정 정보를 입력하라는 메시지가 나타납니다. 입력을 완료하고 나면 도커에 로그인이 됩니다.
>>> sudo docker login
Authenticating with existing credentials...
WARNING! Your password will be stored unencrypted in /home/ubuntu/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
제 EC2는 우분투로 되어있기 때문에, 맥에 설치했을때와는 다른 방식으로 도커를 설치 해줘야합니다. 아래의 명령어들을 한줄씩 입력해주면 설치가 됩니다.
sudo apt update
sudo apt install apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable"
sudo apt update
apt-cache policy docker-ce
sudo apt install docker-ce
로컬에서와 마찬가지로 docker login
으로 로그인을 한 후 도커 레퍼지토리에 있는 이미지를 pull 해오면 됩니다. 우분투에서는 권한설정 문제가 있어서 모든 명령어를 칠 때 앞에 sudo
를 쳐주세요!
>>> sudo docker pull '이미지명'
sudo docker pull jongjong/project:0.1.0
pull 을 해오고 난 후, sudo docker images -a
를 치면 pull된 이미지가 보입니다.
이미지를 실행하기 위해서는 로컬에서와 마찬가지로 run
명령어를 실행하면 됩니다.
sudo docker run --name '컨테이너명' -d -p 8000:8000 jongjong/project:0.1.0
>>> sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
jongjong/project 0.1 481b7f7169f6 5 minutes ago 1.1GB
안녕하세요. 글 잘 보았습니다.
혹시 ec2 에 배포할 경우, apache2 나 nginx 를 이용한 라우팅은 따로 안해주시나요?