Docker基礎(狂神說Docker課程筆記)


課程鏈接

https://www.bilibili.com/video/BV1og4y1q7M4?from=search&seid=18106350651153543104

Docker為什么出現?

  • 開發和運維兩套環境,而環境配置十分麻煩。
    如在Windows上開發,要發布到Linux上運行。Docker給以上問題提出了解決方案:
    Java --- Jar(環境)---打包項目帶上環境(鏡像)---Docker倉庫(應用商店)---下載鏡像---直接運行
  • Docker的思想來自於集裝箱,核心思想:隔離。
    即將應用打包裝箱,每個箱子是互相隔離的,可以將服務器利用到極致。
虛擬機 Docker
linux centos原生鏡像(一個電腦) 隔離鏡像(最核心的環境 +jdk +mysql等)
需要開啟多個虛擬機 運行鏡像就可以了
幾GB 幾MB

官方文檔

https://docs.docker.com/

倉庫地址

https://hub.docker.com/

Docker能做什么?

傳統虛擬機與Docker對比

20201209124302

Docker的優點

  • 不模擬完整的操作系統,系統內核(kernel)非常小,更少的抽象層(GuestOS:如Centos)
  • 容器內的應用直接運行在宿主機的內核,容器本身沒有自己的內核,也沒有虛擬硬件。
  • 每個容器相互隔離,內部都有屬於自己的文件系統,互不影響。

Docker實現DevOps(開發、運維)

  • 應用更快速的交付和部署
    打包鏡像發布測試,一鍵運行;不再需要寫大量幫助文檔,安裝程序
  • 更便捷的升級和擴縮容?
    部署應用就和搭積木一樣
  • 更簡單的系統運維
    開發和測試的環境高度一致
  • 更高效的計算資源利用
    內核級別的虛擬化,可以在一個物理機上運行很多的容器實例,服務器性能可以被壓榨到極致。

Docker的基本組成

20201208171750

  • 鏡像(image):鏡像是一種輕量級、可執行的獨立軟件包,用來打包軟件運行環境和基於運行環境開發的軟件。它包含運行某個軟件所需的所有內容,包括代碼、運行時、庫、環境變量和配置文件。相當於一個模板,通過這個模板來創建容器服務,可以通過一個鏡像創建多個容器。
  • 容器(container):獨立運行一個或一組應用/基本命令有:啟動,停止,刪除等/可理解為一個簡單的linux系統。
  • 倉庫(repository):存放鏡像的地方(公有/私有)

Docker運行原理

Docker是一個Client-Server結構的系統,以守護進程運行在主機上。通過Socket從客戶端進行訪問。

Docker的常用命令

20201212210110

幫助命令

docker --help            # 幫助信息
docker info              # 系統信息,包括鏡像和容器的數量

幫助文檔地址:https://docs.docker.com/engine/reference/

鏡像命令

docker search 鏡像名      # 搜索鏡像
docker pull 鏡像名        # 下載鏡像

Docker采用聯合文件系統,不同鏡像的相同文件無需再次下載:
20201212192925

docker rmi 鏡像名/id      刪除鏡像

容器命令

docker run [options] 鏡像名/id [command]  # 建立容器並啟動:           
[options]:                  
            --name=容器名                 # 命名容器以區分不同容器
            -d                           # 在后台運行容器(必須有一個前台進程,否則進程會自動關閉)
	    -it                          # 使用交互方式運行,進入容器查看內容
	    -p 主機端口:容器端口            # 暴露指定容器端口
	    -P                           # 暴露容器所有端口
[command]:
            /bin/bash                    # 控制台

2

Exit                         # 從容器中退回主機 
CTRL+Q+P                     # 容器不停止退出
docker ps                    # 顯示當前運行的容器 
          -a                 # 帶出歷史運行過的容器
docker rm 容器名/id           # 刪除指定容器
docker rm &(docker ps -aq)   # 刪除全部容器

其他命令

docker start/restart/stop/kill 容器名/id               
docker logs -tf --tail 顯示的日志條數 容器名/id  # 查看日志
docker top 容器名/id                 # 查看容器中的進程信息
docker inspect 容器名/id             # 查看鏡像的元數據
docker exec -it 容器名/id /bin/bash  # 通常容器以后台方式運行,需要進入其中修改配置:進入容器后開啟一個新終端         
docker attach 容器名/id              # 進入容器正在執行的終端
docker cp 容器名/id:容器內路徑 主機文件路徑       # 從容器內拷貝文件到主機上

