Docker從基礎到企業生產應用學習筆記大總結


1、什么是docker 3

1.1docker 起源 3

1.2docker目標 3

1.3 docker三大理念 3

① 構建:不僅僅是代碼構建,也可以是環境 3

② 運輸:運輸,可以把構建環境放到任何地方。 3

③ 運行:可以在任何環境運行 3

1.4docker組成部分 3

1.5docker 組件 (重點也是學習它) 4

1.6docker虛擬化的不同之處 4

2、 為什么使用docker 5

2.1docker在哪幾方面具有較大優勢 5

Docker能做什么,改變了什么? 6

1.簡化配置 6

2.代碼流水線管理 6

① 提高開發效率 7

② 快速配置開發環境 7

③ 隔離應用(沒有虛擬機的效率高) 7

④ 調試能力 7

⑤ 多租互環境 7

⑥ 快速部署(比虛擬機快的多) 7

Docker重要理念不可變基礎設施詳解 8

1、什么是Immutable Infrastructure 8

2Immutable Infrastructure產生背景 8

3Immutable Infrastructure帶來的好處 8

1) 解決環境間差異問題 8

2) 快速回滾到老版本 8

3) 更好的進行CI 8

4) 更好的自動化 8

5) 更容易進行大規模運維 8

Docker快速入門 8

1、安裝docker 8

1.1、安裝環境 8

3.10.0-514.el7.x86_64 8

1.2、安裝docker 9

1.3、查看安裝結果 9

2、啟動docker 9

2.1、啟動docker鏡像 9

2.2、查看docker狀態 9

2.3、關閉docker 9

2.4、查看本地網絡 9

3、基礎命令講解 9

1. 鏡像 9

2. 容器 9

3. 倉庫 9

3.1、鏡像命令 10

3.1.2查看已有鏡像 10

3.1.1、搜索 10

3.1.2、下載 10

3.1.3 導出鏡像 11

 3.1.4、導入鏡像 11

3.1.6刪除鏡像 11

 3.1.7創建鏡像 12

3.2容器 12

3.2.1、啟動容器 12

基於鏡像新建一個容器並啟動。 13

將終止狀態的容器重新啟動。 13

3.2.2、啟動已經終止的容器 14

 3.2.3、后台運行 15

3.2.3、進入鏡像 15

已經起來的鏡像怎么進去 15

3.2.3.1、attach 15

3.2.3.2nsenter  進入到命名空間里面 16

利用docker inspect 獲得PID 16

① –mount參數是進去到mount namespace中 16

② –uts參數是進入到uts namespace中 16

③ –ipc參數是進入到System V IPC namaspace中 16

④ –net參數是進入到network namespace中 16

⑤ –pid參數是進入到pid namespace中 16

⑥ –user參數是進入到user namespace中 16

我們不能每次都要執行上面的命令,找到PID 在進入再次我們需要寫一個腳本 17

3.2.3.3docker exec 17

3.2.4、查看容器列表 18

3.2.5、容器刪除 19

Docker進入容器和網絡訪問 20

隨機映射: 20

指定映射最常用的是第一種,直接指定宿主端口:容器端口 21

 Docker數據管理 22

4.1 掛載數據卷 23

4.1.1 將容器目錄掛載到宿主的隨機目錄 23

4.1.2 指定容器掛載到宿主的固定目錄 生產常用的 24

 測試: 24

4.2 數據卷容器 類似nfs 差不多  其實生產不用 24

4.  手動構建Docker鏡像,生產不常用,一般都是自動化 25

6. Dockerfile構建 Docker鏡像  重點中重點,難點中難點 ****** 26

7.  Docker核心原理-資源隔離和限制 27

實際測驗: 29

 7.3 內存限制配額 29

8. Docker核心原理-網絡和Registry 29

8.1 橋接模式 29

8.2 HOST模式 31

 9. 配置私有倉庫push  pull 31

9.5.1 修改/etc/sysconfig/docker,添加一個啟動參數 32

9.5.2 pull鏡像 33

10生產構建docker鏡像核心思想,生產案例演示 33

 

1、什么是docker

1.1docker 起源

開源項目

誕生2013年初

GO語言開發實現

遵從了Apache2.0協議

項目代碼在GitHub維護

 1.2docker目標

docker項目目標是實現輕量級的操作解約方案。

linux容器(LXC)等技術,在LXC的基礎上進行了封裝,讓用戶不需要關心docker的管理,使得操作更為簡單。

 

1.3 docker三大理念

① 構建:不僅僅是代碼構建,也可以是環境

② 運輸:運輸,可以把構建環境放到任何地方。

③ 運行:可以在任何環境運行

一次創建,處處運行

 

可以做一些整體的交付(不一定是代碼 交付,可以是運行環境和代碼放到一起構建,可以提供運行環境和代碼)

 

核心思想:環境不變可以不用docker,看業務使用,不同業務會有不同的契合度。

引入新技術的原因:解決痛點,做技術儲備

 

通俗點解釋:

就像dockerlog一樣,鯨魚(操作系統)和集裝箱(存放各種服務應用),我們需要把各種各樣的貨物放到鯨魚身,你得為每件貨物考慮,怎么安放(應用程序所需要的環境),考慮貨物與貨物之間是否合適(應用程序依賴環境是否沖突)。

現在我們只要把貨物放入到集裝箱里,就可以安全的存放,穩定,方便。

 

1.4docker組成部分

C/S架構

Docker Client    執行docker命令屬於客戶端

Docker server    docker進程屬於客戶端

注:docker服務端掛掉所有的客戶端也會掛掉,這是docker的一個痛點

 

1.5docker 組件 (重點也是學習它)

① 鏡像(Image):和虛擬機鏡像作用完全一樣,但是組成部分不同。

② 容器(Container):從鏡像創建的一個實例(類似虛擬機),相互之間隔離的,不會像虛擬機那樣隔離的徹底。可以理解為簡化版的linux環境。用容器來運行業務的,可以理解為一個簡化版的linux系統環境

