1. 程式人生 > >Docker技術入門與實戰筆記

Docker技術入門與實戰筆記

開發十年,就只剩下這套架構體系了! >>>   

Docker

一.底層技術支援cgroups/LXC/AUFS

1.cgroups

cgroups 程序分組化管理,Linux核心提供原生支援。通過分組實現對系統資源的限制與分配。

cgroups中的重要概念是“子系統”,也就是資源控制器,每種子系統就是一個資源的分配器.比如cpu子系統是控制cpu時間分配的。首先掛載子系統,然後才有control group的。比如先掛載memory子系統,然後在memory子系統中建立一個cgroup節點,在這個節點中,將需要控制的程序id寫入,並且將控制的屬性寫入,這就完成了記憶體的資源限制。

2.LXC

LXC是Linux containers的簡稱,是一種基於容器的作業系統層級的虛擬化技術。

藉助於namespace的隔離機制和cgroup限額功能,LXC提供了一套統一的API和工具來建立和管理container。

LXC旨在提供一個共享kernel的OS級虛擬化方法,在執行時不用重複載入Kernel,且container的kernel與host共享.

3.聯合檔案系統(UnionFS)

聯合檔案系統(UnionFS)是一種分層、輕量級並且高效能的檔案系統。

聯合檔案系統是 Docker 映象的基礎。映象可以通過分層來進行繼承,基於基礎映象可以製作各種具體的應用映象。

AuFS是ubantu上最常用的聯合檔案系統。

Docker映象實際上是由具有依賴關係的多個Layer組成的。

Union FS 是有最大層數限制的,比如 AUFS,曾經是最大不得超過42層,現在是不得超過127層。

二.基本概念

1.Docker Image

1)作業系統分為核心和使用者空間。對於 Linux 而言,核心啟動後,會掛載 root 檔案系統為其提供使用者空間支援。而 Docker 映象(Image),就相當於是一個 root 檔案系統。比如官方映象 ubuntu:14.04 就包含了完整的一套Ubuntu 14.04 最小系統的 root 檔案系統。

2)Docker Image內不建議有執行期需要修改的配置檔案

2.Docker Container

1)Docker Container是Image的例項,共享核心
2)Docker Container裡可以執行不同Os的Image,比如Ubuntu的或者Centos
3)Docker Container不建議內部開啟一個SSHD服務,1.3版本後新增了docker exec命令進入容器排查問題。
4)Docker Container沒有IP地址,通常不會有服務埠暴露,是一個封閉的“盒子/沙箱”

3.Docker Daemon

1)Docker Daemon是建立和執行Container的Linux守護程序,也是Docker最主要的核心元件.
2)Docker Daemon 可以理解為Docker Container的Container

4.資料卷

資料卷的生存週期獨立於容器,容器消亡,資料卷不會消亡。因此,使用資料卷後,容器可以隨意刪除、重新 run ,資料卻不會丟失。

資料卷是一個的特殊目錄,可以在容器之間共享和重用,資料卷預設會一直存在,即使容器被刪除.Docker掛載資料卷的預設許可權是讀寫,使用者也可以通過:ro指定為只讀。

資料卷容器 如果你有一些持續更新的資料需要在容器之間共享,最好建立資料卷容器。資料卷容器,其實就是一個正常的容器,專門用來提供資料卷供其它容器掛載的。

5. Docker Registry

1)一個Docker Registry中可以包含多個倉庫(Repository);每個倉庫可以包含多個標籤(Tag);每個標籤對應一個映象。

2)通過 <倉庫名>:<標籤> 的格式來指定具體是這個軟體哪個版本的映象。如果不給出標籤,將以 latest 作為預設標籤。

eg:registry.cn-qingdao.aliyuncs.com/dockerres/dockerres:webv1s1

3)虛懸映象 由於新舊映象同名,舊映象名稱被取消,從而出現倉庫名、標籤均為 <none> 的映象。這類無標籤映象也被稱為 虛懸映象(dangling image)。要注意區分虛懸映象與中間層映象。

三.Dockerfile

1.建立docker映象

1)docker commit

docker commit [選項] <容器ID或容器名> [<倉庫名>[:<標籤>]]

eg:docker commit \
                  --author "Tao Wang <[email protected]>" \
                  --message "修改了預設網頁" \
                  webserver \
                  nginx:v2

2)Dockerfile

docker build [選項] <上下文路徑/URL/->

eg:docker build -t nginx:v3 .  <.>表示上下文路徑為當前目錄

2.docker build的用法

a.直接用Git進行構建

docker build https://github.com/twang2218/gitlab-ce-zh.git

b.用給定的 tar 壓縮包構建

docker build http://server/context.tar.gz

c.從標準輸入中讀取 Dockerfile 進行構建

docker build - < Dockerfile

d.從標準輸入中讀取上下文壓縮包進行構建

docker build - < context.tar.gz

3.dockerfile命令

dockerfile內容:
    FROM debian:jessie
    RUN buildDeps='gcc libc6-dev make' \
        && apt-get update \
        && apt-get install -y $buildDeps \
        && wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz" \
        && mkdir -p /usr/src/redis \
        && tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
        && make -C /usr/src/redis \
        && make -C /usr/src/redis install \
        && rm -rf /var/lib/apt/lists/* \
        && rm redis.tar.gz \
        && rm -r /usr/src/redis \
        && apt-get purge -y --auto-remove $buildDeps

1)FROM 指定基礎映象。

如果不以任何映象為基礎,則以FROM scratch代替。

2)RUN

shell 格式: RUN <命令>

exec 格式: RUN ["可執行檔案", "引數1", "引數2"]

每一條RUN語句都會生成一個映象,可以用&&將多條命令合成一條RUN語句。

3)COPY

COPY <源路徑>... <目標路徑>

COPY ["<源路徑1>",... "<目標路徑>"]

使用 COPY 指令,原始檔的各種元資料都會保留。比如讀、寫、執行許可權、檔案變更時間等.

eg:
COPY hom* /mydir/
COPY hom?.txt /mydir/

4)ADD

ADD格式與COPY一樣 在COPY和ADD指令中選擇的時候,可以遵循這樣的原則,所有的檔案複製均使用COPY指令,僅在需要自動解壓縮的場合使用ADD。

5)CMD 啟動引數

CMD 指令用於指定容器預設的啟動程式及引數。

shell 格式: CMD <命令>

exec 格式: CMD ["可執行檔案", "引數1", "引數2"...]

指令格式上,一般推薦使用exec格式。

對於容器而言,其啟動程式就是容器應用程序,容器就是為了主程序而存在的,主 程序退出,容器就失去了存在的意義,從而退出。正確的做法是 直接執行可執行檔案,並且要求以前臺形式執行,不要以服務後臺的形式啟動。

6)ENTRYPOINT 啟動引數

ENTRYPOINT 的目的和 CMD 一樣,都是在指定容器啟動程式及引數。

ENTRYPOINT的主要應用場景:

a.讓映象變成像命令一樣使用

b.應用執行前的準備工作

7)ENV 設定環境變數

ENV <key> <value>

ENV <key1>=<value1> <key2>=<value2>

eg:ENV VERSION=1.0 DEBUG=on \
              NAME="Happy Feet"

8)ARG 構建引數

ARG <引數名>[=<預設值>]

構建引數和 ENV 的效果一樣,都是設定環境變數。所不同的是, ARG 所設定的構建環境的環境變數,在將來容器執行時是不會存在這些環境變數的。

9)VOLUME 定義匿名卷

VOLUME ["<路徑1>", "<路徑2>"...] VOLUME <路徑>

容器執行時應該儘量保持容器儲存層不發生寫操作,對於資料庫類需要儲存動態資料的應用,其資料庫檔案應該保存於卷(volume)中。為了防止執行時使用者忘記掛載卷,在 Dockerfile 中,我們可以事先指定某些目錄掛載為匿名卷.

10)EXPOSE 宣告埠

EXPOSE <埠1> [<埠2>...]

EXPOSE指令是宣告執行時容器提供服務埠,這只是一個宣告,在執行時並不會因為這個宣告應用就會開啟這個埠的服務。

11)WORKDIR 指定工作目錄

WORKDIR <工作目錄路徑>

12)USER 指定當前使用者

USER <使用者名稱>

13)HEALTHCHECK 健康檢查

HEALTHCHECK [選項] CMD <命令> :設定檢查容器健康狀況的命令

HEALTHCHECK NONE :如果基礎映象有健康檢查指令,使用這行可以遮蔽掉其健康檢查指令

eg:HEALTHCHECK --interval=5s --timeout=3s \
                                CMD curl -fs http://localhost/ || exit 1

14)ONBUILD 為他人做嫁衣裳

ONBUILD <其它指令>

eg:ONBUILD COPY ./package.json /app
     ONBUILD RUN [ "npm", "install" ]
     ONBUILD COPY . /app/

Dockerfile 中的其它指令都是為了定製當前映象而準備的,唯有 ONBUILD 是為了幫助別人定製自己而準備的。

ONBUILD 是一個特殊的指令,它後面跟的是其它指令,比如 RUN , COPY 等,而這些指令,在當前映象構建時並不會被執行。只有當以當前映象為基礎映象,去構建下一級映象的時候才會被執行。

四、Docker網路服務

1.外部訪問容器

可以通過 -P 或-p 引數來指定埠對映。

a.使用 -P 標記時,Docker 會隨機對映一個 49000~49900 的埠到內部容器開放的網路埠。
b.-p hostPort:containerPort 指定埠
eg:$ sudo docker run -d -p 5000:5000 training/webapp python app.py
c.-p ip:hostPort:containerPort
eg:sudo docker run -d -p 127.0.0.1:5000:5000 training/webapp python app.py
d.ip::containerPort 對映到指定地址的任意埠
eg:sudo docker run -d -p 127.0.0.1::5000 training/webapp python app.py
e.使用 udp 標記來指定 udp 埠
eg:sudo docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py
f.docker port 來檢視當前對映的埠配置
eg:docker port nostalgic_morse 5000

2.容器互聯

--link 引數的格式為 --link name:alias ,其中 name 是要連結的容器的名稱, alias 是這個連線的別名。

eg:sudo docker run -d -P --name web --link db:db training/webapp python app.py

3.網橋

Docker啟動時,會自動在主機上建立一個docker0虛擬網橋。當建立一個Docker容器的時候,同時會建立了一對虛擬網絡卡(veth pair)介面,這對介面一端在容器內,即eth0;另一端在本地並被掛載到docker0網橋。這樣所有容器在一個區域網內,通過docker0與主機通訊。

4.網路配置

--net=bridge 這個是預設值,連線到預設的網橋。

--net=host 告訴 Docker 不要將容器網路放到隔離的名稱空間中,即不要容器化容器內的網路。此時容器使用本地主機的網路,它擁有完全的本地主機介面訪問許可權。

--net=container:NAME_or_ID 讓 Docker 將新建容器的程序放到一個已存在容器的網路棧中,新容器程序有自己的檔案系統、程序列表和資源限制,但會和已存在的容器共享 IP 地址和埠等網路資源,兩者程序可以直接通過lo 環回介面通訊。

--net=none 讓 Docker 將新容器放到隔離的網路棧中,但是不進行網路配置。之後,使用者可以自己進行配置。

五.其他

tomcat Dockerfile
FROM tomcat:8.5.37-jre8
  MAINTAINER "wdw"
  ADD web1.war /usr/local/tomcat/webapps/
  CMD ["catalina.sh", "