Docker鏡像詳解

133

UnionFS(聯合文件系統)

  • 聯合文件系統(UnionFS)是一種分層、輕量級並且高性能的文件系統,它支持對文件系統的修改作為一次提交來一層層的疊加,同時可以將不同目錄掛載到同一個虛擬文件系統下。聯合文件系統是 Docker 鏡像的基礎。鏡像可以通過分層來進行繼承,基於基礎鏡像(沒有父鏡像),可以制作各種具體的應用鏡像。
  • 特性:一次同時加載多個文件系統,但從外面看起來只能看到一個文件系統。聯合加載會把各層文件系統疊加起來,這樣最終的文件系統會包含所有底層的文件和目錄。

鏡像加載原理

Docker的鏡像實際由一層一層的文件系統組成:

  • bootfs(boot file system)主要包含bootloader和kernel。bootloader主要是引導加載kernel,完成后整個內核就都在內存中了。此時內存的使用權已由bootfs轉交給內核,系統卸載bootfs。可以被不同的Linux發行版公用。
  • rootfs(root file system),包含典型Linux系統中的/dev,/proc,/bin,/etc等標准目錄和文件。rootfs就是各種不同操作系統發行版(Ubuntu,Centos等)。因為底層直接用Host的kernel,rootfs只包含最基本的命令,工具和程序就可以了。
  • 分層理解
    所有的Docker鏡像都起始於一個基礎鏡像層,當進行修改或增加新的內容時,就會在當前鏡像層之上,創建新的容器層。
    容器在啟動時會在鏡像最外層上建立一層可讀寫的容器層(R/W),而鏡像層是只讀的(R/O)。
    20201208183559
docker commit -m="描述信息" -a="作者" 容器id 目標鏡像名:[tag]  # 編輯容器后提交容器成為一個新鏡像

容器數據卷

20201208183759

什么是容器數據卷?

為了實現數據持久化,使容器之間可以共享數據。可以將容器內的目錄,掛載到宿主機上或其他容器內,實現同步和共享的操作。即使將容器刪除,掛載到本地的數據卷也不會丟失。

使用容器數據卷

使用命令:

dokcer run -it -v 主機內目錄:容器內目錄 鏡像名/id

將容器內目錄掛載到主機內目錄上,通過docker inspect命令查看該容器即可以看到掛載信息:
20201211162429
建立掛載關系后,只要使用命令在主機內新建一個文件:

touch /home/mountdir/test.txt

就會在容器內的掛載目錄下發現相同的文件(test.txt),從而實現了容器和主機的文件同步和共享:
20201211162933

匿名掛載

docker run -d  -v 容器內目錄  鏡像名/id  # 匿名掛載

匿名掛載后,使用docker volume ls命令查看所有掛載的卷:
20201208184201
每一個VOLUME NAME對應一個掛載的卷,由於掛載時未指定主機目錄,因此無法直接找到目錄。

具名掛載

docker run -d  -v 卷名:容器內目錄  鏡像名/id  # 具名掛載

20201211164244
可以發現掛載的卷:volume01,並通過docker volume inspect 卷名 命令找到主機內目錄:
20201211164505

所有docker容器內的卷,在未指定主機內目錄時,都在:/var/lib/docker/volumes/卷名/_data 下,可通過具名掛載可以方便的找到卷,因此廣泛使用這種方式進行掛載。

數據卷容器

20201208184546

docker run -it --name container02 --volumes from container01 鏡像名/id  # 將兩個容器進行掛載

DockerFile

Dockerfile是用來構建docker鏡像的文件

構建步驟:

編寫一個dockerfile文件,隨后運行命令:

docker build -f 文件路徑 -t 標簽 .  # 文件名為Dockerfile時可省略且最后的.不要忽略
docker run     # 運行鏡像
docker push    # 發布鏡像

dockerfile命令

