深入淺出Docker(五):基于Fig搭建開發環境
1. 概述
在搭建開發環境時,我們都希望搭建過程能夠簡單,并且一勞永逸,其他的同事可以復用已經搭建好的開發環境以節省開發時間。而在搭建開發環境時,我們 經常會被復雜的配置以及重復的下載安裝所困擾。在Docker技術未出現之前,我們可以使用Pupet、Chef、Ansible等配置管理工具把復雜的 配置管理起來,這樣的管理配置技術仍然是目前比較流行的方式之一。配置管理工具使用的都是自己的DSL語法定義,考慮到環境的復雜性,配置一套通用的開發 環境需要針對各個系統定制,對于大部分開發環境這種維護成本仍然是很高的。Docker技術出現之后,系統的依賴問題得到了徹底的解決,我們可以通過鏡像 的方式簡化環境的安裝。結合Docker的開發部署工具Fig,我們可以使用fig.yml文件來定義所有的環境,一次定義,多處使用,簡單而且高效。
1.1 打包的方式
Docker本省并不能創建一個真實的虛擬機,它只是基于Linux Kernel把額外的系統文件做了封裝,并利用Linux Kernel相關的技術如Cgroup、Namespace隔離用戶應用。應用Docker技術,團隊之間通過共享Image或者Dockefile來復 用開發環境。為了簡化寫Dockerfile的方式 ,Fig提供更加精簡的DSL定義文件fig.yml,可以讓新成員快速搭建開發環境并將精力投入到開發過程中去,而不是研究如何正確安裝并配置諸如PostgreSQL之類的數據庫。目前,軟件開發需要的環境Image,大部分都可以在Docker Hub中搜索到,需要使用時直接下載就可以使用。
1.2 應用組合的方式
使用Docker之后,我們不再需要在本地機器安裝所有的軟件包。我們可以根據項目需要在Docker Hub上搜索相關軟件的Image,然后使用Fig pull從Docker Hub上直接下載并由Fig調用Docker的Link命令把Image關聯起來,這樣所有應用都可以直接調用指定端口的服務,比如Mysql的3306 端口提供數據庫服務。開發者并不需要對Docker有太多的了解,只需要掌握常用的幾條Fig命令就可以隨時調試自己的環境。
1.3 環境共享的方式
Fig直接定義好了Image,我們不需要過多的關心容器或者鏡像。在分享環境時,只需要把對應的Dockerfile和fig.yml文件分享給 同事,他們就可以在自己的機器上運行并搭建出需要的環境,且不用再擔心環境依賴帶來的意外調試煩惱。團隊成員在git clone項目代碼后,就可以如下圖一樣使用一條命令啟動自己的開發環境:
2. Fig安裝指南
首先,我們需要安裝Docker Engine,官方針對主流的系統提供了對應的安裝手冊。這里,我的開發機系統是一臺MacBook Pro,所以我需要安裝boot2docker來支持Docker。
接下來,我們就可以安裝對應系統版本的Fig運行文件。比如在Mac OS或者在64位的Linux上安裝Fig:
$ curl -L https://github.com/docker/fig/releases/download/1.0.0/fig-`uname -s`-`uname -m` > /usr/local/bin/fig; chmod +x /usr/local/bin/fig
當以上的安裝方式不能成功的話,我們可以選擇使用Python Package的安裝方式:
$ sudo pip install -U fig
最后,不管使用什么Linux系統,安裝完Fig之后通過運行以下命令來確保環境的一致性。
$ fig --version
如果一切順利的話,恭喜你,Fig安裝成功了。下面請隨我一起學習如何使用Fig配置開發環境。
3. Rails開發環境配置詳解
我們來配置一套最常用的Rails+PostgreSQL項目。
第一步,確保Fig已經正確的安裝到主機系統,如果還沒有,請參考上一章節的安裝指南。
第二步,在項目根目錄下存放一個名為 Dockerfile 文件:
FROM ruby RUN apt-get update -qq && apt-get install -y build-essential libpq-dev RUN mkdir /myapp WORKDIR /myapp ADD Gemfile /myapp/Gemfile RUN bundle install ADD . /myapp
第三步,創建一個 Gemfile 文件用來定義Rails軟件包。 內容如下所示:
source 'https://rubygems.org' gem 'rails', '4.0.2'
第四步,創建一個fig.yml文件,并使用以下配置文件來做最后的環境初始化。
db: image: postgres ports:- "5432"
web: build: . command: bundle exec rackup -p 3000 volumes:
- .:/myapp
ports:
- "3000:3000"
links:
- db</pre>
第五步,當前你目錄下空空如也,使用如下命令可以生成一套Rails項目骨架:
$ fig run web rails new . --force --database=postgresql --skip-bundle當你跑完以上命令,你就會得到一個嶄新的Rails項目。
$ ls Dockerfile Rakefile config fig.yml public vendor Gemfile app config.ru lib test README.rdoc bin db log tmp編輯一下Gemfile文件,去掉therubyracer包的注釋, 讓Rails依賴的Javascript的運行時環境。
gem 'therubyracer', platforms: :ruby所有的文件編輯都做完之后,運行命令創建開發環境image。
$ fig build運行完build命令后,我們就有了可以立即使用的Image。這兩個Image的名字分別是web和db。為了讓db能連上web,我們通常還需要修改database.yml來支持數據庫連接。
development: &default adapter: postgresql encoding: unicode database: postgres pool: 5 username: postgres password: host: db test: <<: *default database: myapp_test
好了,讓我們運行一下:
$ fig up命令行將顯示如下日志:
Recreating figtest_db_1... Creating figtest_web_1... Attaching to figtest_db_1, figtest_web_1 db_1 | LOG: database system was shut down at 2014-10-01 23:53:11 UTC db_1 | LOG: autovacuum launcher started db_1 | LOG: database system is ready to accept connections web_1 | [2014-10-01 23:53:16] INFO WEBrick 1.3.1 web_1 | [2014-10-01 23:53:16] INFO ruby 2.1.2 (2014-05-08) [x86_64-linux] web_1 | [2014-10-01 23:53:16] INFO WEBrick::HTTPServer#start: pid=1 port=3000 db_1 | FATAL: database "myapp_development" does not exist db_1 | FATAL: database "myapp_development" does not exist web_1 | 192.168.59.3 - - [01/Oct/2014 23:53:40] "GET / HTTP/1.1" 500 13476 0.5112 web_1 | 192.168.59.3 - - [01/Oct/2014 23:53:40] "GET %2Ffavicon.ico HTTP/1.1" 200 - 0.0067通過以上日志可以知道開發數據庫還沒有創建。這時我們可以開啟另外一個terminal,創建開發數據庫:
$ fig run web rake db:create當以上所有步驟都成功運行后,就需要來驗證開發環境的正確性了。通過訪問http://localhost:3000/ 我們應該可以看到熟悉的Rails歡迎頁面:
4. Django開發環境配置詳解
接下來讓我們使用Fig來配置一套運行Django/PostgreSQL的應用程序吧。
首先我們新建一個項目目錄,并在目錄里創建3個文件。第一個文件是Docker鏡像的定義文件: Dockerfile,用來描述安裝在Docker容器里軟件依賴關系。文件如下:
FROM python:2.7 ENV PYTHONUNBUFFERED 1 RUN mkdir /code WORKDIR /code ADD requirements.txt /code/ RUN pip install -r requirements.txt ADD . /code/以上文件描述這個Image將安裝requirements.txt指定的python依賴包。
第二個文件是requirements.txt,它是python依賴包定義描述文件,內容如下:
Django psycopg2最后,Fig需要把所有的環境都連接起來運行。這個文件名為 fig.yml 。它描述項目需要的服務組件、指定鏡像的版本、如何連接服務、什么卷可以被載入容器內部、什么端口可以暴露出來等。內容形如:
db: image: postgres web: build: . command: python manage.py runserver 0.0.0.0:8000 volumes:- .:/code
ports:
- "8000:8000"
links:
- db</pre>
到此處,我們就可以使用 fig run 來創建一個Django項目了:
$ fig run web django-admin.py startproject figexample .當你運行完之后,可以在當前目錄下看到創建的新項目文件:
$ ls Dockerfile fig.yml figexample manage.py requirements.txt接下來的事情就是創建數據庫鏈接,修改 figexample/settings.py 的DATABASES = ...部分。
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql_psycopg2', 'NAME': 'postgres', 'USER': 'postgres', 'HOST': 'db', 'PORT': 5432, } }這個配置信息是用來連接postgres鏡像服務。
然后,運行命令 fig up來啟動容器。
Recreating myapp_db_1... Recreating myapp_web_1... Attaching to myapp_db_1, myapp_web_1 myapp_db_1 | myapp_db_1 | PostgreSQL stand-alone backend 9.1.11 myapp_db_1 | 2014-01-27 12:17:03 UTC LOG: database system is ready to accept connections myapp_db_1 | 2014-01-27 12:17:03 UTC LOG: autovacuum launcher started myapp_web_1 | Validating models... myapp_web_1 | myapp_web_1 | 0 errors found myapp_web_1 | January 27, 2014 - 12:12:40 myapp_web_1 | Django version 1.6.1, using settings 'figexample.settings' myapp_web_1 | Starting development server at http://0.0.0.0:8000/ myapp_web_1 | Quit the server with CONTROL-C.這個時候,你可以開啟瀏覽器,然后輸入 localhost:8000 就可以訪問這個Django應用。
注意,當你跑起來應用之后,就可以初始化數據庫了。這里,請一定要保證fig up是在運行中,并另外開啟一個命令行窗口執行一下命令:
$ fig run web python manage.py syncdb如果你反復使用了fig up之后,可以體會到它一次性會把web和db兩個鏡像一起啟動,如果你CONTROL-C之后,數據庫也會停止服務。你甚至可以fig run web /bin/bash的方式直接進入到容器里看看。
5. Wordpress開發環境配置詳解
Fig一樣可以應付PHP應用的開發需求。
首先,創建一個Dockerfile來支持生成開發用Image。
$ curl https://wordpress.org/latest.tar.gz | tar -xvzf -以上這條命令創建名為 wordpress 的目錄。進入到此目錄,創建鏡像文件 Dockerfile,內容如下:
FROM stackbrew/ubuntu:13.10 RUN apt-get update && apt-get install php5 php5-mysql -y ADD . /code下一步創建 fig.yml,它將定義出web服務和mysql db服務。
web: build: . command: php -S 0.0.0.0:8000 -t /code ports:- "8000:8000"
links:
- db
volumes:
- .:/code
db: image: mysql environment: MYSQL_DATABASE: wordpress MYSQL_ROOT_PASSWORD: wordpress</pre>
wordpress有一個支持文件需要修改,它是wp-config.php:
<?php define('DB_NAME', 'wordpress'); define('DB_USER', 'root'); define('DB_PASSWORD', 'wordpress'); define('DB_HOST', getenv("DB_1_PORT_3306_TCP_ADDR") . ":" . getenv("DB_1_PORT_3306_TCP_PORT")); define('DB_CHARSET', 'utf8'); define('DB_COLLATE', '');define('AUTH_KEY', 'put your unique phrase here'); define('SECURE_AUTH_KEY', 'put your unique phrase here'); define('LOGGED_IN_KEY', 'put your unique phrase here'); define('NONCE_KEY', 'put your unique phrase here'); define('AUTH_SALT', 'put your unique phrase here'); define('SECURE_AUTH_SALT', 'put your unique phrase here'); define('LOGGED_IN_SALT', 'put your unique phrase here'); define('NONCE_SALT', 'put your unique phrase here');
$tableprefix = 'wp'; define('WPLANG', ''); define('WP_DEBUG', false);
if ( !defined('ABSPATH') ) define('ABSPATH', dirname(FILE) . '/');
require_once(ABSPATH . 'wp-settings.php');</pre>
以上三個文件都修改后,就可以在此目錄下運行 fig up來啟動wordpress。可以使用瀏覽器訪問localhost:8000 瀏覽Wordpress首頁。
6. 結論
通過Fig來構建基于Docker的開發環境可以讓我們的開發事半功倍。其實如果讀者按照我的步驟一步一步搭建開發環境,仍然會有很多挑戰。
首先,因為國內帶寬的限制,從官方下載Image是一個長時間等待的過程。即使Docker公司已經使用了CDN服務,但在國內網絡使用仍然很慢。為了能快速下載,我還常備一條V*N線路作為數據通道來下載Image。目前這是最理想的方式,可以節省很多開發時間。
第二,fig up并不能保證Image能一次成功。但不需要灰心。你可以fig run web /bin/bash直接到容器里面調試。我遇到過多次費解的問題都是直接在里面跑命令解決的。當你退出時,fig會自動更新到相應的Image里。當你再 次fig up,它會使用新Image去創建這個運行容器。
第三,fig up會創建兩個以上的容器實例,在退出容器后再次啟動fig up,并不會重用之前退出的容器實例,而是新建容器實例。像fig up這類常用命令運行多次之后會導致過期的容器文件仍然存儲在你的開發機器上并占用硬盤空間,并且Fig還沒有提供對應的命令自動清理它們。目前可以解決 的辦法是直接使用Docker rm/rmi命令手工清除。
以上總結出的實戰經驗,仍然不能掩蓋Fig特有的亮點:運用Fig可以定義統一運行步驟,讓部署環境可以完全的隔離在一個獨立的容器環境里,并且這 個隔離環境可以在開發、測試、生產多個步驟中保持一致。當前Fig項目還很年輕,需要大家多參與項目的討論,提出自己的問題才能讓Fig更好使用,更多信 息可以到這里查閱。
7. 作者簡介
肖德時, Red Hat Engineering Service/HSS 內部工具組Team Leader。Nodejs開源項目nodejs-cantas Lead Developer。擅長企業內部工具的設計以及實現。開源課程Rails Starter的發起人。rubygem: lazy_high_charts的Maintainer。推ter賬號:xds2000,郵箱:xiaods@gmail.com
8.下期預告
Docker引擎可以在多臺主機上啟動成千上百的實例,那么如何管理這些容器實例顯然會成為一個挑戰。所以下期我將給大家介紹一款非常出色的容器集群管理框架Kubernetes,敬請期待!
來自:http://www.infoq.com/cn/articles/docker-build-development-environment-based-on-fig?utm_source=infoq&utm_medium=related_content_link&utm_campaign=relatedContent_articles_clk