1. 程式人生 > >如何應用Docker?簡明教程告訴你

如何應用Docker?簡明教程告訴你

Docker已經迅速發展了一段時間,不少同學可能都在對Docker的應用,實際的應用,解決開發和運營中的實際問題,如何應用Docker,對docker能做什麼有了更多的需求,為此,我整理了一份 Docker應用教程 ,致力提供更多的 Docker應用案例和問題解決。初學的同學還請有先按本文了解docker的基本操作。

Docker 是個容器,像個碗或者盆,其實更像個櫥櫃 帶格子的那種.

你可以把喜歡的東西放在各種各種的格子裡,然後不管櫥櫃搬到哪,就你在裡面放置的好玩意不會變。

這樣你就可以輕鬆的在ubuntu上執行一個centos

下面是老外做的一個不是很直觀也能看明白的直觀圖,對比docker和VM的不同:

docker

這裡有映象可以下載 these slides(link is external) 都是Docker提供的(不足最近github的訪問速度是真xxx,隨意最好找找有沒有代理加快下載,如果對docker不瞭解,還是要謹慎一些,二次釋出的映象,也許會有問題).

獲取docker

docker對mac支援不是很好,可以用boot2docker(link is external)來解決.老外推薦使用CoreOs來操作Vagrant(這又是一個神器,將來會陸續在我的網站出現,請持續關注)

老外在這裡強烈推薦CoreOS,說怎麼怎麼好,我還是推薦先使用ubuntu或者在windows上裝個vbox在用ubuntu,coreos作為一個新型的伺服器級別的系統,也十分值得關注,因為CoreOs將作為主力的docker容器發展。

下面這一段是老外將他在CoreOS安裝docker的事,主要是 Vagrantfile (這是一個Vagrant可以識別的配置檔案):

config.vm.box ="coreos"
config.vm.box_url ="http://storage.core-os.net/coreos/amd64-generic/dev-channel/coreos_production_vagrant.box"
config.vm.network "private_network",
        ip:"172.12.8.150"

如果使用NFS 就加下面一段:
# This will require sudo access when using "vagrant up"
config.vm.synced_folder ".","/home/core/share",
    id:"core",:nfs =>true,:mount_options =>['nolock,vers=3,udp']
如果使用vmware不使用virtualbox:
config.vm.provider :vmware_fusion do|vb,override|override.vm.box_url ="http://storage.core-os.net/coreos/amd64-generic/dev-channel/coreos_production_vagrant_vmware_fusion.box"end

最好要加上一個外掛:
# plugin conflictifVagrant.has_plugin?("vagrant-vbguest")then
    config.vbguest.auto_update =falseend

如果在CoreOS上操作過程中,提示重啟,請不要擔心,這是為了啟用特性所做的操作

下面為docker正式內容

你的第一個容器

第一步嘗試是必須的,雖然你可能不是直接發現docker的強大,但是足以“管中窺豹”(這老外比我都羅嗦)

docker有一些基礎的容器,也接受民間提供製作好的容器,以後你如果想貢獻,也可以在這裡 index.docker.io(link is external) 釋出自己的容器.

最流行最基礎的Docker映象還是“Ubuntu”

如果沒有這個映象,那麼需要下載~

Run Bash:

docker run ubuntu /bin/bash
什麼事情都沒有發生! 哈哈, 實際上已經有東西運行了. 執行 docker ps (像在linux主機上執行 ps) – 你什麼容器也看不到,一個程序都沒有(這老外~尼瑪). Run docker ps -a, 見證奇蹟的時刻!

CONTAINER ID    IMAGE           COMMAND         CREATED              STATUS      PORTS       NAMES
8ea31697f021    ubuntu:12.04/bin/bash       About a minute ago   Exit0                  loving_pare

我們已經可以看到一個在執行的 /bin/bash, 但是沒有任何程序在維持它的執行.一個docker容器是伴隨程序執行的.

先記住上面說的. 讓我們繼續操作docker,來玩一會兒:

docker run -t -i ubuntu /bin/bash

現在你可以看到你已經以root的身份登入到了docker 容器!

