Seapy's Blog


레일스(Rails) 배포

레일스 프로젝트 배포 방법으로는 Capistrano가 가장 많이 사용되고 있으며 배포가 명령어 한줄이면 될정도로 간단하다.

그런데 정말로 전체적인 배포 과정이 간단한것일까? Capistrano를 이용해 배포하는것은 쉽다고 해도 서버 설정은 그리 간단하지 않다. 이러한 서버 설정 및 설치를 코드화, 자동화 하기위해 Chef, Puppet 같은것이 사용되기도 하지만 그 자체로도 상당히 복잡하다.

이번 포스트에서 언급하는 Docker를 이용한 배포는 한줄이면 nginx, unicorn을 이용한 서버 구축은 물론 어플리케이션 배포까지 가능하다.

참고로 Docker에 대해서 전혀 모르는 경우 Docker 홈페이지나 다음 블로그 글들을 참고하기 바란다.

Docker 이미지 생성 및 실행

그럼 실제로 배포하는 과정을 간단하게 적어보겠다.

참고로 이 내용은 스크린캐스트 Easy Ruby On Rails deploy on Docker, Docker로 레일스 배포하기(Docker Seoul meetup #1 발표)에서 동영상으로 확인 할 수 있다.

새로운 레일스 프로젝트를 생성하고 해당 폴더로 이동한다.

$ rails new docker
$ cd docker

프로젝트가 생성됬으면 프로젝트 루트폴더에 Dockerfile을 생성하고 다음 내용을 붙여넣기 한다.

# Dockerfile
FROM seapy/rails-nginx-unicorn
MAINTAINER seapy(iamseapy@gmail.com)

EXPOSE 80

seapy/rails-nginx-unicorn 이미지는 내가 만든것으로 쉬운 배포 작업을 위해 사전작업이 완료된 상태의 이미지다. 자세한 내용은 github에서 확인할수 있고 Docker hub에도 등록되어 있다.

unicorn gem을 사용하기 위해 Gemfile에서 다음 내용을 추가하거나 코멘트를 제거하고 bundle install을 실행한다.

# Gemfile
gem 'unicorn'
$ bundle install

마지막으로 id_rsa 파일을 만들고 빈파일로 둔다.

이 파일은 bitbucket 개인저장소에 접근해야하는경우 필요한 값으로 필요하지 않더라도 파일은 존재해야한다. 저장소 접근이 필요한경우에는 bitbucket에 추가되어있는 공개키에 해당하는 개인키를 입력한다(cp ~/.ssh/id_rsa id_rsa)

레일스 프로젝트에서 해야할 작업은 모두 종료됬다.

이제 다음 명령어로 Docker 이미지를 생성한다.

$ docker build -t your/project .

Docker 이미지 이름이 your/project가 생성되고 이안에는 nginx, unicorn을 위한 설정 파일과 여러분의 레일스 어플리케이션 코드가 추가되어있다.

이제 생성된 이미지로 Docker 컨테이너를 실행한다.

$ docker run -d -p 80:80 -e SECRET_KEY_BASE=secretkey your/project

이제 레일스 어플리케이션 실행이 완료되었다. docker run 명령어를 서버에서 실행했다면 서버에 배포가 된것이다.

여기서 프로젝트에 따라 -e 옵션을 이용해 추가 환경변수를 설정하게 될것이다.

샘플로 만든 레일스 프로젝트는 아무것도 설정한것이 없어서 실제 실행시 접속하면 페이지가 없다는 오류 화면만 보게 되는데 robots.txt 파일을 확인해서 정상이라면 배포에 이상이 없다고 보면 된다.

커스터 마이징

다양한 확장 가능성을 생각해서 seapy/rails-nginx-unicorn 이미지에서는 nginx, unicorn, foreman 설정파일을 프로젝트마다 덮어쓸수 있다.

nginx의 경우 직접 설정파일을 만들고 레일스 프로젝트 Dockerfile에서 다음 라인을 추가한다. 참고로 추가한 설정파일은 nginx 설정파일중 http 블럭안에 들어간다.

# Dockerfile
ADD config/your-custom-nginx.conf /etc/nginx/sites-enabled/default

unicorn 설정파일은 레일스 프로젝트의 config/unicorn.rb에 신규 생성후 저장하면되고,

foreman 설정파일은 레일스 프로젝트의 Procfile에 신규 생성후 저장하면된다.

특정 Ruby, nginx 버전 사용하기

Ruby, nginx의 버전이 달라지는것에 따른 영향을 없애려면 레일스 프로젝트의 Dockerfile에서 FROM 절에 태그를 이용해 버전을 명시하면 된다.

# Dockerfile
FROM seapy/rails-nginx-unicorn:ruby2.1.2-nginx1.6.0

Asset Precompile에 대해서

seapy/rails-nginx-unicorn 이미지를 만들면서 제일 고민했던 부분은 assets:precompile로 운영환경 설정이 필요한데 Dockerfile이 실행되는 시점에는 운영환경 정보가 없었고, 로컬 환경으로 작업후 추가하려니 마찬가지로 로컬 환경도 도커 이미지 안에서는 무용지물이었다.

해결방법으로 CMD에서 foreman 실행전에 assets:precompile을 실행하도록 했다.

컨테이너가 실행될때마다 실행되기 때문에 찝찝했지만 현재로서는 가장 최선의 방법으로 생각해서 적용했다.

더 좋은 방법이라면 빌드 전용 젠킨스를 놔두고 여기서 Docker 이미지 생성시 한번만 실행하고 결과 파일을 복사하는것이지만 젠킨스가 없는 환경에서는 위의 방법이 최선이라고 생각했다.

다른곳에 적용하고자 하는분들을 위한 팁

레일스 쉽게 배포하기지만 내가 만든 Dockerfile을 github에서 참고한다면 PHP, Java, Python(Django), Node.JS 등에서도 가능하다.

비슷한 작업을 하려는 분들에게 드리는 팁이라면 Dockerfile의 ONBUILD가 핵심이라는것이다. 이에 대한 자세한 정보는 공식문서를 참고하기 바란다.

정리

Docker를 처음 알게 된것이 5월쯤으로 기억하는데 그 순간부터 지금까지 Docker에 완전 빠져 살았다.

다른것을 하고 싶어도 이 매력적인 기술앞에 모두 패했고 결국 Docker를 처음 접하면서 하고 싶었던것을 이번에 이루게 됬다.

다음 포스트에서는 아직 미완성이지만 elasticsearch를 Docker로 쉽게 배포하는것과 실제 적용 사례를 적어보려고 한다.

참고정보 및 유용한 링크