Docker入門,看這篇就夠了

Docker是怎麼出現的

關於Docker的發展史,本文就不作介紹,有興趣的小夥伴們能夠查看這篇文章,挺有意思的。http://www.oschina.net/news/5...css

什麼是Docker?

  在Docker以前,咱們確定要先了解Docker是什麼。官網的介紹是「Docker is the world’s leading software container platform.」官方給Docker的定位是一個應用容器平臺。至於爲何要作這個Docker,官網上還有這麼一句話"Docker is an open platform for developers and sysadmins to build, ship, and run distributed applications, whether on laptops, data center VMs, or the cloud."這句話用一句很是簡單的話去歸納就是"Build once,Run anyWhere".這一點跟Java很像。那麼它這樣作是要解決現實中什麼問題,我列舉幾個狀況。
   1.合做開發的時候,在本機能夠跑,別人的電腦跑不起來
   這裏咱們拿java Web應用程序舉例,咱們一個java Web應用程序涉及不少東西,好比jdk、tomcat、spring等等。當這些其中某一項版本不一致的時候,可能就會致使應用程序跑不起來這種狀況。Docker則將程序直接打包成鏡像,直接運行在容器中便可。
   2.服務器本身的程序掛了,結果發現是別人程序出了問題把內存吃完了,本身程序由於內存不夠就掛了
  這種也是一種比較常見的狀況,若是你的程序重要性不是特別高的話,公司基本上不可能讓你的程序獨享一臺服務器的,這時候你的服務器就會跟公司其餘人的程序共享一臺服務器,因此不可避免地就會受到其餘程序的干擾,致使本身的程序出現問題。Docker就很好解決了環境隔離的問題,別人程序不會影響到本身的程序。
  3.公司要弄一個活動,可能會有大量的流量進來,公司須要再多部署幾十臺服務器
  在沒有Docker的狀況下,要在幾天內部署幾十臺服務器,這對運維來講是一件很是折磨人的事,並且每臺服務器的環境還不必定同樣,就會出現各類問題,最後部署地頭皮發麻。用Docker的話,我只須要將程序打包到鏡像,你要多少臺服務,我就給力跑多少容器,極大地提升了部署效率。前端

Docker與虛擬機的區別

關於Docker與虛擬機的區別,我在網上找到的一張圖,很是直觀形象地展現出來,話很少說,直接上圖。java

圖片描述

圖片描述

  比較上面兩張圖,咱們發現虛擬機是攜帶操做系統,自己很小的應用程序卻由於攜帶了操做系統而變得很是大,很笨重。Docker是不攜帶操做系統的,因此Docker的應用就很是的輕巧。另外在調用宿主機的CPU、磁盤等等這些資源的時候,拿內存舉例,虛擬機是利用Hypervisor去虛擬化內存,整個調用過程是虛擬內存->虛擬物理內存->真正物理內存,可是Docker是利用Docker Engine去調用宿主的的資源,這時候過程是虛擬內存->真正物理內存。node

Docker安裝

  Docker的安裝很是簡單,官網上都給出了具體的安裝步驟,都是可視化的安裝,三步就搞定了。這裏我就不細說了,附上Docker的官網安裝教程地址。
Mac:https://docs.docker.com/docke...
Windows:https://docs.docker.com/docke...
linux的話,官網有不一樣版本的安裝的教程,這裏放上ubuntu的安裝教程,其餘小夥們自行查看。
ubuntu:https://docs.docker.com/engin...linux

Docker三個基本概念

  下面這張圖很是的經典,很形象地展現了,什麼是容器,什麼是鏡像,什麼是倉庫,以及三者之間的聯繫。
圖片描述spring

  接下來咱們來解釋一下這張圖。如今咱們要造一間廚房,在造以前咱們首先要乾的一件事,就是先列舉出咱們造廚房須要的東西。咱們可能須要一個通了水電煤的房子以及一些必需的廚房用具諸如鍋碗瓢勺、煤氣竈、冰箱、水槽等等這些東西。如今咱們知道須要了什麼東西以後,咱們就去找這些東西。首先咱們先去京東購買一些廚房用具,這些用具就比如咱們的Docker鏡像,咱們廚房的用具到了以後得找個地方把它們放在,不可能隨處丟吧,否則後面用的時候就找不到它了,那麼咱們Docker鏡像也是這樣,須要一個Docker倉庫去存儲這些鏡像。如今咱們有了這些廚房用具以後就能夠作飯了嗎?答案固然是不能,沒水沒電沒火啊!這時候咱們得把廚房用具給裝到一個通了水電煤的房子才行,那麼Docker鏡像也是這樣,單純的Docker鏡像是不能用的,它得裝到Docker容器中通了水電煤才能使用。等咱們裝好了廚房用具以後咱們就能夠開始作飯,那麼咱們的Docker鏡像裝到Docker容器以後,咱們應用就能夠跑起來了。docker