③ 倉庫(Repository):鏡像倉庫,鏡像做好可以放進去,所有服務器只要可以連接到倉庫,都可以直接下載,相當與yum倉庫。docker自己也有一個docker hub

 

1.6docker虛擬化的不同之處

   可見容器實在操作系統層面實現虛擬化,直接復用本地主機的操作系統,而傳統虛擬化方式則是在硬件層面實現的。  簡要的說就是虛擬機是虛擬  docker是隔離

 

核心思想:對新技術的選擇在實驗科研中一定是最新要敢為人先,生產中一定不要敢為人先,讓別人先去踩坑

 

虛擬機和docker的實現原理和區別:對內核要求高,這也是搞火ubuntu的原因

 

 

DockerOpenStack的區別  核心思想理念  拿項目管理考試和現實來講解做對比

虛擬機需要運行hypervisordocker都跑在docker引擎里面,docker不是虛擬機,沒有操作系統直接運行應用。

 

docker無法像虛擬機一樣提供完全的資源隔離,甚至好多地方都沒有隔離,比如用戶空間,一直再填坑,體驗新功能需要內核支持。

 

類別

Docker

OpenStack/kvm

部署難度

非常簡單

組件多,部署復雜

啟動速度

秒級

分鍾級

執行性能

和物理系統幾乎一致

VM會占用一些資源

鏡像體積

鏡像是MB級別

虛擬機鏡像GB級別

管理效率

管理簡單

組件相互依賴,管理復雜

隔離性

隔離性高

徹底隔離

可管理性

單進程、不建議啟動SSH

完整的系統管理

網絡連接

比較弱

借助Neutron可以靈活組件各類網絡架構

需要注意:

 

  1. docker里面只能啟動一個單進程,還是在前台,如果掛了docker就直接退出。
  2. docker容器就是一個進程,掛了也就掛了,按照docker理念不需要打開ssh,不需要連接上。 容器掛了再重新啟動一個。
  3. docker 管理簡單 管理簡單以為操作的簡單,沒有辦法想怎么管怎么管,在復雜的環境管理簡單就不是優勢了。
  4. 單進程  可以寫一個腳本里面寫多個進程解決,但是這有不符合docker理念,只要啟動一個就好了。套件可以跑,php+nginx 可以 但是直接跑lnmp就不符合docker的理念了。

 

2、為什么使用docker

如果保障環境一致性:  快速回滾?  回到上一個版本? 虛擬化快照來實現  為什么需要虛擬環境呢,比如我要升級一個軟件,結果就把所有依賴的包都升級了,那就出故障了。

 

  標准化和規范性

 

docker項目的發起人和Docker.IncCTO 認為,docker在正確的地點、時間順應了正確的趨勢即高效地構建應用,現在開發者需要能方便地創建運行在雲平台的應用,也就是說應用必須能夠脫離底層機器,而且同時是任何時間任何地點可獲取的。因此開發者需要創建一種分布式應用程序的方式,這也是docker所能夠提供的。

 

docker通過容器來打包應用,這樣我們就可以在新的機器上啟動這個容器就可以了,這無疑節約了大量的時間,並且大大降低了部署過程中的錯誤。並且可以支持把代碼和容器打包,這樣我們就可以直接啟動容器做相應的測試,上線。真正做到了一次搭建,處處運行。

 

2.1docker在哪幾方面具有較大優勢

① 更快的交付和部署

對於開發和運維人員來說,最希望的就是一次創建或配置,可以在任意地方運行。

開發者可以使用一個標准的鏡像來構建一套開發容器,開發完成后,運維人員開一直接使用這個容器來部署代碼。

② docker可以快速創建容器,快速迭代應用程序,並讓整個過程全程可見,使團隊中的其他成員更容易理解應用程序是如何創建和工作的。

③ Docker很輕很快!容器啟動時間是 秒級,大量地節約開發、測試、部署的時間。

 

④ 更高效虛擬化

 

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

 

 

⑤ 更輕松的遷移和擴展

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

 

 

⑥ 更簡單的管理

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

 

Docker能做什么,改變了什么?

 

 

1.簡化配置

主要應用場景,把代碼和運行環境放到一起,這樣就不需要什么代碼部署,直接啟動容器就是一個服務。不許要環境部署和代碼上線

 

 2.代碼流水線管理

傳統流程:開發寫代碼--測試--運維上線 docker 可以避免這么復雜的流程

 

docker管理這個流水線,開發保存鏡像,測試run起來測試,測試結束,運維run起來跑,(虛擬機太大也可以實現),一次構建到處運行

 

① 提高開發效率

② 快速配置開發環境

③ 隔離應用(沒有虛擬機的效率高)

④ 調試能力

⑤ 多租互環境

⑥ 快速部署(比虛擬機快的多)

 

開發也好測試也好運維也好,要使用的話直接yum一個docker,然后從倉庫導入一下,整個環境就可以工作了

 

趙班長總結:

面向產品 :產品交付  安全,把什么成果代碼都打包進docker一起交付 

面向開發: 簡化配置環境 ,只用告訴開發下載一個docker就行了,本地不需要環境

面向測試: 多版本測試

面向運維: 環境一致性

面向架構: 自動化擴容(微服務)

 

 

Docker重要理念不可變基礎設施詳解

1、什么是Immutable Infrastructure

Immutable Infrastructure,直譯過來就是不可變基礎設施。

它是由Chad Fowler2013年提出的一個很有前瞻性的構想。

基礎設備中的每層的每個組件都可以自動安裝、部署。

每個組件在完成后將將不會發生更改,如果要更改,則丟棄老的組件並部署一個新的組件。

這種思想與不可變對象的概念完全相同。

這里所說的每一層,指的是從os(虛擬機、雲主機)到集群,節點管理和單個節點的安裝軟件配置。

2Immutable Infrastructure產生背景