這些命令都在做什麼?

  • docker run – 執行一個容器
  • -i – 開發輸入(so we can interact with it)
  • ubuntu – 使用ubuntu基礎映象
  • /bin/bash – 執行bash shell

跟進改變

使用 (ctrl+d or type exit) 來退出然後繼續執行 docker ps -a . :

CONTAINER ID    IMAGE           COMMAND         CREATED              STATUS      PORTS       NAMES
30557c9017ec    ubuntu:12.04/bin/bash       About a minute ago   Exit127                elegant_pike
8ea31697f021    ubuntu:12.04/bin/bash       22 minutes ago       Exit0                  loving_pare

複製貼上現在執行的容器 ID (30557c9017ec in my case). 執行docker diff <container id>. :

[email protected] ~ $ docker diff 30557c9017ec
A /.bash_history
C /dev
A /dev/kmsg

我們可以看到我們僅僅登入了 bash之後的改變,建立了  .bash_history file, a /dev directory and a/dev/kmsg file. 這是細微的變化,確實偉大的存在! Docker 會跟蹤我們在容器中的所有改動. 事實上,docker就是執行我們創造改動,提交改動,釋出改動,然後將改變帶到任何地方. 這就是我們使用docker所依賴的基礎.

下面我們就來安裝點新玩意到容器中,讓把它們打包成我們自己的.

# Get into Bash
docker run -t -i ubuntu /bin/bash

# Install some stuff
apt-get update
apt-get install -y git ack-grep vim curl wget tmux build-essential python-software-properties

等這些都執行完了之後,退出,再執行 docker ps -a . 在複製最新的ID (docker diff <Container ID>):

[email protected] ~ $ docker diff 5d4bdae290a4> A TON OF FILE LISTED HERE

當然又有很多的新檔案被新增. 下面我們就來打包我們的版本,為了以後更好的使用.我們將提交修改,給它命名並打上標籤。 我們將使用: docker commit <Container ID> <Name>:<Tag>

[email protected] ~ $ docker commit 5d4bdae290a4 fideloper/docker-example:0.1
c07e8dc7ab1b1fbdf2f58c7ff13007bc19aa1288add474ca358d0428bc19dba6  # You'll get a long hash as a Success message

我們來看看我們打包好的映象. Run docker images:

[email protected] ~ $ docker images

REPOSITORY                 TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
fideloper/docker-example   0.1                 c07e8dc7ab1b        22 seconds ago      455.1 MB
ubuntu                     13.109f676bd305a46 weeks ago         178 MB
ubuntu                     saucy               9f676bd305a46 weeks ago         178 MB
ubuntu                     13.04               eb601b8965b8        6 weeks ago         166.5 MB
ubuntu                     raring              eb601b8965b8        6 weeks ago         166.5 MB
ubuntu                     12.105ac751e8d6236 weeks ago         161 MB
ubuntu                     quantal             5ac751e8d6236 weeks ago         161 MB
ubuntu                     10.049cc9ea5ea5406 weeks ago         180.8 MB
ubuntu                     lucid               9cc9ea5ea5406 weeks ago         180.8 MB
ubuntu                     12.049cd978db300e6 weeks ago         204.4 MB
ubuntu                     latest              9cd978db300e6 weeks ago         204.4 MB
ubuntu                     precise             9cd978db300e6 weeks ago         204.4 MB

你已經注意到了那麼多的ubuntu啊. 當我第一次載入使用ubuntu基礎映象的時候,就已經載入相應的ubuntu標記,更多知識請瀏覽 Docker index(link is external).

非常有趣,不管怎樣我們已經用了自己的映象 叫做 fideloper/docker-example 並且有個版本標籤0.1!

使用 Dockerfile 建立一個伺服器

讓我們使用Dockerfile來建立一個伺服器,大概就是通過一個配置檔案,讓git和wget自動的完成這個伺服器環境的搭建工作.

建立一個目錄,然後cd進去,因為我們要使用nginx伺服器,就需要有個預設的配置檔案.

建立一個叫做 default 的配置檔案:

server {
    root /var/www;
    index index.html index.htm;# Make site accessible from http://localhost/
    server_name localhost;

    location /{# First attempt to serve request as file, then# as directory, then fall back to index.html
        try_files $uri $uri//index.html;}}

這就是nginx的基礎配置了.

下面我們建立一個 Dockerfile 並新增如下內容, 修改映象FROM為我們自己的映象(多麼happy):

FROM fideloper/docker-example:0.1

RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe">/etc/apt/sources.list
RUN apt-get update
RUN apt-get-y install nginx

RUN echo "daemon off;">>/etc/nginx/nginx.conf
RUN mkdir /etc/nginx/ssl
ADD default/etc/nginx/sites-available/default

EXPOSE 80

CMD ["nginx"]

這些東西有都是什麼的?

  • FROM 告訴docker使用哪個映象,用什麼版本
  • RUN 以root使用者身份來執行linux命令
  • ADD 複製檔案到容器內
    • 這是一個非常方便來管理配置檔案的方式
  • EXPOSE 暴露埠給主機,也可以新增更多的埠比如: EXPOSE 80 443 8888
  • CMD 執行一個命令 (但不是以 sh -c). 這通常是來執行長時間的程序,但是我們只是來啟動nginx.
    • 在生產環境中,我們想看到nginx在執行失敗的情況下的表現

儲存好這些,讓我們來build一個新映象

docker build -t nginx-example .

如果它正常工作了並結束 Successfully built 88ff0cf87aba (這個容器ID並不一定都是一樣的).

檢查一下你有獲得的什麼映象 docker images:

[email protected] ~/webapp $ docker images
REPOSITORY                 TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
nginx-example              latest              88ff0cf87aba35 seconds ago      468.5 MB
fideloper/docker-example   0.1                 c07e8dc7ab1b        29 minutes ago      455.1 MB
...other Ubuntu images below ...

再執行一下 docker ps -a:

[email protected] ~/webapp $ docker ps -a
CONTAINER ID        IMAGE                   COMMAND                CREATED              STATUS    PORTS    NAMES
de48fa2b142b        8dc0de13d8be/bin/sh -c #(nop) CM   About a minute ago   Exit 0             cranky_turing84c5b21feefc2eb367d9069c/bin/sh -c #(nop) EX   About a minute ago   Exit 0             boring_babbage3d3ed53987ec77ca921f5eef/bin/sh -c #(nop) AD   About a minute ago   Exit 0             sleepy_brattain
b281b7bf017f        cccba2355de7            /bin/sh -c mkdir /et   About a minute ago   Exit0             high_heisenberg
56a84c7687e9        fideloper/docker-e.../bin/sh -c #(nop) MA   4 minutes ago        Exit 0             backstabbing_turing... other images ...

你可以看到 每一行Dockerfile中的指令, 一個新的容器已經誕生 if that line results in a change to the image used. Similar(ish) to version control! (Also, how funny is the name “backstabbing_turing”?)(這一段很難明白?難道又是老外在用,英語文化開玩笑,希望給個指點)

最後,執行這個web服務

讓我們來執行web伺服器! 使用 docker run -p 80:80 -d nginx-example (確定你要使用的名稱).

-p 80:80 經容器的80埠 繫結到了主機上 通過curl localhost 或者訪問主機ip就可以看到執行的狀態  [email protected] ~/webapp $ docker run -d nginx-example
73750fc2a49f3b7aa7c16c0623703d00463aa67ba22d2108df6f2d37276214cc# Success!

[email protected] ~/webapp $ docker ps
CONTAINER ID        IMAGE                  COMMAND    CREATED          STATUS         PORTS     NAMES
a085a33093f4        nginx-example:latest   nginx      2 seconds ago    Up2 seconds   80/tcp    determined_bardeen

現在我們使用 docker ps 而不是 docker ps -a – 我們可以看到容器中正在執行的程序(回想最初的命令). 執行 curl localhost:

[email protected] ~/webapp $ curl localhost/index.htmld <html><head><title>500InternalServerError</title></head><body bgcolor="white"><center><h1>500InternalServerError</h1></center><hr><center>nginx/1.1.19</center></body></html>

我們看到了nginx的迴應,但是是500錯誤. 這是因為我們並沒有一個index.html 資原始檔讓nginx返回. 讓我們停止這個容器的執行 docker stop <container id>:

[email protected] ~/webapp $ docker stop a085a33093f4
a085a33093f4

來解決一下這個問題,我們來共享一個目錄在主機和容器之間,這樣就用個index.html了,首先建立一個index.html在我們想要貢獻的目錄中

# I'm going to be sharing the /home/core/share directory on my CoreOS machine
echo "Hello, Docker fans!">>/home/core/share/index.html

然後我們再啟動這個容器(注意命令):

docker run -v /home/core/share:/var/www:rw -p 80:80 -d nginx-example
  • docker run – 啟動容器
  • -v /path/to/host/dir:/path/to/container/dir:rw – 指定一個目錄共享到容器,並且指定許可權為讀寫,也可以指定為只讀
  • -p 80:80 – 繫結埠.
  • -d nginx-example 啟動nginx-example的容器,由於在配置檔案的CMD中已經指定啟動了 nginx ,在容器啟動時nginx即啟動

執行 curl localhost:

[email protected] ~/webapp $ curl localhost
Hello,Docker fans!

…或者直接訪問主機ip

注意這個ip是主機的ip. 我已經在 Vagrantfile  中指定了ip。我不需要知道要轉發的ip究竟是什麼? 當時可以通過這個命令來看到 docker inspect <Container ID>.

[email protected] ~/webapp $ docker inspect a0b531aa00f4
[{"ID":"a0b531aa00f475b0025d8edce09961077eedd82a190f2e2f862592375cad4dd5","Created":"2014-03-20T22:38:22.452820503Z",... a lot of JSON ..."NetworkSettings":{"IPAddress":"172.17.0.2","IPPrefixLen":16,"Gateway":"172.17.42.1","Bridge":"docker0","PortMapping":null,"Ports":{"80/tcp":[{"HostIp":"0.0.0.0","HostPort":"80"}]}},... more JSON ...}]

連結不同的容器

現在已經可以將多個容器聯合在一起了 。能將容器聯合在一起,是一項非常重要的技能. 舉個例子, 比如你的web容器想要連結你的資料庫容器. 連結可以讓多個分支應用,獨立於你的應用。

舉個例子:

啟動一個容器,並且取個有意義點的名字 (在這裡就叫, mysql):

docker run -p 3306:3306-name mysql -d some-mysql-image

啟動你的web容器 將它和另外一個容器連結在一起 -d name:db (where db is an arbitrary name used in the container’s environment variables):

docker run -p 80:80-link mysql:db -d some-application-image

在例子中, some-application-image 有這樣的環境變數設定DB_PORT_3306_TCP_ADDR=172.17.0.8 and DB_PORT_3306_TCP_PORT=3306 用於在應用中的設定

結論

我們就是可以這麼簡單的來建立一臺伺服器,新增應用程式碼,控制應用。執行環境中的每一件事都在你的掌控之中

通過這種方式,我們可以 跳過複雜的環境設定,專心於自己的程式碼.

P.S. – Tips and Tricks

 如果執行完了這次體驗,你想自己做點什麼,並且清理掉之前的docker 容器:

  • 刪除容器r: docker rm <Container ID>
  • 刪除所有容器: docker rm $(docker ps -a -q)
  • 移除映象: docker rmi <Container ID>
  • 移除所有映象: docker rmi $(docker ps -a -q)

Note: 在移除映象前,你必須刪除掉,所有依賴於該映象的容器

加入你已經完整體驗了上面的教程,那麼就已經對docker有了很系統的瞭解,因為docker 無非就是用來構建一個可移植環境,為了能有進一步的提高,推薦進行下面的學習:

  • docker操作命令,主要熟悉一個常用的操作,docker的命令不多,基本上都會用到,推薦:docker命令詳解
  • Dockerfile的編寫,用於建立一個屬於自己的定製化的docker image映象,docker建立映象很簡單,主要是要能夠編寫Dockerfile進行定製,推薦:Dockerfile說明文件

來源:簡果網

連結:http://www.simapple.com/303.html