命令 效果
FROM 基礎鏡像:Centos/Ubuntu
MAINTAINER 鏡像作者+郵箱
RUN 鏡像構建的時候需要運行的命令
ADD 為鏡像添加內容(壓縮包)
WORKDIR 鏡像工作目錄(進入容器時的目錄)
VOLUME 掛載的目錄
EXPOSE 暴露端口配置
CMD/ENTRYPOINT 指定這個容器啟動時要運行的命令(CMD替代先前命令,ENTRYPOINT在先前命令后追加)
COPY 類似於ADD,將文件拷貝到鏡像中
ENV 構建時設置環境變量

構建過程

  • 每個保留關鍵字(指令)都必須是大寫字母
  • 從上到下順序執行
  • "#" 表示注釋
  • 每一個指令都會創建提交一個新的鏡像層並提交

構建實例

20201208185616

Docker網絡

理解Doker0

通過命令ip addr查看本地ip地址,我們發現除了本機回環地址和埃里遠的內網地址外,還多了一個網卡:Docker0,這是Docker服務啟動后自動生成的。
20201211165741
而如果進入一個正在后台運行的tomcat容器,同樣使用ip addr命令,發現容器得到了一個新的網絡:12: eth@if13,ip地址:172.17.0.2。這是Docker在容器啟動時為其分配的。
1607676753(1)
思考一個問題:此時我們的linux主機可以ping通容器內部(172.17.0.2)嗎?(注意與容器暴露端口相區分
20201211170424

  • linux可以ping通docker容器內部,因為docker0的ip地址為172.17.0.1,容器為172.17.0.2
  • 原理:我們每啟動一個docker容器,docker就會給容器分配一個默認的可用ip,我們只要安裝了docker,就會有一個網卡docker0(bridge)。網卡采用橋接模式,並使用veth-pair技術(veth-pair就是一堆虛擬設備接口,成對出現,一段連着協議,一段彼此相連,充當一個橋梁。)。
  • 這時我們退出容器,回到主機再次觀察主機的ip地址:
    20201211170810
    我們驚奇地發現了一個新網絡13: vethda1df4b@if12,對應容器內網絡地址的12: eth@if13
  • 容器和容器之間是可以互相ping通的:容器1→Docker0→容器2
    20210131140833
    docker中的所有網絡接口都是虛擬的 ,轉發效率高。刪除容器后,對應的網橋也隨之刪除。

若編寫一個微服務並連接數據庫,如果數據庫ip改變,如何根據容器名而不是ip訪問容器?顯然,直接使用容器名是無法ping通容器內部的:
20201212200850
這時我們可以在容器啟動命令中加入一個選項:--link,使得我們可以根據容器名來訪問容器。

docker run -d -P --link 容器名/id 鏡像名/id

20201212200748
然而反向就不可以ping通,這是因為--link的本質是把需要連接的容器名/id寫入啟動容器的配置文件中,即增加了一個ip和容器名/id的映射:
20201212201930
目前已經不建議使用這種方式。

自定義網絡

我們使用命令:

docker network ls    # 查看所有的docker網絡

20201212202126
docker中的網絡模式有:

  • bridge:橋接(docker默認)/
  • none:不配置網絡 /
  • host:和宿主機共享網絡

docker run 命令默認帶有一個參數--net bridge,此處的bridge指的就是docker0。如果我們不想使用docker0,那如何創建一個新的網絡呢?

docker  network create --driver 網絡模式 --subnet 子網ip --gateway 網關 網絡名         

20201212205640
我們不僅在docker network ls命令下發現了這個新創建的網絡newnet,還可以使用docker network inspect命令查看其詳細信息,包括了我們創建時定義的子網ip和網關:
20201212202733
只要兩個容器啟動時都通過 --net,選用了同一個已創建的網絡,不同容器間即可通過ip地址或容器名/id連通:
20201212203023

網絡連通

20201212204434
對於建立在不同網絡下(docker0, newnet)的兩個容器tomcat01和tomcat02,他們的網段不同,因此是無法彼此ping通容器內部的:
20201212204311
這時我們需要通過docker network connect命令打通容器與網絡之間的連接:

docker network connect 網絡名 容器名/id

20201212203803
這個功能類似於將一個容器賦予多個ip地址,同樣可以用docker network inspect命令查看網絡連通后,該網絡的變化:
20201212204235
原本newnet網絡中只含有tomcat02,現在增加了tomcat01,因此可以連通。


免責聲明!

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



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