當然在很多年以前這個概念是得不到技術支持的,我們很難在不同的物理機上實現軟件的不可變。

 不過隨着虛擬化技術以及雲計算的發展,現在這已經變得可能了。

 我們更多的時候,面對的不是一台台的物理主機,更多的是雲主機實例。

 安裝一個操作系統也不需要幾小時,而只需要鼠標點幾下,等上兩三分鍾即可。

 重裝系統這個概念已經不存在,刪掉一個主機實例我們也不會心疼。

 

3Immutable Infrastructure帶來的好處

1) 解決環境間差異問題

2) 快速回滾到老版本

3) 更好的進行CI

4) 更好的自動化

5) 更容易進行大規模運維

 

 

Docker快速入門

 

 

 1、安裝docker

1.1、安裝環境

[root@linux-node1 ~]# cat /etc/redhat-release

CentOS Linux release 7.3.1611 (Core)

[root@linux-node1 ~]# uname -r

3.10.0-514.el7.x86_64

1.2、安裝docker

yum install docker -y

1.3、查看安裝結果

[root@linux-node1 ~]# rpm -qa docker

docker-1.13.1-63.git94f4240.el7.centos.x86_64

[root@linux-node1 ~]# docker --version

Docker version 1.13.1, build 94f4240/1.13.1 

我們可以通過官方的docker官網下載最新版本。

Docker官網:http://www.docker.com/

注:使用docker目前使用的越新越好,因為docker一直都在不足,每次更新都更加的完善。

2、啟動docker

2.1、啟動docker鏡像

[root@docker ~]# systemctl start docker

2.2、查看docker狀態

[root@docker ~]# systemctl  status docker

2.3、關閉docker

systemctl stop docker

2.4、查看本地網絡

 

docker啟動后,會生成一個docker:0的網卡(虛擬機也會生成)。

 

3、基礎命令講解

 以docker的三大組件,分別講解命令。

  1. 鏡像
  2. 容器
  3. 倉庫

3.1、鏡像命令

docker 運行容器前需要本地存在對應的鏡像,如果鏡像本地不存在,docker會從鏡像倉庫下載(默認從Docker Hub倉庫下載)。

3.1.2查看已有鏡像

 

docker images

[root@docker ~]# docker images

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE

oldboy/nginx1       latest              c436de4b837a        5 days ago          401.1 MB

oldboy/nginx        v1                  99695fe97fb5        5 days ago          181.4 MB

docker.io/nginx     latest              05a60462f8ba        3 weeks ago         181.4 MB

docker.io/centos    latest              0584b3d2cf6d        4 weeks ago         196.5 MB

 在列出的信息中,可以看到幾個字段的信息

  • 來自於那個倉庫(REPOSITORY)
  • 鏡像標記(TAG)
  • 它的ID號(唯一)
  • 創建時間
  • 鏡像大小

 

3.1.1、搜索

docker search [鏡像名稱]

例:查看dockerhub中nginx的鏡像。

[root@docker ~]# docker search nginx

 

3.1.2、下載

docker pull [鏡像名稱]

例:下載docker.io/centos/redis

 docker pull  docker.io/centos/redis

Using default tag: latest

Trying to pull repository docker.io/centos/redis ...

latest: Pulling from docker.io/centos/redis

3.1.3 導出鏡像

docker save -o [鏡像包名] [鏡像名稱]

例:導出centos基礎鏡像為centos.tar

[root@docker ~]# docker images

[root@docker ~]# docker save -o centos.tar docker.io/centos

[root@docker ~]# ll -h centos.tar -rw-r--r-- 1 root root 195M Dec  1 20:54 centos.tar

 3.1.4、導入鏡像

docker load --input [鏡像包名]

[root@linux-node1 ~]# docker load --input centos.tar

 

docker load <[鏡像包名]

3.1.6刪除鏡像

docker rni [鏡像id]

例:刪除一個鏡像

[root@docker ~]# docker images

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE

oldboy/nginx1       latest              c436de4b837a        5 days ago          401.1 MB<none>              <none>              6ab373e100c9        5 days ago          181.4 MB

oldboy/nginx        v1                  99695fe97fb5        5 days ago          181.4 MB

docker.io/nginx     latest              05a60462f8ba        3 weeks ago         181.4 MB

docker.io/centos    latest              0584b3d2cf6d        4 weeks ago         196.5 MB

daemon: conflict: unable to delete 0584b3d2cf6d (cannot be forced) - image has dependent child images

[root@docker ~]# docker rmi 6ab373e100c9

[root@docker ~]# docker images

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE

oldboy/nginx1       latest              c436de4b837a        5 days ago          401.1 MB

oldboy/nginx        v1                  99695fe97fb5        5 days ago          181.4 MB

docker.io/nginx     latest              05a60462f8ba        3 weeks ago         181.4 MB

docker.io/centos    latest              0584b3d2cf6d        4 weeks ago         196.5 MB

注:不能刪除已有容器的鏡像

例:刪除一個已有容器的鏡像

[root@docker ~]# docker rmi 0584b3d2cf6d

Failed to remove image (0584b3d2cf6d): Error response from daemon: conflict: unable to delete 0584b3d2cf6d (cannot be forced) - image has dependent child images

例:移除本地所有未打過標簽的本地鏡像

docker images可以列出本地所有的鏡像,其中可能包含很多中間狀態的來打過標簽的鏡像,大量占據着磁盤空間。

使用下面命令可以清理所有未打過標簽的本地鏡像

docker rmi $(docker images -q -f "danglingture")

 

 3.1.7創建鏡像

創建鏡像為較為復雜點,在之后的文檔中會詳細介紹。 所有重難點都在這里!

 

3.2容器

容器是獨立運行的一個或一組應用,以及他們的運行環境。對應的虛擬機可以理解為模擬運行的一套操作系統(提供了運行環境和其他其系統環境)和跑在上面的應用。

3.2.1、啟動容器

啟動容器的方式

① 基於鏡像新建一個容器並啟動。

