# Docker 이미지 만들고 배포하기

# 도커 이미지 만들기

도커는 이미지를 만들기 위해 컨테이너의 상태를 그대로 이미지로 저장하는 단순하고 무식한 방법을 사용합니다.

예를 들어, 어떤 애플리케이션을 이미지로 만든다면 리눅스만 설치된 컨테이너에 애플리케이션을 설치하고 그 상태를 그대로 이미지로 저장합니다. 가상머신의 스냅샷과 비슷한 방식입니다.

이런 과정은 콘솔에서 명령어를 직접 입력하는 것과 별 차이가 없으므로 쉘 스크립트를 잘 알아야 하지만 좋은 샘플이 많이 공개되어 있어 잘 몰라도 크게 걱정하지 않아도 됩니다. 또한 컨테이너의 가벼운 특성과 레이어 개념을 이용하여 생성과 테스트를 빠르게 수행할 수 있습니다.

이제 Ruby로 만들어진 간단한 웹 애플리케이션을 도커라이징Dockerizing(=도커 이미지를 만듦)해보겠습니다.

# Sinatra 웹 애플리케이션 샘플

일단 웹 애플리케이션 소스코드를 작성해야겠죠. Sinatra라는 가벼운 웹 프레임워크를 사용하기 위해 새로운 폴더를 만들고 Gemfile과 app.rb를 만듭니다.

Gemfile

source 'https://rubygems.org'
gem 'sinatra'

app.rb

require 'sinatra'
require 'socket'

get '/' do
  Socket.gethostname
end

ruby와 sinatra에 대해 전혀 모르더라도 Gemfile은 패키지를 관리하고 app.rb는 호스트명을 출력하는 웹 서버를 만들었다는 걸 예상할 수 있습니다.

이제 패키지를 설치하고 서버를 실행해보겠습니다.

bundle install            # install package
bundle exec ruby app.rb   # Run sinatra
~/Workspace/project/github.com/subicura/sinatra                                 
❯ bundle install                                                                
Using rack 1.6.4                                                                
Using tilt 2.0.6                                                                
Using bundler 1.14.3                                                            
Using rack-protection 1.5.3                                                     
Using sinatra 1.4.7                                                             
Bundle complete! 1 Gemfile dependency, 5 gems now installed.                    
Use `bundle show [gemname]` to see where a bundled gem is installed.            
~/Workspace/project/github.com/subicura/sinatra                                 
❯ bundle exec ruby app.rb                                                       
[2019-01-12 02:43:13] INFO  WEBrick 1.3.1                                       
[2019-01-12 02:43:13] INFO  ruby 2.3.0 (2015-12-25) [x86_64-darwin15]           
== Sinatra (v1.4.7) has taken the stage on 4567 for development with backup from
 WEBrick                                                                        
[2019-01-12 02:43:13] INFO  WEBrick::HTTPServer#start: pid=1593 port=4567  
::1 - - [01/Sat/2019:02:43:20 +0900] "GET / HTTP/1.1" 200 28 0.0036             
::1 - - [01/Sat/2019:02:43:20 KST] "GET / HTTP/1.1" 200 28                      
- -> /                                                                          
^C== Sinatra has ended his set (crowd applauds)                                 
[2019-01-12 02:43:23] INFO  going to shutdown ...                               
[2019-01-12 02:43:23] INFO  WEBrick::HTTPServer#start done. 

run-sinatra ruby가 설치되어 있지 않다고요? 도커만 있으면 문제없습니다. 다음 명령어를 실행합니다.

docker run --rm \
-p 4567:4567 \
-v $PWD:/usr/src/app \
-w /usr/src/app \
ruby \
shell script -c "bundle install && bundle exec ruby app.rb -o 0.0.0.0"
                                                                                
~/Workspace/project/github.com/subicura/sinatra                                 
❯ docker run --rm \                                                             
> -p 4567:4567 \                                                                
> -v $PWD:/usr/src/app \                                                        
> -w /usr/                                 
...

호스트의 디렉토리를 루비가 설치된 컨테이너의 디렉토리에 마운트한다음 그대로 명령어를 실행하면 로컬에 개발 환경을 구축하지 않고 도커 컨테이너를 개발환경으로 사용할 수 있습니다.

도커를 개발환경으로 사용하면 개발=테스트=운영이 동일한 환경에서 실행되는 놀라운 상황이 펼쳐집니다. 이 부분은 재미있는 내용이 많지만, 주제에서 벗어나므로 이 정도만 언급하고 다음 기회에 더 자세히 알아봅니다.

서버가 정상적으로 실행됐으면 웹 브라우저에서 테스트해봅니다. http://localhost:4567

도커 컨테이너의 호스트명이 보입니다. 소스는 잘 작성한 것 같네요! 이제 도커 이미지를 만들 준비가 완료됐습니다.

# Ruby Application Dockerfile

도커는 이미지를 만들기 위해 Dockerfile이라는 이미지 빌드용 DSLDomain Specific Language 파일을 사용합니다. 단순 텍스트 파일로 일반적으로 소스와 함께 관리합니다.

고급 개발자는 바로 Dockerfile을 만들 수도 있겠지만, 일반 개발자들은 일단 리눅스 서버에서 테스트로 설치해보고 안 되면 될 때까지 삽질하면서 최적의 과정을 Dockerfile로 작성해야 합니다. 우리는 초보니까 Ruby 웹 애플리케이션을 ubuntu에 배포하는 과정을 먼저 살펴보겠습니다.

순서

  1. ubuntu 설치
  2. ruby 설치
  3. 소스 복사
  4. Gem 패키지 설치
  5. Sinatra 서버 실행

이 과정을 그대로 쉘 스크립트로 옮겨봅니다.

# 1. ubuntu 설치 (패키지 업데이트)
apt-get update

# 2. ruby 설치
apt-get install ruby
gem install bundler

# 3. 소스 복사
mkdir -p /usr/src/app
scp Gemfile app.rb root@ubuntu:/usr/src/app  # From host

# 4. Gem 패키지 설치
bundle install

# 5. Sinatra 서버 실행
bundle exec ruby app.rb

ubuntu 컨테이너를 실행하고 위 명령어를 그대로 실행하면 웹 서버를 실행할 수 있습니다. 리눅스에서 테스트가 끝났으니 이 과정을 Dockerfile로 만들면 됩니다. 아직 자세한 명령어를 배우진 않았지만 일단 만들어 봅니다. 핵심 명령어는 파일을 복사하는 COPY와 명령어를 실행하는 RUN입니다.

# 1. ubuntu 설치 (패키지 업데이트 + 만든사람 표시)
FROM       ubuntu:16.04
MAINTAINER subicura@subicura.com
RUN        apt-get -y update

# 2. ruby 설치
RUN apt-get -y install ruby
RUN gem install bundler

# 3. 소스 복사
COPY . /usr/src/app

# 4. Gem 패키지 설치 (실행 디렉토리 설정)
WORKDIR /usr/src/app
RUN     bundle install

# 5. Sinatra 서버 실행 (Listen 포트 정의)
EXPOSE 4567
CMD    bundle exec ruby app.rb -o 0.0.0.0

쉘 스크립트의 내용을 거의 그대로 Dockerfile로 옮겼습니다. 차이점은 도커 빌드 중엔 키보드를 입력할 수 없기 때문에 (y/n)을 물어보는 걸 방지하기 위해 -y 옵션을 추가한 것 정도입니다.

빌드 파일을 작성했으니 이제 이미지를 만들어 봅니다.

Last Updated: 6/18/2023, 2:13:15 PM