個人第一個Docker鏡像

上面的文章中,咱們瞭解了一下Docker,接下來咱們學着作一個屬於本身的Docker鏡像。shell

第一步:從鏡像中心下載一個Node鏡像

a).去http://hub.daocloud.io/上找到Node鏡像地址並執行以下命令
      docker pull daocloud.io/library/node:標籤
    b).查看本地庫的Docker鏡像,是否下載完成
      docker images

結果以下:
圖片描述數據庫

第二步:寫一個app.js

app.js的內容以下,內容很簡單,做用也很簡單,起一個80端口的服務,頁面顯示「Hello Docker」。express

var http = require('http');

http.createServer(function (request, response) {

    // 發送 HTTP 頭部
    // HTTP 狀態值: 200 : OK
    // 內容類型: text/plain
    response.writeHead(200, {'Content-Type': 'text/plain'});

    // 發送響應數據 "Hello World"
    response.end('Hello Docker\n');
}).listen(3000);

// 終端打印以下信息
console.log('Server running at http://127.0.0.1:3000/');

第三步:寫一個Dockerfile,用於構建鏡像

#依賴的鏡像
FROM daocloud.io/library/node:latest
#鏡像建立者的信息
MAINTAINER wuming "wuming@maihaoche.com"
#執行mkdir helloDocker建立一個helloDocker文件夾
RUN mkdir helloDocker
#將app.js添加到helloDocker文件夾中
ADD app.js  helloDocker
#容器運行時啓動的命令,下面命令等價於 CMD node /helloDocker/app.js
CMD ["node","/helloDocker/app.js"]

第四步:執行命令,構建對象

docker build -t hello-docker .
//-t 用於指定鏡像的name:tag,沒有指定tag則是latest。
//. 表明Dockerfile 所在的路徑,這裏是當前目錄

結果以下:
圖片描述

若是鏡像倉庫或者標籤錯了的話,可使用以下命令進行修改

    docker tag IMAGE ID name:tag
   例: docker tag 1786dad83d25 hello-docker:1.0.0

結果以下:
圖片描述
這裏須要注意的是「docker tag」是新建一個標籤用於目標鏡像指向源鏡像,因此咱們記得刪除原來的標籤

docker rmi name:tag
例:docker rmi hello-docker:latest

圖片描述

舒適提示:當前目錄應該有Dockerfile和app.js纔可用上面命令構建成功
圖片描述

個人第一個Docker容器

docker run  -d -p 8003:3000 IMAGE ID

注意事項:
-p IP:host_port:container_port-p IP::port 來指定容許訪問容器的主機上的 IP、接口等,我這裏只容許外部8080端口來訪問3000端口
-d 就是在後臺運行容器,並返回容器ID。有興趣的小夥伴能夠體驗一下有-d和沒-d的區別

這時咱們輸入http://localhost:8003/就能夠訪問了咱們剛剛啓的服務了。
圖片描述

另外咱們能夠經過docker ps 來查看當前全部啓動的容器。
接下來咱們進入容器中看看這個容器到底有什麼東西!

docker exec -it <CONTAINER ID 或者 NAMES> /bin/bash

圖片描述

進入容器中咱們就看到了剛剛咱們以前在Dockerfile建的helloDocker文件夾,進去以後發現了咱們的app.js.執行exit命令就能夠退出容器。

Docker 數據卷的使用

  到這裏咱們已經掌握瞭如何去製做一個鏡像以及如何啓動一個鏡像了,接下來咱們要說點難一點的東西Docker數據卷的使用。首先說一下什麼是卷,爲何要引入卷這個東西。
  這邊咱們拿前端開發來講,咱們在前端開發中,咱們的js、css以及一些圖標等等這些靜態資源,這些文件都是能夠直接在url輸入地址直接訪問到的,自己這些東西不會影響項目的運行,說點通俗點就是咱們的這些資源怎麼整不會讓服務器報500錯誤.按照咱們前面的方法去作的話,確定之間把這些文件所有打到鏡像裏面,可是這個方法有個很很差的地方的。就是咱們每次修改他們都須要從新打一次鏡像,就感受很繁瑣。因而咱們就想,咱們能不能把此次靜態資源從鏡像中抽離出來,咱們讓容器指向這個目錄,而後咱們的服務就能夠訪問這些資源,每次改變完以後咱們就不須要從新打鏡像了,這樣豈不是很好。正由於如此咱們的數據卷就出來了,用來解決這個問題,那麼什麼是數據卷呢?咱們用一句話來闡述就是「數據卷是一個可供一個或多個容器使用的特殊目錄。」接下來咱們實際操做一把。