② 將終止狀態的容器重新啟動。

 容器太輕量了,很多時候用戶都是隨時刪除和新創建容器。

docker run [選項、參數] 鏡像名稱 [執行的命令] 

注:如果不指定鏡像名稱會自動生成名稱,管理docker一般都是以名稱或者id號來管理的

例:輸出一個hell[root@docker ~]# docker run docker.io/centos /bin/echo 'hello world'

hello world

這跟直接在本地執行一個hello world 沒有任何區別。

 

[root@docker ~]# docker ps -a 查看docker啟動狀態  不加-a的話只顯示正在運行的

 

 

因為沒有指定容器名稱,所以他自己自動生成了gigantic_sinoussi

例:啟動一個bash,允許用戶交互,指定容器名稱為mycentos

[root@docker ~]# docker run -i -t --name mycentos docker.io/centos (鏡像名) /bin/bash  如果后面不是命令,最后就必須是鏡像名

[root@c761cee8863f /]#

-name:指定容器名稱-t:讓docker分配一個偽終端

-i:讓容器的標准輸入打開(input)

接上例:在交互模戶,模式下。用戶可以通過所創建的終端來輸入命令

[root@c761cee8863f /]# pwd/

[root@c761cee8863f /]# ls

anaconda-post.log  bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

繼續接上例:在可交互模式查看進程,本地信息

root@c761cee8863f /]# ps aux

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND

root         1  0.0  0.0  11752  1876 ?        Ss   15:44   0:00 /bin/bash

root        17  0.0  0.0  47424  1660 ?        R+   16:02   0:00 ps aux

[root@c761cee8863f /]# free -m

              total        used        free      shared  buff/cache   available

Mem:           1993         158        1121           8         713        1669

Swap:           475           0         475

[root@c761cee8863f /]# exit

[root@docker ~]# free -m

              total        used        free      shared  buff/cache   available

Mem:           1993         147        1140           8         706        1681

Swap:           475           0         475

 

容器不是一個虛擬機,他只是一個進程,pid為1的進程結束了,這個容器就掛了,他就是為了隔離這個進程而存在的。

 

docker的隔離性並不是很好,在物理機可以看到服務器的硬件信息,docker本身不能解決,但是可以用一些黑科技解決,當然如果自己用的話也可以不用解決這個問題。

docker run來創建容器時,docker在后台運行的標准操作包括:

  1. 檢查本地是否存在 指定的鏡像,不存在就從倉庫下載。
  2. 利用鏡像創建並啟動一個鏡像
  3. 分配一個文件系統,並在只讀的鏡像層外面掛載一層可讀寫層。
  4. 從宿主主機配置的網橋接口中橋接一個虛擬接口到容器中去
  5. 從地址池配置一個ip地址給容器
  6. 執行用戶指定的應用程序
  7. 執行完畢后容器被終止

3.2.2、啟動已經終止的容器

 

docker start [容器名稱|容器id]

例:啟動mycentos

[root@docker ~]# docker ps

CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

[root@docker ~]# docker ps -a

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS               NAMES

c761cee8863f        docker.io/centos    "/bin/bash"              35 minutes ago      Exited (0) 18 minutes ago                       mycentos

ccfc03f90613        docker.io/centos    "/bin/echo /bin/bash"    36 minutes ago      Exited (0) 36 minutes ago                       elated_brown

443da0721b41        docker.io/centos    "/bin/echo 'hello wor"   44 minutes ago      Exited (0) 44 minutes ago                       gigantic_sinoussi

[root@docker ~]# docker start mycentos

mycentos

[root@docker ~]# docker ps

CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

c761cee8863f        docker.io/centos    "/bin/bash"         36 minutes ago      Up 3 seconds                            mycentos

注:有的人想在容器起來的時候在執行其他的東西。這是不推薦的因為docker的理念,不可變基礎設施,不要修改容器(前面有講解),再重新創建一個就可以了,已改動就可變了。

 3.2.3、后台運行

更多的時候需要讓Docker 在后台運行而不是直接執行命令的結果輸出在當前宿主機下,此時,可以通過添加 -d 參數來實現。

例:如果不使用-d參數運行容器

 [root@docker ~]# docker run   centos echo hello world

hello world

容器會把輸出結果打印到宿主機上

例:使用-d參數

[root@docker ~]# docker run  -d centos echo hello world

f6f8844f843b6479ab2d9faf52aef55a8c9516effa1dc7574299989025f24a41

[root@docker ~]# docker logs f6f8844f843b6479ab2d9faf52aef55a8c9516effa1dc7574299989025f24a41

hello world

 這時候容器會在后台運行並不會把輸出結果(STDOUT)打印到宿主機上面(輸出結果可以用docker logs查看)
:容器是否會長久運行,是和docker run指定的

3.2.3、進入鏡像

已經起來的鏡像怎么進去

Centos 7命令補全工具:

yum -y install bash-completion 自動補全命令

3.2.3.1、attach  

docker attach [鏡像名稱]

這個登錄相當於單用戶模式,只能有一個人登錄。一般生產不推薦使用此法。

例:一方操作另一方會自動操作。

 

命令不靠譜

3.2.3.2nsenter  進入到命名空間里面

生產場景是不使用docker attach的,需要我們使用nsenter這個工具,這個工具包含在util-linux軟件包里面。nsenter可以訪問另一個進程的名字空間。nsenter要正常工作需要有root權限。

[root@docker ~]#  yum install util-linux -y

一般情況下最小化安裝里都已經安裝完畢。

我們通過nsenter就可以進入容器,但是nsenter是通過容器第一個進程的pid進入容器里,所以我們需要知道容器的pid。我們可以通過docker inspect來獲取到pid

利用docker inspect 獲得PID

[root@docker ~]# docker start mycentos

mycentos

[root@docker ~]# docker inspect -f "{{ .State.Pid }}" mycentos

10656

[root@docker ~]# nsenter -t 10656 -m -u -i -n -p

