docker實踐(1) 入門和springBoot實踐部署

 

一. 什麼是docker     


     Docker是一個開源項目,誕生於2013年初, 最初是 dotCloud 公司內部的一個業餘項目。 它基於Google公司推出的Go語言實現。項目後來加入了Linux基金會, 遵從了 Apache 2.0 協議,項目代碼在GitHub上進行維護。
     Docker 自開源後受到廣泛的關注和討論, 以至於dotCloud公司後來都改名爲Docker Inc。 Redhat 已經在其RHEL6.5中集中支持Docker;Google也在其PaaS產品中廣泛應用。

     Docker 目的目實現輕的操作系化解決方案。Docker的基Linux容器(LXC) 等技在LXC的基礎上Docker進行了進一步的封裝,讓用戶不需要去關心容器的管理, 使得操作更爲簡便。 用戶操作Docker的容器就像操作一個快速輕量級的虛擬機一樣簡單。

     docker有效地將單個操作系統管理的資源劃分到獨立地組中,以便更好地在各個獨立組直接平衡有衝突的資源使用需求。

    下面的圖片比較了Docker和傳統虛擬化方式的不同之處, 可見容器是在操作系統層面上實現虛擬化, 直接複用本地主機的操作系統, 而傳統方式則是在硬件層面實現。

      容器和 VM(虛擬機)的主要區別是,容器提供了基於進程的隔離,而虛擬機提供了資源的完全隔離。虛擬機可能需要一分鐘來啓動,而容器只需要一秒鐘或更短。容器使用宿主操作系統的內核,而虛擬機使用獨立的內核。

      Docker 的侷限性之一是,它只能用在 64 位的操作系統上。

    

    

 

 

二. 爲什麼使用docker     


    作爲一種新興的虛擬化方式,Docker跟傳統的虛擬化方式相比具有衆多的優勢。

    首先,秒級實現:Docker容器的啓動可以在秒級實現,這相比傳統的虛擬機方式要快得多。 

    其次,高效使用資源: Docker 對系統資源的利用率很高, 一臺主機上可以同時運行數千個Docker容器。容器除了運行其中應用外, 基本不消耗額外的系統資源, 使得應用的性能很高, 同時系統的開銷儘量小。
    傳統虛擬機方式運行10個不同的應用就要起10個虛擬機, 而Docker只需要啓動10 個隔離的應用即可。

 

具體說來, Docker 在如下幾個方面具有較大的優勢:

2.1 更快速的交付和部署
    對開發和運維(devop) 人員來說, 最希望的就是一次創建或配置, 可以在任意地方正常運行。開發者可以使用一個標準的鏡像來構建一套開發容器, 開發完成之後, 運維人員可以直接使用這個容器來部署代碼。Docker可以快速創建容器, 快速迭代應用程序, 並讓整個過程全程可見, 使團隊中的其他成員更容易理解應用程序是如何創建和工作的。Docker容器很輕很快!容器的啓動時間是秒級的, 大量地節約開發、測試、 部署的時間。

2.2 更高效的虛擬化

     Docker 容器的運行不需要額外的hypervisor支持, 它是內核級的虛擬化, 因此可以實現更高的性能和效
率。

2.3 輕鬆的遷移和擴展
    Docker 容器幾乎可以在任意的平臺上運行, 包括物理機、 虛擬機、 公有云、 私有云、 個人電腦、 服務器
等。 這種兼容性可以讓用戶把一個應用程序從一個平臺直接遷移到另外一個。

2.4 更簡單的管理
    使用 Docker, 只需要小小的修改, 就可以替代以往大量的更新工作。 所有的修改都以增量的方式被分發和更新, 從而實現自動化並且高效的管理。

比傳統虛擬機總結:

 

三. docker體系結構     


     docker使用C/S 架構,docker daemon作爲 server 端接受 client 的請求,並處理(創建、運行、分發容器),他們可以運行在一個機器上,也通過sockerts或者 RESTful API 通信。

     

    Docker daemon 一般在宿主主機後臺運行,用戶使用 client 而直接跟 daemon 交互。Docker client以系統做 bin 命令的形式存在,用戶用 docker 命令來跟 docker daemon 交互。


3.1 Docker的內部組件

docker有三個內部組件
• docker images 鏡像
• docker registries 倉庫
• docker containers  容器

3.1.1 鏡像images

   docker images就是一個只讀的模板。比如:一個image 可以包含一個ubuntu的操作系統,裏面安裝了apache或者你需要的應用程序。images可以用來創建docker containersdocker提供了一個很簡單的機制來創建images或者更新現有的images,你甚至可以直接從其他人那裏下載一個已經做好的images。