數據卷

第一步:咱們創建一個myDocker文件,裏面包含兩個文件app.js和package.json

app.js的內容以下:

var express = require('express');
var app = express();
//設置public目錄爲靜態目錄
app.use(express.static('public'));
//監聽3000端口
app.listen(3000);

package.json內容以下(主要目的是安裝express,本身能夠npm init本身生成一下,沒必要抄個人):

{
  "name": "docker",
  "version": "1.0.0",
  "description": "docker test",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.15.3"
  }
}

第二步:在myDocker同級目錄下,新建一個public目錄,放張圖片進去,這裏我放了一張美女圖片(hhh)。

圖片描述

第三步:在myDocker同級目錄下新建一個Dockerfile,內容以下:

#設置基礎鏡像
FROM daocloud.io/library/node:latest
#維護者信息
MAINTAINER wuming wuming@maihaoche.com
#在容器中新建一個myDocker文件中
RUN mkdir myDocker
#將Dockerfile所在目錄中myDocker文件夾的內容加到目標容器中的myDocker文件夾中
ADD myDocker  /myDocker
#設置工做目錄
WORKDIR /myDocker
#執行安裝項目依賴包的命令
RUN npm install
#容器啓動時,執行node app.js
CMD node app.js

第四步:構建一個名爲my-docker的鏡像

當前目錄結構爲:
myDocker
  ----Dockerfile
  ----myDocker
    ----app.js
    ----package.json
  ----public
構建命令

docker build -t my-docker:latest .

第五步:以掛載方式啓動容器

docker run -d -p 8003:3000 -v /Users/wuming/dockerWorkpace/myDocker/public:/myDocker/public  my-docker:latest

這裏我將本機的myDocker下的public掛載到容器中的/myDocker/public下,這裏咱們能夠登入容器中看一下,會發現咱們鏡像並無將咱們的public目錄打包進去,可是咱們的容器中卻有這個public目錄。
圖片描述

第六步:訪問咱們的圖片

在遊覽器地址欄中輸入http://localhost:8003/test.jpg即可看見,以下效果:圖片描述
你們能夠往本身的本機的public丟圖片進去,再去訪問它試試看,以及看看容器中的public沒有動態改變,答案是能夠的。

數據卷容器

上面咱們已經實現了數據卷,可是咱們發現加入若是我要起多個容器服務,時間短還能記得這個容器掛載目錄,要是時間多了豈不是都忘了,並且每次這樣去掛載也挺麻煩的,咱們能不能把咱們已經配好數據卷的容器做爲一個數據卷的提供者呢?答案是能夠的,這就是咱們要說的數據卷容器,接下來咱們操做一下。
docker run -d -p 8005:3000 --volumes-from NAMES或者CONTAINER ID  my-docker:latest
上面的NAMES或者CONTAINER ID爲咱們配好的數據卷的容器。啓動完容器以後,咱們能夠訪問試一下,而且往掛載目錄丟點其餘圖片進去,看看兩個容器服務是否是均可以訪問到。答案是能夠的。

使用網絡

外部訪問容器

1.映射全部接口地址
-p <端口號(8003)>:<端口號(3000)>

任何ip地址的指定<端口號(8003)>均可以訪問到服務(前提是那ip地址對應的主機要起了這個服務)

2.映射到指定地址的指定端口
-p <ip地址(127.0.0.1)><端口號(8003)>:<端口號(3000)>

指定ip地址的<端口號(8003)>均可以訪問到服務(前提是那ip地址對應的主機要起了這個服務),好比指定127.0.0.1,只有本機輸入127.0.0.1:8003或者localhost:8003能夠訪問本身的服務,可是其餘同一個局域網的手機輸入本機的對應局域網的ip地址:8003是訪問不到的,小夥們能夠拿本身的手機試試。