[root@c761cee8863f /]#

那個參數選項是簡寫全稱的就是:

nsenter --traget $PID  --mount --uts  --ipc --net --pid

nsenter參數:

① –mount參數是進去到mount namespace中

② –uts參數是進入到uts namespace中

③ –ipc參數是進入到System V IPC namaspace中

④ –net參數是進入到network namespace中

⑤ –pid參數是進入到pid namespace中

⑥ –user參數是進入到user namespace中

 我們進入容器查看進程

[root@c761cee8863f /]# ps aux

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND

root         1  0.0  0.0  11776  1664 ?        Ss+  22:06   0:00 /bin/bash

root        14  0.0  0.0  13376  1988 ?        S    22:12   0:00 -bash

root        27  0.0  0.0  49024  1808 ?        R+   22:21   0:00 ps aux

 其中/bin/bash 是我們開啟容器運行的第一個進程

-bash 是nsenter 啟動時生成的進程,這樣我們退出后,容器不會退出,仍然會運行。

我們不能每次都要執行上面的命令,找到PID 在進入再次我們需要寫一個腳本

寫腳本思想,先把框架寫出來

 cat  cat docker_in.sh

#!/bin/bash

# Use nsenter to access docker

docker_in(){

  NAME_ID=$1

  PID=$(docker inspect -f "{{ .State.Pid }}" $NAME_ID)

  nsenter -t $PID -m -u -i -n -p

}

docker_in $1

執行結果

[root@docker ~]# chmod +x docker_in.sh

[root@docker ~]# ./docker_in.sh mycentos

[root@c761cee8863f /]# ps aux

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND

root         1  0.0  0.0  11776  1664 ?        Ss+  22:06   0:00 /bin/bash

root        28  0.0  0.0  13376  1984 ?        S    22:28   0:00 -bash

root        41  0.0  0.0  49024  1812 ?        R+   22:28   0:00 ps aux

3.2.3.3docker exec

docker exec 的本意不是為了進入容器,僅僅是為了在外面執行一個容器的操作。

docker exec [容器名稱|id] 命令

例:在容器mycentos外執行命令whoami等

[root@docker ~]# docker exec mycentos whoami

root

[root@docker ~]# docker exec mycentos ps aux

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND

root         1  0.0  0.0  11776  1664 ?        Ss+  22:06   0:00 /bin/bash

root        46  0.0  0.0  47424  1660 ?        Rs   22:34   0:00 ps aux

進入容器方法

docker exec -it [容器名稱|id] /bin/bash

例:使用docker exec 進入容器

[root@docker ~]# docker ps

CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

c761cee8863f        docker.io/centos    "/bin/bash"         6 hours ago         Up 30 minutes                           mycentos

[root@docker ~]# docker  exec -it mycentos  /bin/bash

[root@c761cee8863f /]# exit

[root@docker ~]# docker  exec -it c761cee8863f  /bin/bash

[root@c761cee8863f /]#

nsenter 實現原理不一樣 實現結果一樣的 推薦使用腳本進入是最佳實現

3.2.4、查看容器列表

docker ps

:查看正在運行的容器

[root@docker ~]# docker ps

CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

c761cee8863f        docker.io/centos    "/bin/bash"         6 hours ago         Up 32 minutes                           mycentos

例:查看所有容器

[root@docker ~]# docker ps -a

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                     PORTS               NAMES

edfdd26e20da        centos              "echo hello world"       3 hours ago         Exited (0) 3 hours ago                         kickass_heisenberg

f6f8844f843b        centos              "echo hello world"       3 hours ago         Exited (0) 3 hours ago                         reverent_yalow

例:只查所有鏡像的id

[root@docker ~]# docker ps -a -q

edfdd26e20da

f6f8844f843b

查看所有運行容器的id只要去掉-a參數即可。

3.2.5、容器刪除

可以使用docker rm 來刪除一個出於終止狀態的容器。

例:刪除 reverent_yalow

[root@docker ~]# docker ps -a

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                     PORTS               NAMES

f6f8844f843b        centos              "echo hello world"       4 hours ago         Exited (0) 4 hours ago                         reverent_yalow

[root@docker ~]# docker rm reverent_yalow

reverent_yalow

[root@docker ~]# docker ps -a

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                     PORTS               NAMES

cd9cf2398630        centos              "while true ;echo hel"   4 hours ago         Created                                        high_mclean

如果刪除一個正在運行中的容器,可以添加-f 參數。Docker會發送SIGKLL信號給容器。

 清理所有出於終止狀態的容器,可以配合剛才我們展示的docker ps -a -q。用docker rm $(docker ps -a -q)

例:刪除所有終止狀態的容器

[root@docker ~]# docker ps -a

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                     PORTS               NAMES

cd9cf2398630        centos              "while true ;echo hel"   4 hours ago         Created                                        high_mclean

[root@docker ~]# docker rm $(docker ps -a -q)

cd9cf2398630

[root@docker ~]# docker ps -a

CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

c761cee8863f        docker.io/centos    "/bin/bash"         7 hours ago         Up About an hour                        mycentos

這里還有一個測試時好用的參數

docker run --rm   [選項] [鏡像名稱] [命令]

使用 --rm參數在我們使用完這個容器,關閉就會自動刪除,省時省力,當然如果還需要在測試,就重新啟動一個容器,也符合docker不可變基礎設施理念。

例:創建一個測試容器,退出后自動給刪除

root@docker ~]# docker ps -a

CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

c761cee8863f        docker.io/centos    "/bin/bash"         7 hours ago         Up About an hour                        mycentos

[root@docker ~]# docker run --rm -it  --name ceshi centos /bin/bash

[root@e392d10516b0 /]# exit

[root@docker ~]# docker ps -a

CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

c761cee8863f        docker.io/centos    "/bin/bash"         7 hours ago         Up About an hour                        mycentos

 

 

 

 Docker進入容器和網絡訪問

 

