Docker를 통해 webapp을 배포하는 방법을 알아보자
Static Sites
가장 먼저 정적 사이트를 실행시키는 방법을 알아볼 것이다. 도커 허브로부터 이미지를 꺼낸 다음 컨테이너를 실행시켜 웹 서버를 실행시키는 것이 얼마나 쉬운지 보자. 아래 링크의 레지스트리에서 static-site 이미지를 실행시켜 보자.
https://hub.docker.com/r/prakhar1989/static-site/
Docker Hub
hub.docker.com
먼저 도커 이미지를 다음 명령어를 통해 remote registry에서 가져온다.
$ docker pull prakhar1989/static-site
다음으로 해당 이미지를 실행시킨다. --rm 옵션을 통해 종료 이후 해당 컨테이너를 삭제한다.
$ docker run --rm prakhar1989/static-site
이미지는 컨테이너의 청사진, 컨테이너는 실행 가능한 구현체라고 생각하면 된다.
컨테이너를 실행시키면 터미널에서 Nginx is running... 이라는 메시지를 볼 수 있다. 이제 서버는 실행이 되고 있다. 하지만 어떻게 웹사이트를 볼 수 있을까? 돌아가는 포트는 몇번일까? 그리고 호스트 머신에서 컨테이너에 직접 접근하는 방법은 무엇일까? 일단 ctrl+c를 눌러 컨테이너를 종료하자.
위 경우는 클라이언트 즉 컨테이너가 아무 포트도 노출하고 있지 않다. 따라서 포트를 공개하기 위해 다시 도커를 실행시켜야 한다. 또한 터미널이 실행중인 컨테이너에 붙어있지(attached) 않도록 그러니까 백그라운드에서 실행되도록 설정을 해주어야 한다. 이를 detached mode라고 한다.
$ docker run -d -P --name static-site prakhar1989/static-site
위 명령어에서, -d는 터미널과 detach하는 옵션이다. -P는 노출된 포트를 랜덤한 포트에 발행하고 --name은 컨테이너에게 이름을 따로 지정한 것이다. 이제 우리는 다음 명령어를 통해 실행되고 있는 포트를 확인할 수 있다.
$ docker port static-site
443/tcp -> 0.0.0.0:55000
443/tcp -> :::55000
80/tcp -> 0.0.0.0:55001
80/tcp -> :::55001
이제 http://localhost:55001에서 static-site를 확인할 수 있다.(80/tcp)
또한 원한다면 아래 명령어를 통해 클라이언트가 컨테이너에 포워딩할 포트 번호를 직접 지정할수도 있다.
$ docker run -p 8888:80 prakhar1989/static-site
백그라운드에서 실행중인 컨테이너를 종료하기 위해서 아래 명령어를 입력하면 된다.
$ docker stop static-site
다음으로 사용자가 원하는 이미지를 스스로 만드는 법에 대해 알아보겠다.
Docker Images
이번에는 도커의 이미지에 대해 더 자세히 알아보며 직접 이미지를 반들어 보자.
도커 이미지는 컨테이너의 기반이 된다. 우리는 레지스트리에서 원하는 이미지를 가져온 다음 클라이언트에서 이미지를 기반으로 한 컨테이너를 실행시켰다. 다음 명령어를 실행시켜 로컬에 저장된 이미지 목록을 확인하자
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 20.04 2b4cba85892a 10 days ago 72.8MB
prakhar1989/static-site latest f01030e1dcf3 6 years ago 134MB
여기서 IMAGE ID는 해당 이미지의 고유한 id를 나타내고, TAG는 이미지의 버전을 나타낸다.
만약 git에 익숙하다면 모든 이미지들은 git처럼 관리된다고 생각해도 좋다. 이미지는 다양한 버전을 가지고 있는데, remote registry에서 가져올 때 특정 버전을 지정하여 가져올 수도 있다.
$ docker pull ubuntu:18.04
도커 이미지를 얻기 위해서는 레지스트리에서 가져올 수도 있고 당신이 직접 이미지를 만들수도 있다. Docker Hub에는 수많은 이미지들이 저장되어 있다. 만약 터미널에서 필요한 이미지를 검색하고 싶다면 아래 명령어를 사용하면 된다.
$ docker search
Docker Hub
hub.docker.com
도커의 이미지는 부모 이미지와 자식 이미지로 나뉜다.
- Base images는 부모가 없는 이미지를 말한다. 우분투나 데비안 같은 OS이미지들이 여기에 포함된다.
- Child images는 부모 이미지에 추가적인 기능이 더해진 이미지를 말한다.
또한, 도커의 이미지는 공식 이미지와 사용자 이미지로 나뉜다. 이중 사용자 이미지의 이름음 다음과 같은 형식을 띈다.
user/image-naem
Dockerfile
도커파일은 해당 이미지를 생성할때 실행될 명령어들을 담고 있다. 도커파일에 명령어를 작성할 때의 큰 특징 중 하나는 문법이 리눅스와 상당히 흡사하다는 점이다. 때문에 다른 문법을 따로 배우지 않아도 된다는 장점이 있다. 이제 도커파일을 직접 작성해보자.
먼저 base image를 설정해주자. 이번 예시는 플라스크 앱이므로 python3를 추가해준다.
FROM python:3
다음 순서는 파일들을 복사하고 dependencies들을 추가한다. 먼저, 작업 디렉터리를 설정하고 모든 파일들을 복사한다.
# set a directory for the app
WORKDIR /usr/src/app
# copy all the files to the container
COPY . .
복사한 파일들로부터 dependency들을 추가한다.
# install dependencies
RUN pip install --no-cache-dir -r requirements.txt
다음으로 노출할 포트번호를 지정해야 한다. 일반적으로 flask앱은 포트 5000에서 실행되므로 이를 명시한다.
EXPOSE 5000
마지막 단계는 어플리케이션을 실행하기 위한 명령어를 지정해주는 것이다. 플라스크 앱의 경우에는 python ./app.py가 된다.
CMD ["python", "./app.py"]
CMD의 가장 중요한 목적은 컨테이너가 실행될때 어떤 명령어를 수행해야하는지를 나타낸다. 이로서 도커파일이 완성되었다.
도커파일을 통해 컨테이너를 빌드하기 위해서는 docker build 명령어를 실행하면 된다.
$ docker build -t yourusername/catnip .
위 명령에서 실행하는 yourusername은 Docker hub에 등록된 유저이름과 동일해야 한다. 또한 이 명령어는 도커파일이 있는 위치를 포함해야한다. 위의 경우에는 현재위치(.)가 지정되어 있다.
호스트 환경에 python3에 대한 이미지가 없다면 도커는 먼저 해당 이미지를 불러온다. 이제 docker images 명령어를 통해 로컬에 이미지가 생성되었는지 확인하자.
REPOSITORY TAG IMAGE ID CREATED SIZE
seyoung8239/catnip latest 9565315077d9 3 minutes ago 927MB
ubuntu 20.04 2b4cba85892a 10 days ago 72.8MB
prakhar1989/static-site latest f01030e1dcf3 6 years ago 134MB
이제 다음 명령어를 통해 어플리케이션을 실행시킬 수 있다.
docker run -p 8888:5000 yourusername/catnip
8888:5000의 의미는 컨테이너 내부에서 5000서버를 통해 어플리케이션을 띄우고 외부에서 8888포트를 통해 노출시키겠다는 의미이다.
예시에서 git clone으로 가져온 app을 빌드 후 실행했을 때, import에러가 발생했다. requirements.txt에 있는 Flask의 버전을 2.0이 상으로 수정하면 해당 문제를 해결할 수 있다.
Docker on AWS
방금 생성한 이미지를 AWS Elastic Beanstalk를 이용해 간단히 배포 해보자.
Docker push
배포를 하기에 앞서 어플리케이션의 이미지를 레지스트리에 올려 AWS가 찾을 수 있도록 해야한다. 도커 레지스트리의 종류는 다양하지만 이번 예시에서는 도커 허브를 사용하겠다. remote registry에 이미지를 push하기 위해서는 우선 로그인을 해야한다.
$ docker login
다음으로 아래 명령어를 통해 docker hub에 이미지를 push한다.
$ docker push yourusername/catnip
Beanstalk
AWS Elastic Beanstalk(EB)는 AWS가 제공하는 PasS(Platform as a Service)이다. 일반적으로 사용되는 배포 툴인 Heroku, Google App Engine과 비슷하다. 사용자는 단순히 EB에게 앱을 어떻게 실행시키는 지만 알려주면, 스케일링, 모니터링 그리고 업데이트까지 EB가 처리한다.
코드 업로드 버튼을 누르고 프로젝트 디렉터리의 Dockerrun.aws.json 파일을 업로드 해준다. 해당 파일의 내용에 대해서는 잠시 후에 알아보겠다. 다음으로 프로젝트 생성 버튼을 누르면 AWS EB에 배포가 완료된다.
{
"AWSEBDockerrunVersion": "1",
"Image": {
"Name": "prakhar1989/catnip",
"Update": "true"
},
"Ports": [
{
"ContainerPort": 5000,
"HostPort": 8000
}
],
"Logging": "/var/log/nginx"
}
Dockerrun.aws.json파일은 위와 같다. 이미지의 이름과 내부, 외부에서 사용할 포트의 번호가 지정되어 있다.
배포가 완료된 후의 AWS 콘솔 화면은 위와 같다. 올려진 링크를 통해 어플리케이션에 직접 접근할 수 있다.
'DevOps > Docker' 카테고리의 다른 글
MacOS Docker-Ubuntu VSCode (0) | 2021.09.11 |
---|---|
MacOS Docker Linux GUI (0) | 2021.09.11 |
MacOS Docker Linux (0) | 2021.09.11 |