鏡像工作原理:
   每個 docker 都有很多層次構成,docker使用union file systems 將這些不同的層結合到一個image中去。AUFS (AnotherUnionFS)是一種Union FS, 簡單來說就是支持將不同目錄掛載到同一個虛擬文件
   系統下(unite several directories into a single virtual filesystem)的文件系統,更進一步的理解, AUFS支持爲每一個成員目錄(類似Git Branch)設定 readonly、readwrite和 whiteout-able 權限,同時 AUFS裏有一個類似分層的概念,對readonly 權限的 branch 可以邏輯上進行修改(增量地,不影響readonly部分的)。通常Union FS有兩個用途,一方面可以實現不借助LVM、RAID將多個disk 掛到同一個目錄下,另一個更常用的就是將一個 readonly 的branch 和一個 writeable 的 branch 聯合在一起,LiveCD 正是基於此方法可以允許在 OS image 不變的基礎上允許用戶在其上進行一些寫操作。Docker在AUFS上構建的 container image 也正是如此。


3.1.2 倉庫registries

    倉庫是集中存放像文件的所。 有候會把倉庫倉庫註冊服器(Registry) 混, 並不格區分。實際上,倉庫註冊服器上往往存放着多個倉庫, 每個倉庫中又包含了多個像, 每個像有不同的標籤tag) 。
    倉庫公開倉庫Public) 和私有倉庫Private種形式。
    最大的公開倉庫Docker Hub, 存放了數量大的像供用。 國內的公開倉庫包括Docker Pool等, 可以提供大定快速的訪問
    當然, 用也可以在本地網建一個私有倉庫當用戶創建了自己的像之後就可以使用push命令將它上到公有或者私有倉庫這樣下次在外一臺機器上使用候, 只需要從倉庫pull下來就可以了。
    *注:Docker倉庫的概念跟Git類似, 註冊服務器可以理解爲GitHub這樣的託管服務。


3.1.3 容器containers 

       Docker利用容器來用。容器是從建的例。 它可以被啓動、 開始、 停止、除。 每個容器都是相互隔離的、 保安全
的平臺。
       可以把容器看做是一個易版的Linux境( 包括root戶權限、程空、 用和網等) 和行在其中的用程序。
*注:像是隻的, 容器在啓動建一可寫層作爲最上層。

3.1.4、容器工作原理

 當我們運行 docker run -i -t ubuntu /bin/bash 命令時,docker 在後臺運行的操作如下:

  1.  拉取鏡像:如果本地有 ubuntu 這個 image 就從它創建容器,否則從公有倉庫下載
  2. 創建容器:從image 創建容器
  3. 掛載文件:分配一個文件系統,並在只讀的 image 層外面掛載一層可讀寫的層
  4. 網絡橋接:從宿主主機配置的網橋接口中橋接一個虛擬接口到容器中去
  5. 分配 IP:從地址池配置一個ip 地址給容器
  6. 執行命令:執行你指定的程序,在這裏啓動一個/bin/bash進程
  7. 輸入輸出: -i -t 指定標準輸入和輸出

 


3.2 Docker底層技術

    docker 底層的2個核心技術分別是NamespacesControl groups
     以下內容摘自 InfoQ Docker,自 1.20 版本開始 docker 已經拋開 lxc,不過下面的內容對於理解 docker還是有很大幫助。

1)pid namespace
    不同用戶的進程就是通過 pid namespace 隔離開的,且不同 namespace 中可以有相同 pid。所有的LXC進程在docker 中的父進程爲 docker 進程,每個 lxc 進程具有不同的 namespace。同時由於允許嵌套,因此可以很方便的實現Docker in Docker。

2) net namespace
   有了 pid namespace, 每個 namespace中的pid 能夠相互隔離,但是網絡端口還是共享 host 的端口。
   網絡隔離是通過 net namespace實現的, 每個net namespace 有獨立的 network devices, IPaddresses, IP routing tables, /proc/net目錄。這樣每個container 的網絡就能隔離開來。docker默認採用veth的方式將 container 中的虛擬網卡同 host 上的一個 docker bridge: docker0 連接在一起。

3) ipc namespace

    container 中進程交互還是採用linux常見的進程間交互方法(interprocess communication - IPC),包括常見的信號量、消息隊列和共享內存。然而同VM不同的是,container的進程間交互實際上還是host上具有相同 pid namespace 中的進程間交互,因此需要在IPC 資源申請時加入namespace 信息 -每個IPC 資源有一個唯一的 32 位 ID。

4) mnt namespace
    類似 chroot,將一個進程放到一個特定的目錄執行。mnt namespace允許不同namespace 的進程看到的文件結構不同,這樣每個namespace中的進程所看到的文件目錄就被隔離開了。同chroot不同,每個namespace 中的 container 在/proc/mounts的信息只包含所在 namespace 的 mount point。

5) uts namespace

   UTS("UNIX Time-sharing System") namespace 允許每個 container 擁有獨立的 hostname和domainname,使其在網絡上可以被視作一個獨立的節點而非Host上的一個進程。

6) user namespace
    每個 container 可以有不同的 user 和 group id, 也就是說可以在 container 內部用 container內部的
用戶執行程序而非 Host 上的用戶。Control groups 主要用來隔離各個容器和宿主主機的資源利用。


 

四. docker安裝並運行spring boot


4.1 安裝

對於CentOS6,可以使用 EPEL庫安裝Docker,命令如下

$   sudo    yum install http://mirrors.yun-idc.com/epel/6/i386/epel-release-6-8.noarch.rpm  

$   sudo    yum install docker-io  

CentOS7系統CentOS-Extras 庫中已帶Docker,可以直接安裝:

  1. $   sudo    yum install docker  

4.2 啓動 Docker 服務

安裝之後啓動Docker 服務,並讓它隨系統啓動自動加載。

$   sudo    service docker  start 

$   sudo    chkconfig   docker  on  

 

4.3 下載官方的 CentOS 鏡像到本地

必須先啓動docker才能下載:

docker pull centos

 

4.4 運行一個 Docker 容器:

# docker run --t centos /bin/bash

[root@dbf66395436d /]#

我們可以看到,CentOS 容器已經被啓動,並且我們得到了 bash 提示符。在 docker 命令中我們使用了 “-i 捕獲標準輸入輸出”和 “-t 分配一個終端或控制檯”選項。若要斷開與容器的連接,輸入 exit。

[root@cd05639b3f5c /]# cat /etc/redhat-release

CentOSLinux release 7.3.1611(Core)
[root@cd05639b3f5c /]#exit
exit
[root@localhost ~]#

 

4.5 利用Dockerfile來創建鏡像

我們安裝java8, 基礎鏡像是centos。新建一個目錄和一個Dockerfile

$ mkdir java8
$ cd java8
$ touch Dockerfile

Dockerfile 中每一條指令都創建鏡像的一層:

# Pull base image.  
FROM centos  
  
# 設置jdk 的環境變量。
ENV JAVA_HOME /usr/java8
  
# 複製/usr/java文件到鏡像中(jdk1.8.0_66 目錄和Dockerfile在同一目錄)
#ADD jdk1.8.0_66 /usr/java8
COPY jdk1.8.0_66 /usr/java8
# Define default command.  
CMD ["bash"] 

Dockerfile 基本的語法是
使用 # 來註釋
FROM 指令告訴Docker使用哪個鏡像作爲基礎
接着是維護者的信息
RUN 開頭的指令會在創建中運行。

 

Build構建,在當前目錄下也可以通過 -f Dockerfile 文件的位置:

 docker build -t='java8'  ./

或者$ docker build -f /path/to/a/Dockerfile .

然後查看鏡像:

docker images

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
java8               latest              2abc9f66aba0        4 minutes ago       484.9 MB
docker.io/centos    latest              36540f359ca3        9 days ago          192.5 MB

 運行已經構件好的鏡像:

docker run -it java8 /bin/bash  

然後echo $JAVA_HOME 看看。

 

4.6 構建sping-boot

這個java jar 包就是turing-api-1.0-SNAPSHOT.jar 簡單http服務:

直接下載jar包:https://github.com/huangguisu/k8s.git

https://github.com/huangguisu/k8s/blob/master/docker/springboot/turing-api-1.0-SNAPSHOT.jar

Dockerfile:

#基礎鏡像:倉庫是java,標籤用java8 
FROM java8  
#當前鏡像的維護者和聯繫方式  
MAINTAINER guisu [email protected]  
#將打包好的spring程序拷貝到容器中的指定位置  
ADD turing-api-1.0-SNAPSHOT.jar /opt/turing-api-1.0-SNAPSHOT.jar
#容器對外暴露8080端口  
EXPOSE 8080  
#容器啓動後需要執行的命令  
CMD $JAVA_HOME/bin/java  -jar /opt/turing-api-1.0-SNAPSHOT.jar

構建:

docker build-t="spingboot"

啓動:

本地80端口映射到容器的8081端口

sudo docker run-d -p 80:8080 spingboot

然後就可以訪問主機的80端口了。

 

 

五. 問題


1、具體錯誤:Error response from daemon: conflict: unable to delete b227a9dfe196 (must be forced) - image is being used by stopped container 7b080f1e1f17

錯誤解析:這是由於要刪除的目標鏡像中有容器存在,故無法刪除鏡像

解決辦法:先刪除鏡像中的容器,再刪除該鏡像。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章