隨機映射:

docker run -d -P httpd  類似我們公司買了一台路由器在上面做了一個端口映射幫我們上網一樣

 

其實上面的命令的原理結果在iptables里可以看出來:

[root@linux-node1 ~]# iptables -t nat -vnL

 

我們可以進容器實例里面去看一下實際情況:

 

 

 

可以很明顯的看到確實是映射正確的

訪問日志:

[root@linux-node1 ~]# docker logs cc41ebe12346

 

測試效果:

 

指定映射最常用的是第一種,直接指定宿主端口:容器端口

 

查看映射:

 

第二種,假如宿主有多個ip的話,讓容器的端口綁定到宿主的固定一個ip的端口上;

第三種,只綁定宿主ip,端口隨機取;

第四種,它的意思是一條docker run命令可以同時用多次”-p”參數,指定多個端口映射關系,比如,docker run –d –p 99:80 –p 33:443 –name mynginx33 nginx

 

 

 

啟動容器時用-P(大寫)參數,表示讓容器隨機對應一個宿主機的端口,如上,容器的80容器端口80對應宿主的82端口,容器的443對應宿主的443端口。

總結:端口隨機映射的好處是:端口不會沖突。難點是,生產中還得用腳本或者其他方式獲取到這個隨機的端口,由於它是變化的,所以腳本必須得適應這種變化性。

 

 

 Docker數據管理

 

Docker數據資源存儲管理原理圖 (分層設計存儲的)

 

 

如果想要數據持久化永久保存就引入下面概念:(docker理念其實是停了就停了,沒有持久保存這一說)  其實數據卷類似光盤一樣,掛載就行了,其實也不是很好管理,因為如果你有幾百個鏡像,就得掛載幾百個目錄

 

 

4.1 掛載數據卷

4.1.1 將容器目錄掛載到宿主的隨機目錄

docker run -d --name volume-test1  -v /data httpd

創建一個名字是volume-test1,以httpd系統為基礎鏡像的容器,它的主機名是httpd,把這個容器的/data目錄掛載到宿主機上。

重新開一個SecureCRT session,然后輸入docker inspect -f``.`Volumes` volume-test1,就會看到下面的:

map[/data:/var/lib/docker/volumes/a6d633be7da3ca959a45328f9d95f9b7db7c1f7ff9012a51ed85a0bdb7f98b94/_data]

它相當於是一個字典,把容器的/data映射到宿主的/var/lib/docker/volumes/a6d633be7da3ca959a45328f9d95f9b7db7c1f7ff9012a51ed85a0bdb7f98b94/_data。

在容器的/data目錄下新建一個文件,可以在/var/lib/docker/volumes/a6d633be7da3ca959a45328f9d95f9b7db7c1f7ff9012a51ed85a0bdb7f98b94/_data里看到;

同樣,在宿主的

/var/lib/docker/volumes/a6d633be7da3ca959a45328f9d95f9b7db7c1f7ff9012a51ed85a0bdb7f98b94/_data里創建一個文件,也能在容器的/data目錄下看到。

這個跟VMware的共享目錄一模一樣,一對兒目錄映射關系。

 

 

 

 

 

 

4.1.2 指定容器掛載到宿主的固定目錄 生產常用的

docker run -d --name volume-test2  -v /mnt/test/:/data nginx

 

 

 測試:

 

 

 

上面用-v參數來建立容器和宿主的磁盤映射關系,其實是違背了docker“一處部署,到處運行”的原則,上面的方法在Dockerfile(后文會講到)里是不支持的。

但是這樣指定磁盤映射也有好處,比如收集docker容器里的進程日志,假如在容器里再開一個logstash就不符合docker運行單進程的原則,變得臃腫,所以在所有docker容器里建一個log目錄,然后都統一映射到宿主的/opt/docker-log里,然后在宿主起一個logstash進程,通過/opt/docker-log這個目錄就能收集到所有docker進程的日志了。

 

4.2 數據卷容器 類似nfs 差不多  其實生產不用

數據卷容器的作用實現了各容器之間的數據共享,容器不論起停都不影響數據共享,如下,

新建的容器volume-test4共享了容器volume-test1的數據卷,所以新創建的volume-test4容器就有/data這個目錄,並且這個目錄下有剛才創建的文件。

 

 

可以看到它就訪問到了centos容器掛載的內容了

 

  1.  手動構建Docker鏡像,生產不常用,一般都是自動化

獲取鏡像id

 

[root@linux-node1 ~]# docker kill $(docker ps -a -q)  干掉所有運行的容器

[root@linux-node1 ~]# docker rm $(docker ps -a -q)  刪除所有容器 這種命令生產絕對不能用

容器是運行起來叫容器 鏡像是鏡像這兩個是不同概念的(禁止的狀態)

構建鏡像的話,現以官方的centos docker鏡像為基礎鏡像來創建容器,進入容器后一頓yum或者一頓make,這樣鏡像就完成了一半了,再提交就行了。

下面實例構建一個nginx的容器。

①  docker pull centos

②  docker run –it –name  nginx-man-construct centos

③  在centos容器里,安裝編譯安裝nginx所需的依賴包,

[root@962aee9a1846 /]# yum -y install wget gcc gcc-c++openssl-devel make

④  進入/usr/local/src,下載pcre,解壓pcre(不用安裝,一會安裝nginx時指定pcre的解壓目錄即可)

⑤  建立nginx的運行用戶,useradd -s /sbin/nologin -M www;

⑥  下載nginx的tar包,wget http://nginx.org/download/nginx-1.10.1.tar.gz,解壓進入nginx目錄,./configure--prefix=/usr/local/nginx-1.10 --user=www --group=www --with-http_ssl_module--with-http_stub_status_module --with-pcre=/usr/local/src/pcre-8.39 &&make && make install。

