고백 시간. 4년 동안 Honeybadger에서 일한 내 개발 환경은 크게 바뀌지 않았습니다. 그러나 그 동안 Honeybadge는 약 10개의 서비스가 작동해야 하므로 훨씬 더 정교해졌습니다.
이것이 우리가 로컬 개발을 위해 Docker로 옮겨온 이유입니다. 모든 개발자가 Postgres, Cassandra, Memcached 등을 설정하는 대신 docker-compose를 사용하여 미리 만들어진 환경을 가동할 수 있습니다. 굉장합니다.
당연히 Dockerized 애플리케이션을 배포하는 것이 얼마나 쉬운지 궁금해지기 시작했습니다.
도커로 배포
Docker는 배포를 쉽게 만들어주는 docker-machine 및 docker-swarm과 같은 유틸리티와 함께 제공됩니다. 지금까지 그들은 그 약속을 지키지 않았습니다. 이들의 결함에 대해 모두 읽고 싶다면 최근 해커 뉴스 게시물을 확인하세요.
그래서 Amazon의 ECS(EC2 Container Service)에 집중하기로 결정했습니다.
ECS란 무엇입니까?
ECS는 docker-compose 및 docker-swarm의 성숙한 프로덕션 준비 매시업과 같습니다.
ECS를 사용하면 "내 웹 앱 사본 3개 실행"이라고 말하면 EC2 인스턴스 클러스터 내에서 적절한 Docker 컨테이너를 지능적으로 가동합니다.
컨테이너 간에 요청을 로드 밸런싱하고 로드에 따라 클러스터를 확장하거나 축소할 수 있습니다.
도커화된 Sinatra 앱 만들기
여기 간단한 Sinatra 앱이 있습니다. 현재 시간을 인쇄하므로 캐시된 버전이 표시되는지 알 수 있습니다. 또한 앱을 실행하는 컴퓨터의 이름도 인쇄합니다. 나중에 이 앱을 실행하고 로드 밸런서를 사용하여 요청을 라우팅하는 여러 서버를 가동할 것입니다. 호스트 이름을 반환하면 특정 요청을 처리한 서버를 알 수 있습니다.
앱
제가 보여드릴 Dockerized Sinatra 앱은 tcnksm-sample/docker-sinatra를 크게 재작성한 버전입니다.
require 'sinatra'
require 'sinatra/base'
class App < Sinatra::Base
get '/' do
"Hello from sinatra! The time is #{ Time.now.to_i } on #{ `hostname` }!"
end
end
다음은 Gemfile
입니다. :
# Gemfile
source 'https://rubygems.org'
gem 'sinatra'
gem 'thin'
...여기 config.ru
가 있습니다. 파일:
$:.unshift(File.dirname(__FILE__))
require 'app'
run App
도커파일
이 앱에 대한 Docker 이미지를 생성하려면 Dockerfile이 필요합니다. 앱의 디렉터리를 만들고 파일을 복사하고 포트 80에서 웹 서버를 실행합니다.
FROM ruby:2.3.1-slim
RUN apt-get update -qq && apt-get install -y build-essential
ENV APP_ROOT /var/www/docker-sinatra
RUN mkdir -p $APP_ROOT
WORKDIR $APP_ROOT
ADD Gemfile* $APP_ROOT/
RUN bundle install
ADD . $APP_ROOT
EXPOSE 80
CMD ["bundle", "exec", "rackup", "config.ru", "-p", "80", "-s", "thin", "-o", "0.0.0.0"]
이미지 빌드 및 실행
먼저 Docker에게 현재 디렉토리의 Docker 파일에서 이미지를 빌드하도록 지시할 것입니다. 그런 다음 컨테이너의 포트 80을 localhost:4000에 매핑하여 실행합니다.
docker build -t docker-sinatra .
docker run -p 4000:80 docker-sinatra
작동하는지 확인하려면 웹 브라우저에서 localhost:4000을 엽니다. 다음과 같이 표시되어야 합니다.
ECS에 배포
이제 ECS에 배포해 보겠습니다. 우리는 그들의 설정 마법사를 사용할 것입니다. 그게 속임수야? 난 상관없어. :) ECS 제어판으로 이동합니다.
"시작하기"를 클릭하십시오. 그런 다음 다음 화면에서 "계속"을 클릭하십시오."
도커 레지스트리 만들기
일반적으로 개발 환경에서 프로덕션 서버로 Docker 이미지를 업로드하지 않습니다. 대신 dockerhub와 같은 Docker 레지스트리로 이미지를 보내면 서버가 배포 시 이미지를 가져옵니다. Amazon은 프라이빗 Docker 레지스트리를 제공합니다. 반드시 사용해야 하는 것은 아니지만 당분간은 계속 사용하겠습니다.
내 레지스트리 이름을 "docker-sinatra"로 지정하겠습니다.
이미지를 레지스트리로 푸시
그런 다음 이미지를 빌드하고 레지스트리에 푸시하기 위해 실행할 명령 목록이 제공됩니다.
이것을 처음 시도했을 때 내 브라우저의 광고 차단기가 명령이 올바르게 표시되지 않도록 했습니다. 이상해 - 나도 알아.
작업 정의 만들기
AWS는 새롭고 혼란스러운 용어를 만드는 것을 좋아합니다. "작업 정의"는 단순히 함께 실행되어야 하는 컨테이너 목록입니다. 일종의 Procfile 또는 docker-compose 구성과 비슷합니다.
따라서 애플리케이션에 Nginx를 실행하는 컨테이너 하나, Unicorn을 실행하는 컨테이너 하나, Sidekiq를 실행하는 컨테이너 하나가 있는 경우 세 가지 모두가 "작업 정의"에 포함될 수 있습니다.
우리 앱은 훨씬 간단합니다. 우리는 하나의 컨테이너만 가지고 있습니다. 따라서 구성이 최소화됩니다.
- 레지스트리에서 올바른 이미지를 가져오는지 확인하겠습니다.
- 컨테이너의 포트 80을 컨테이너를 실행하는 EC2 인스턴스의 포트 80에 매핑하겠습니다.
서비스 만들기
더 헷갈리는 용어! "서비스" 구성을 사용하면 실행해야 하는 "작업"(앱 사본이라고도 함)의 수와 부하 분산 방식을 지정할 수 있습니다.
여기에서는 포트 80에서 로드 밸런싱을 사용하여 3개의 앱 복사본을 실행하려고 합니다.
클러스터 회전
클러스터는 Amazon의 ECS 소프트웨어를 실행하는 일반적인 EC2 인스턴스의 무리입니다. 다른 EC2 인스턴스로 할 수 있는 모든 것을 할 수 있습니다. 이 경우 3개의 t2.micro 인스턴스를 원한다고 지정했습니다.
몇 가지 확인 단계와 약 5분의 기다림 끝에 모든 것이 준비되었습니다.
서비스가 작동하면 다음과 같은 화면이 표시됩니다.
앱 테스트
로드 밸런서 이름을 클릭하여 세부 정보를 가져올 수 있습니다. 거기에서 공개 도메인 이름을 찾아야 합니다. 브라우저에 넣으면 샘플 앱이 표시됩니다.
몇 번 새로 고침하면 호스트 이름이 변경되는 것을 볼 수 있습니다. 로드 밸런서가 세 호스트 모두에서 요청의 균형을 조정하기 때문입니다.
청소
ECS 마법사는 지금 AWS 계정에 많은 리소스를 생성했습니다. 당신은 아마 그들을 거기에두고 싶지 않을 것입니다. 그것들은 물건을 어지럽히고 비용이 많이 들 수 있습니다.
다행히 ECS 마법사는 CloudFormation을 사용하여 모든 리소스를 생성합니다. 즉, CloudFormation 스택을 제거하기만 하면 모든 것을 삭제할 수 있습니다.