這是本系列的第三篇,整個系列介紹了咱們公司如何把基礎框架從PaaS移植到Docker上。
node
在這最後一篇,咱們用一個真實的例子來介紹如何自動化整個部署過程。
web
咱們來進入主題並啓動一個基本的Rails應用。在這個Demo中,我將使用Ruby 2.20 和Rails 4.11。
在終端中運行:
sql
$ rvm use 2.2.0 $ rails new && cd docker-test
而後咱們來建立個基本的控制器:
docker
$ rails g controller welcome index
而後修改routes.rb
文件,使這個項目的根路徑指向咱們剛建立的welcome#index
方法:
shell
root 'welcome#index'
在終端執行 rails s
來啓動服務並打開http://localhost:3000
就能夠看到首頁了。咱們不許備作其它功能了,這只是個例子來證實咱們能夠建立並在容器裏部署且正常工做。
安全
咱們將用Unicorn作咱們的webserver。添加gem 'unicorn'
和gem 'foreman'
到Gemfile而後安裝它們(在終端執行bundle install
)。
Unicorn 須要在Rails應用啓動前配置,咱們須要在config文件夾中放入unicorn.rb配置文件。這裏有個關於Unicorn的配置的例子。你能夠直接複製粘貼這個Gist的內容。
而後咱們添加包含下面內容的Procfile到項目的根目錄下,這樣咱們就能夠用foreman來啓動項目了:
ruby
web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb
若是你用foreman start
來運行應用,它也能正常工做而且能夠在http://localhost:5000
上進行訪問。
服務器
接下來咱們來建立運行應用的鏡像文件。在Rails項目的根目錄建立個Dockerfile文件,並把下面的內容貼進去:
# Base image with ruby 2.2.0 FROM ruby:2.2.0 # Install required libraries and dependencies RUN apt-get update && apt-get install -qy nodejs postgresql-client sqlite3 --no-install-recommends && rm -rf /var/lib/apt/lists/* # Set Rails version ENV RAILS_VERSION 4.1.1 # Install Rails RUN gem install rails --version "$RAILS_VERSION" # Create directory from where the code will run RUN mkdir -p /usr/src/app WORKDIR /usr/src/app # Make webserver reachable to the outside world EXPOSE 3000 # Set ENV variables ENV PORT=3000 # Start the web app CMD ["foreman","start"] # Install the necessary gems ADD Gemfile /usr/src/app/Gemfile ADD Gemfile.lock /usr/src/app/Gemfile.lock RUN bundle install --without development test # Add rails project (from same dir as Dockerfile) to project directory ADD ./ /usr/src/app # Run rake tasks RUN RAILS_ENV=production rake db:create db:migrate
利用上面提供的Dockerfile,經過下面的命令進行建立鏡像:
$ docker build -t localhost:5000/your_username/docker-test .
若是一切順利,在長長的日誌的最後能看到以下信息:
Successfully built 82e48769506c $ docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE localhost:5000/your_username/docker-test latest 82e48769506c About a minute ago 884.2 MB
試試運行這個容器:
$ docker run -d -p 3000:3000 --name docker-test localhost:5000/your_username/docker-test
如今應該能夠用經過Boot2Docker虛擬機的3000端口來訪問這個應用了(例如個人:http://192.168.59.103:3000)。
經過本系列的第二篇,你應該已經瞭解如何發佈剛纔新建立的鏡像到私有registry並部署在一個機器上了,咱們跳過這一部分直接討論如何自動化這個過程。
接下來將定義3個shell腳本,而後用rake將他們捆綁在一塊兒執行。
每次咱們建立鏡像並部署時,最後把全部的東西都清除掉。主要包括:
中止(若是已經運行),而後重啓Boot2Docker
移除孤立的Docker鏡像(那些沒有標籤而且再也不使用的容器)
把以下的clean.sh腳本文件放在項目的根目錄。
echo Restarting boot2docker... boot2docker down boot2docker up echo Exporting Docker variables... sleep 1 export DOCKER_HOST=tcp://192.168.59.103:2376 export DOCKER_CERT_PATH=/Users/user/.boot2docker/certs/boot2docker-vm export DOCKER_TLS_VERIFY=1 sleep 1 echo Removing orphaned images without tags... docker images | grep "<none>" | awk '{print $3}' | xargs docker rmi
而後給這個文件可執行權限:
$ chmod +x clean.sh
建立的過程基本上是前面的步驟重作一遍。建立一個build.sh文件在項目的根目錄,而後把下面內容貼進去:
docker build -t localhost:5000/your_username/docker-test .
記得給它可執行權限。
最後,來建立以下內容的deploy.sh文件:
# Open SSH connection from boot2docker to private registry boot2docker ssh "ssh -o 'StrictHostKeyChecking no' -i /Users/username/.ssh/id_boot2docker -N -L 5000:localhost:5000 root@your-registry.com &" & # Wait to make sure the SSH tunnel is open before pushing... echo Waiting 5 seconds before pushing image. echo 5... sleep 1 echo 4... sleep 1 echo 3... sleep 1 echo 2... sleep 1 echo 1... sleep 1 # Push image onto remote registry / repo echo Starting push! docker push localhost:5000/username/docker-test
若是你對這部分有疑惑,請確認你已經理解了本系列的第二篇文章的相關部分。
一樣,記得給這個文件可執行權限。
將這3個腳本分開依次執行:
clean
build
deploy/push
因爲開發者都是比較懶的,因此這會是一個很大的幫助。
最後一步是將這些打包起來,也就是用rake將三部分合在一塊兒。
爲了簡單,你能夠將這一堆代碼直接粘貼在項目根目錄下的Rakefile後面。打開Rakefile文件,而後把這些粘貼在最後:
namespace :docker do desc "Remove docker container" task :clean do sh './clean.sh' end desc "Build Docker image" task :build => [:clean] do sh './build.sh' end desc "Deploy Docker image" task :deploy => [:build] do sh './deploy.sh' end end
儘管你可能不懂這些rake的語法(它們真的很棒!),可是咱們這麼作的目的很明顯。咱們在Docker命名空間下聲明瞭3個任務。他們會建立如下3個任務:
rake docker:clean
rake docker:build
rake docker:deploy
Deploy是依賴build的,而build依賴於clean,因而每次咱們從終端這麼執行:
$ rake docker:deploy
這樣,3個腳本就都會被按順序執行。
爲了驗證它們能夠正常工做,你只須要在應用的代碼中作一點小的改動,而後執行:
$ rake docker:deploy
而後來看看結果。一旦鏡像被上傳(初次執行會比較慢),你能夠SSH進入你的生產環境服務器,而後pull(用SSH隧道)Docker鏡像並執行它。這很是簡單。
好吧,可能它花了一些功夫來讓全部的組成部分工做起來,可是一旦完成,在Heroku上部署的工做就變得很是簡單。
P.S. 跟之前同樣,請讓我知道你的想法。我不肯定這是最好的或者是最快的或者是最安全的方案來用Docker部署應用,可是咱們確實是這麼用它的。
確認Boot2Docker啓動並在運行。
若是你不知道你的Boot2Docker虛擬機的IP,執行boot2docker ip
。
若是你忘了如何用私有registry,請看本系列第二篇。