⑦  設置nginx開機自啟動,將/usr/local/nginx/sbin/nginx加到/etc/rc.local里(這是一個坑,后面會講到),但是這樣加在平常的系統(物理機或虛擬機)里是可以自啟動的,但是在容器里不行,前面說過,必須讓進程運行在前台,不然容器僅僅執行一個…./nginx的啟動命令就以為結束任務了,然后就退出容器了,所以要讓nginx在前台運行,修改nginx.conf,在頂部加一條“daemon off;”即可。

 

⑧  yum clean all。然后退出容器,exit

⑨  提交鏡像,

⑨  提交鏡像,

 

 

 做完上面的步驟就創建並提交完docker鏡像了

 

我們可以這個鏡像創建一個容器:

 

 1:修改鏡像后要重新commit;構建鏡像也可以添加自啟動命令或者參數,后面的構建Dockerfile會講到。

6. Dockerfile構建 Docker鏡像  重點中重點,難點中難點 ******

由Dockerfile自動構建鏡像,其實就是把手動構建的命令逐行寫入一個“腳本”里,只不過這個腳本有自己的語法。現把上面手動創建nginx鏡像的結果寫成dockerfile形式,你會發現超級簡單。

 

這里是創建Dockerfile時會用到的語法,下面進行實際創建。

①  mkdir -p /opt/docker-file/nginx&& cd /opt/docker-file/nginx

②  vim Dockerfile   (開頭字母必須大寫),內容見下:

# This is my first Dockerfile

# version 1.0

# Author: 盧烈楚 

#Base images

FROM centos

 

#MAINTAINER  維護者

MAINTAINER luliechu   983765387@qq.com

 

#ADD使用這個命令拷貝文件或目錄(壓縮包會自動解壓);必須把文件拷貝到Dockerfile同目錄下

ADD pcre-8.39.tar.gz /usr/local/src

ADD nginx-1.10.1.tar.gz /usr/local/src

 

 

#commands  干什么

RUN yum install -y wget gcc gcc-c++ makeopenssl-devel

RUN useradd -s /sbin/nologin -M www

 

#WORKDIR 相當於cd,切換到目錄

WORKDIR /usr/local/src/nginx-1.10.1

RUN ./configure--prefix=/usr/local/nginx-1.10 --user=www --group=www --with-http_ssl_module--with-http_stb_module --with-pcre=/usr/local/pcre-8.39http_stb_module--with-pcre=/usr/local/pcre-8.39 && make && make install

RUN echo "daemon off;" >>/usr/local/nginx-1.10/conf/nginx.conf

 

ENV PATH /usr/local/nginx-1.10/sbin:$PATH 

#對外開放80端口

EXPOSE 80

 

#容器啟動時自動執行“nginx”命令

CMD ["nginx"]

 

③  pcre-8.39.tar.gz和nginx-1.10.1.tar.gz拷貝到與Dockerfile的同級目錄下。

④  構建鏡像,docker build -t mynginx:v2 /opt/docker-file/nginx/ (-t后面跟的是鏡像名字,最后的路徑是Dockerfile的路徑)  備注:同級目錄當前目錄可以用.來代替

 

⑤  無需commit就能查到這個鏡像了。

 

 

7.  Docker核心原理-資源隔離和限制

目前通過加參數可以做到cpu和內存的資源限制,但centos6還無法限制磁盤,centos7可以限制磁盤配額。

7.1 壓測實驗cpu和內存的限制

通過壓力測試來實驗限制cpu資源;在linux下使用壓測工具:stress。

有epel源(epel6可以,epel7好像不行stress)的情況下,yum install -y stress即可完成安裝。需要在容器里安裝壓測工具,目的是壓測容器而不是壓測宿主機。

 

我們先寫一個Dockerfile來創建一個鏡像:

vim /opt/docker-file/stress-container/Dockerfile

FROM centos

ADD epel-6.repo /etc/yum.repos.d/

RUN yum -y install stress && yumclean all

ENTRYPOINT ["stress"]

 

:ENTRYPOINT ["stress"]這一行表示啟動容器后,容器立刻執行stress命令並接收參數;在有這個參數的情況下,docker run -it --rm stress1 --cpu 4 這條進入容器的命令相當於docker run -it --rm stress1  stress --cpu 4,加上一個ENTRYPOINT就省去了每次啟動容器都加這個命令了。

把epel-6.repo下載到/opt/docker-file/stress-container目錄下,然后,docker build-t stress /opt/docker-file/stress-container。

 

docker run –help可以查看dockerrun可以添加的參數,

 

7.2 cpu限制配額

 -c參數:指定該容器占用宿主機cpu的權重,也可以叫配額,默認是有1024個配額,也就是滿配額。

比如宿主機只有一個容器,同時該容器的配額是1024,那么啟動這個容器時就可以占用宿主機的100%的cpu;宿主機同樣只有一個容器,該容器的配額是512-c 512,那么啟動這個容器最多只能占用宿主機的50%的cpu。

比如有兩個容器,他倆的cpu配額都是1024,那么啟動這兩個容器時就會各占50%的cpu。

比如有兩個容器,A容器的cpu配額是1024,B容器的cpu配額是512,那么啟動這兩個容器時A容器占用66%的cpu,B容器占用33%的cpu。

 

實際測驗:

docker run -it --rm stress1 --cpu 1,這樣就啟動了一個裝有stress壓測工具的容器。

--rm是說容器結束后自動刪除容器,--cpu 1是說占用一個cpu核心來執行stress壓測實驗。

運行上面的命令后,在宿主機用top查看cpu情況,發現宿主機的cpu被這個容器占用了25%,因為我的宿主機是4核的。

結束上面的容器,然后docker run -it --rm stress1 --cpu 4,運行這個命令后,發現宿主機出來了四個stress進程,每個都占用25%,一共占用了100%的宿主機cpu。

:這里的宿主機是相對於docker來說的宿主機,這個宿主機也可能是物理機或者虛擬機。