Docker經常使用命令

1.殺死全部正在運行的容器

docker kill $(docker ps -a -q)

2.刪除全部已經中止的容器

docker rm $(docker ps -a -q)

3.刪除全部鏡像

docker rmi $(docker images -q)

4.關閉容器

docker stop CONTAINER ID或者NAMES

5.從新啓動關閉的容器

docker start CONTAINER ID或者NAMES

6.移除本地容器

docker rm CONTAINER ID或者NAMES

7.查看本地容器

docker ps  //查看正在運行的容器
docker ps -a //查看全部容器

8.查看本地鏡像

docker images

9.建立鏡像

docker build -t name:tag Dockerfile路徑

10.修改本地鏡像標記

docker tag  IMAGE ID  name:tag 
 docker rmi name:tag

11.刪除本地鏡像

docker rmi name:tag或者IMAGE ID

12.進入容器

docker exec -it IMAGE ID或者NAMES /bin/bash

13.獲取鏡像中心的鏡像

docker pull name:tag

14.獲取容器的端口映射配置

docker port CONTAINER ID或者NAMES

持續更新更新....

Dockerfile命令速查表

FROM 命令

FROM <image>:<tag>

用於設置基礎鏡像,通常是Dockerfile的第一句。
若是沒有指定 tag ,則默認tag是latest。

MAINTAINER

MAINTAINER <name>

用來指定維護者的姓名和聯繫方式。

RUN

RUN <command> 或 RUN ["executable", "param1", "param2"]

每條 RUN 指令將在當前鏡像基礎上執行指定命令,並提交爲新的鏡像。

ADD

ADD <src> <dest>

將 <src> 文件複製到 <dst> 文件:<src> 是相對被構建的源目錄的相對路徑,能夠是文件或目錄的路徑,也能夠是一個遠程的文件 url,<dst> 是容器中的絕對路徑。

COPY

COPY <src> <dest>

複製本地主機的 <src> (爲Dockerfile所在目錄的相對路徑)到容器中的 <dest>,與ADD指令差很少

ENTRYPOINT

ENTRYPOINT ["executable", "param1", "param2"] :推薦使用的 exec 形式

ENTRYPOINT command param1 param2 :shell 形式

配置容器啓動後執行的命令,而且不可被 docker run 提供的參數覆蓋。
一個 Dockerfile 中只能有一個 ENTRYPOINT,若是有多個,則最後一個生效。

CMD

CMD ["executable","param1","param2"] 使用 exec 執行,推薦方式;
CMD command param1 param2 在 /bin/sh 中執行,提供給須要交互的應用;
CMD ["param1","param2"] 提供給 ENTRYPOINT 的默認參數;

指定啓動容器時執行的命令,每一個 Dockerfile 只能有一條 CMD 命令。若是指定了多條命令,只有最後一條會被執行。

若是用戶啓動容器時候指定了運行的命令,則會覆蓋掉 CMD 指定的命令。

WORKDIR

WORKDIR /path/to/workdir

爲後續的 RUN、CMD、ENTRYPOINT 指令配置工做目錄。

可使用多個 WORKDIR 指令,後續命令若是參數是相對路徑,則會基於以前命令指定的路徑。例如

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd

則最終路徑爲 /a/b/c 。

EXPOSE

EXPOSE <port> [<port>...]

告訴 Docker 服務端容器暴露的端口號,供互聯繫統使用。
例如 EXPOSE 8080 3000,開放 8080 和 3000 端口。

ENV

ENV <key> <value>

指定一個環境變量,會被後續 RUN 指令使用,並在容器運行時保持。

VOLUME

VOLUME ["/data"]

建立一個能夠從本地主機或其餘容器掛載的掛載點,通常用來存放數據庫和須要保持的數據等。

USER

USER <UID/Username>

爲容器內指定 CMD RUN ENTRYPOINT 命令運行時的用戶名或UID。

ONBUILD

ONBUILD [INSTRUCTION]

配置當所建立的鏡像做爲其它新建立鏡像的基礎鏡像時,所執行的操做指令。
例如,利用Dockerfile建立了一個鏡像A,其中Dockerfile中有這麼幾個命令

ONBUILD RUN mkdir test
ONBUILD ADD app.js /test/app.js

那麼鏡像B基於鏡像A去構建的時候,默認會在最後加上這兩行命令

FROM 鏡像A
 RUN mkdir test
 ADD app.js /test/app.js
相關文章
相關標籤/搜索