2:安裝stress壓測工具的目的是讓容器把它所能利用的cpu資源跑滿,看看能占宿主機的百分之多少;stress這個工具會一直做運算,直到cpu跑滿。

 也可以通過—cpuset-cpus指定使用哪個cpu來運行容器,docker run –it –cpuset-cpus=0 stress,用第一個cpu來運行容器stress。

 7.3 內存限制配額

上面用-c和—cpuset-cpus來指定cpu配額和使用哪個cpu,下面來限制內存使用。

docker run -it -m 128m --rm stress1 --cpu 8 --io 4 --vm 2--vm-bytes 500M --timeout 10s “-m 128m”設置stress1這個容器最大可使用宿主機128M內存,壓測工具stress指定的500M的內存測試,所以隨着壓力增大,容器使用宿主機的內存一旦超過了128M就會觸發異常並退出。

 

8. Docker核心原理-網絡和Registry

Docker容器默認使用橋接模式。

8.1 橋接模式

 

 

 

目前起着四個容器,對應四個橋接網絡,如下圖,

啟動docker后會創建一個虛擬網橋(用brctl show命令查看),每啟動一個容器都會創建一個橋接接口

 

ip add li

 

 

宿主機和容器之間通過iptables實現端口的轉換、容器上網,如下

Iptables -t nat -Ln

 

 

 

8.2 HOST模式

每個docker容器可以選擇不同的網絡模式。

 

 

 

host模式是容器不使用network啊、namespace什么的,直接和宿主機使用同一個網絡堆棧,這樣的話容器起一個80端口,宿主機就起一個80端口,容器起一個655端口,宿主機就起一個655端口,缺點的話容器與宿主機的ip范圍、端口范圍等統統一樣;優點就是方便,假如容器的端口與宿主機沒沖突,那就可以用。

 

 9. 配置私有倉庫push  pull

9.1 下載並運行倉庫

docker pull registry

docker run –d –p 5005:5000 registry。registry的默認運行端口是5000,如果本機5000端口被占用了,可以指定一個別的端口。

9.2 找一個已有鏡像打tag

docker tag zhangshanci/my-nginx:v3192.168.0.55:5005/test/nginx:v1 “zhangshanci/my-nginx:v3”是鏡像的名稱,“192.168.0.55:5005/test/nginx:v1”是要存到倉庫里的名稱。

 

9.3 push鏡像

高版本的docker在push時要求有ssl數字證書,官網有三種解決辦法:

①  購買一個ssl證書,在所有docker容器前端配置一個nginx做反向代理;

②  將下圖紅圈里的參數加到/etc/sysconfig/docker的啟動參數里;

③  自己制作一個證書,不過還是得加參數,不如方法二方便還。

 

 

 

修改/etc/sysconfig/docker文件,添加啟動參數:

 

:這個參數也必須添加到要pull的機器上。

 

9.4 改完/etc/sysconfig/docker后重啟docker、啟動registry

 

 

重新push鏡像:

 

這樣push上去后,別的機器可以再pull拉下來,但是必須指定倉庫的名稱,如果不指定倉庫名稱,默認是從docker hubpull鏡像。

 

9.5.1 修改/etc/sysconfig/docker,添加一個啟動參數

 

 

9.5.2 pull鏡像

 

這是一個裝有nginx的鏡像,以它為鏡像啟動一個容器,

docker run -it -p :80 30ff66a25ec4/usr/local/nginx-1.10/sbin/nginx

這樣iptables –t nat –L -n就能看到本地有一個端口與容器的80端口對應,打開瀏覽器,輸入ip:port就可以訪問到容器里的nginx了。

10生產構建docker鏡像核心思想,生產案例演示

架構架構  分層設計

 

docker生產實踐

 

系統層  centos

運行環境層  tomcat  php

 

應用服務層    shopping  按業務來分  (配置文件代碼)

寫好的結構如下:寫好之后再提交

 

 

 

 

案例寫一個純系統鏡像:

# Docker for CentOS

 

#Base image

FROM centos

 

#Who

MAINTAINER luliechu 983765387@qq.com

 

#EPEL

ADD epel.repo /etc/yum.repos.d/

 

#Base pkg

RUN yum install -y wget mysql-devel supervisor git redis tree net-tools sudo psmisc && yum clean all

 

 

寫一個帶ssh的純系統鏡像:

# Docker for CentOS

 

#Base image

FROM centos

 

#Who

MAINTAINER luliechu 983765387@qq.com

 

#EPEL

ADD epel.repo /etc/yum.repos.d/

 

#Base pkg

RUN yum install -y openssh-clients openssl-devel openssh-server wget mysql-devel supervisor git redis tree net-tools sudo psmisc && yum clean all

 

# For SSHD

 

 

RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key

RUN ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key

RUN echo "root:123" | chpasswd

 

 

在系統上寫一個基於純系統上python環境

#Base image

FROM test/centos:base

 

#Maintainer

MAINTAINER luliechu  9837653887@qq.com

 

# Python env

RUN yum install -y python-devel python-pip supervisor

 

# Upgrade pip

RUN pip install --upgrade pip

 

 

在帶ssh系統上寫一個基於上搭建python環境

#Base image

FROM test/centos-ssh

 

#Maintainer

MAINTAINER luliechu 983765387@qq.com

# Python env

RUN yum install -y python-devel python-pip supervisor

 

# Upgrade pip

RUN pip install --upgrade pip

 

 

部署應用

 

 

Dockerfile 如下:

Base image

FROM test/python-ssh

 

#Maintainer

MAINTAINER luliechu 983765387@qq.com

 

# Add www user

RUN useradd -s /sbin/nologin -M www

 

# ADD file

ADD app.py /opt/app.py

ADD requirements.txt /opt/

ADD supervisord.conf /etc/supervisord.conf

ADD app-supervisor.ini /etc/supervisord.d/

 

# pip

RUN /usr/bin/pip2.7 install -r /opt/requirements.txt

 

# Port

EXPOSE 22 5000

 

#CMD

CMD ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"]

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM