環境篇:Docker

  • 2020 年 3 月 26 日
  • 筆記

Docker

www.docker.com

Docker 是什麼?

Docker 是一個開源的應用容器引擎,基於Go語言並遵從Apache協議的開源,讓開發者可以打包他們的應用以及依賴包到一個可移植的鏡像中,然後發布到任何流行的 Linux或Windows 機器上,也可以實現虛擬化。容器是完全使用沙箱機制,相互之間不會有任何介面。

如果沒有Docker

環境和配置變動,導致項目等不能簡單的部署成功,我們將需要的配置、系統、數據等等整體打包成我們需要的鏡像,簡單啟動就可以了,

Securely build and share any application, anywhere一次構建,處處運行。

  • 虛擬機和容器化的區別?
    • 虛擬機:整套安裝環境的一種解決方案,它可以在一種作業系統裡面運行另一個作業系統,比如在Windows系統裡面運行Linux系統。應用程式對此沒有感知,因為虛擬機看上去就和真實的作業系統一模一樣,能夠使應用程式,作業系統和硬體三者之間的邏輯不變,而對於底層系統來說,虛擬機就是一個普通文件,不需要了就刪掉。

    • 虛擬機佔用的資源多、步驟多,啟動是分鐘級的太慢。

    • 容器化技術:因為如上的問題,Linux發展出了另一種虛擬化技術,Linux容器(Linux Containers縮寫LXC)。Linux容器不是模擬一個完整的作業系統,而是對程式進行隔離。有了容器,就可以將軟體運行所需要的所有資源打包到一個隔離的容器中,容器和虛擬機不同,不需要捆綁一整套的作業系統,只需要軟體工作所需要的庫資源和設置。系統因此而變得高效輕量並保證部署在任何環境中的軟體都能始終如一的運行。

1 Docker架構

  • Docker 包括三個基本概念:
    • 鏡像(Image):Docker 鏡像(Image),就相當於是一個 root 文件系統。比如官方鏡像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系統的 root 文件系統。
    • 容器(Container):鏡像(Image)和容器(Container)的關係,就像是面向對象程式設計中的類和實例一樣,鏡像是靜態的定義,容器是鏡像運行時的實體。容器可以被創建、啟動、停止、刪除、暫停等。
    • 倉庫(Repository):倉庫可看著一個程式碼控制中心,用來保存鏡像。
Docker 面向對象
鏡像
容器 對象

概念 說明
Docker 鏡像(Images) Docker 鏡像是用於創建 Docker 容器的模板,比如 Ubuntu 系統。
Docker 容器(Container) 容器是獨立運行的一個或一組應用,是鏡像運行時的實體。
Docker 客戶端(Client) Docker 客戶端通過命令行或者其他工具使用 Docker SDK (https://docs.docker.com/develop/sdk/) 與 Docker 的守護進程通訊。
Docker 主機(Host) 一個物理或者虛擬的機器用於執行 Docker 守護進程和容器。
Docker Registry Docker 倉庫用來保存鏡像,可以理解為程式碼控制中的程式碼倉庫。Docker Hub(https://hub.docker.com) 提供了龐大的鏡像集合供使用。一個 Docker Registry 中可以包含多個倉庫(Repository);每個倉庫可以包含多個標籤(Tag);每個標籤對應一個鏡像。通常,一個倉庫會包含同一個軟體不同版本的鏡像,而標籤就常用於對應該軟體的各個版本。我們可以通過 <倉庫名>:<標籤> 的格式來指定具體是這個軟體哪個版本的鏡像。如果不給出標籤,將以 latest 作為默認標籤。
Docker Machine Docker Machine是一個簡化Docker安裝的命令行工具,通過一個簡單的命令行即可在相應的平台上安裝Docker,比如VirtualBox、 Digital Ocean、Microsoft Azure。

2 Docker安裝

  • 以centos7以上為例。(安裝2019.03版本)
  1. 刪除老版本
yum -y  remove docker                     docker-client                     docker-client-latest                     docker-common                     docker-latest                     docker-latest-logrotate                     docker-logrotate                     docker-engine  
  1. 安裝需要的軟體包
yum install -y yum-utils device-mapper-persistent-data lvm2  
  1. 設置穩定儲存庫
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo  
  1. 更新yum軟體包索引
yum makecache fast  
  1. 安裝最新版本的Docker Engine-Community和containerd
yum -y install docker-ce docker-ce-cli containerd.io  
  1. 啟動
systemctl start docker  
  1. 設置開機啟動
systemctl enable docker  
  1. 測試
#版本  docker version  
  1. 配置阿里雲鏡像加速

訪問阿里雲鏡像加速器網頁

設置密碼盡量簡單如:docker123

如果覺得不方便可以使用網易雲加速,地址更改如下

#1  mkdir -p /etc/docker    #2  tee /etc/docker/daemon.json <<-'EOF'  {  "registry-mirrors": ["http://hub-mirror.c.163.com"]  }  EOF    #3  systemctl daemon-reload    #4  systemctl restart docker  
  1. hello-world鏡像
docker run hello-world  

3 Docker 命令

3.1 幫助命令

docker help  

3.2 查看本地鏡像

docker images  

-a:顯示所有的鏡像

-q:僅顯示id

REPOSITORY 鏡像倉庫源
TAG 鏡像標籤
IMAGE ID 鏡像ID
CREATED 鏡像創建時間
SIZE 鏡像大小

同一個REPOSITORY(倉庫源)可以有多個TAG,代表這個倉庫源的不同版本,使用REPOSITORY:TAG來定義不同的鏡像。

如果不指定一個鏡像的版本標籤,例如:使用hello-world,docker將默認使用hello-world:latest鏡像

3.3 查詢鏡像

docker search 需要的鏡像  

https://hub.docker.com/上去搜索需要的軟體,經常搭配-s參數查詢點贊數比較高的鏡像

3.4 下載鏡像

docker pull 需要的鏡像:需要的版本tag  

3.5 刪除鏡像

#刪除單個  docker rmi -f 鏡像ID  #刪除多個  docker rmi -f 鏡像名1:TAG 鏡像名2:TAG  #刪除全部  docker rmi -f ${docker images -qa}  

3.6 查看容器

docker ps  

-a:顯示所有的容器

-l:顯示最近一條容器

-n:顯示最近幾條容器

-q:僅顯示id

3.7 新建啟動停止容器

#新建容器並啟動,如果沒有鏡像,會先去hubdocker上pull鏡像  docker run 可選參數  鏡像名(或ID)  #重啟容器  docker restart 容器名(或ID)  #停止容器(普通<==>強制)  docker stop 容器名(或ID) <==>   docker kill 容器名(或ID)  #啟動之前創建的容器  docker start 容器名(或ID)  #刪除之前創建的容器<==>批量  docker rm -f 容器ID	<==>	docker ps -aq | xargs docker rm  

-d:守護式後台運行容器,並返回容器ID(如使用tomcat)

-v:數據卷,指定主機的某個目錄為容器的某個目錄(如使用tomcat-> /root/tomcat/:/usr/local/tomcat/webapps/)

-i:互動式運行容器,通常-t一起使用(如使用linux中的linux)

-t:為容器重新分配一個偽輸入終端,通常與-i一起使用(如使用linux中的linux)

–name="新容器名字":為容器指定一個名稱

-P:隨機埠映射

-p:指定埠映射,有以下4種格式

​ ip:hostPort:containerPort

​ ip::containerPort

​ hostPort:containerPort

​ containerPort

3.7.1 守護式例子

#新建啟動容器  docker run --name="tomcat1" -dp 8888:8080  tomcat:8.0.52  

3.7.2 互交式例子

#1 新建啟動容器,如下圖中目錄變更為容器ID  docker run --name='centos1' -it centos  

#2 退出容器  exit	-->容器停止退出  ctrl+p+q	-->容器不停止退出(注意有先後順序)  

#3 進入一個運行的容器  docker exec -it 容器名(或ID) /bin/bash  

3.8 提交容器

docker commit -a='作者' -m='修改內容' 容器名(或ID) 容器前綴/容器名:TAG號  
  • 使用上面守護式例子繼續
#進入容器目錄  docker exec -it tomcat1 /bin/bash  #替換index.jsp內容  cat > webapps/ROOT/index.jsp << EOF  Hello Tomcat  EOF  

#提交容器  docker commit -a='Heaton' -m='my tomcat test' tomcat1 heaton/tomcat:0.0.1  

#刪除現有的運行容器  docker rm -f $(docker ps -q)  #運行之前自己構建的鏡像容器  docker run --name="tomcat1" -dp 8888:8080  heaton/tomcat:0.0.1  

3.9 上傳鏡像

  • 選擇阿里雲或者hub,如下是阿里雲的上傳方式

#登錄阿里雲docker倉庫,輸入密碼  dockerlogin [email protected] registry.cn-hangzhou.aliyuncs.com  

#標記tag  docker tag b60d74c216b8 registry.cn-hangzhou.aliyuncs.com/docker-tzy/rep1:0.0.1  #上傳  docker push registry.cn-hangzhou.aliyuncs.com/docker-tzy/rep1:0.0.1  

4 容器數據卷

Docker容器產生的數據,如果不通過commit生成新的鏡像,持久化,那麼容器刪除以後,數據就沒有了。

為了能保存數據在docker中我們使用數據卷。

  • 數據卷可以在容器之間共享或重用數據
  • 卷中的更改可以直接生效
  • 數據卷中的更改不會包含在鏡像的更新中
  • 數據卷的生命周期一直持續到沒有容器使用它為止

docker inspect 容器ID –> 返回Docker對象的資訊(查看掛載情況)

4.1 例1(命令-v)

#創建可讀可寫  docker run -it -v /my_root:/my_docker centos  #創建可讀不可寫(Read-only)  #docker run -it -v /my_root:/my_docker:ro centos  


#進入綁定文件夾,主機建立新文件  touch root.txt  

#進入綁定文件夾,容器修改文件  echo "docker add" > root.txt  


#停止容器,主機修改文件  echo "root add" > root.txt  #在重新啟動容器  docker start -i 34fe34e36ada  

4.2 例2(DockerFile)

#創建Dockerfile文件   vim dockerFile,寫入如下內容  #效果為docker run -it -v /my_root:/my_docker centos    FROM centos  VOLUME ["my_docker1","my_docker2"]  CMD echo "success"  CMD /bin/bash  

#構建鏡像  docker build -f /Dockerfile -t mybuild/centos:0.0.1 .  

#運行,發現有2個容器卷  docker run -it mybuild/centos:0.0.1  

如例1進行數據卷測試,發現數據共享

4.3 例3(volumes-from)

容器間數據共享

#運行容器1  docker run -it --name docker1 mybuild/centos:0.0.1  #運行容器2  docker run -it --name docker2 --volumes-from docker1 mybuild/centos:0.0.1  #運行容器3  docker run -it --name docker3 --volumes-from docker2 mybuild/centos:0.0.1  

如例1進行數據卷測試

5 Dockerfile

Dockerfile是用來構建Docker鏡像的構建文件,是由一系列命令和參數構成的腳本。

Java HelloWord.java HelloWord.class
Docker images DockerFile
  • 基礎注意點

    • 每條保留字指令必須為大寫字母且後面需要更至少一個參數
    • 指令從上到下循序執行
    • #為注釋
    • 每條指令都會創建一個鏡像層且對鏡像進行提交
  • 執行流程

    1. docker從基礎鏡像運行一個容器
    2. 執行一條指令並對容器做出修改
    3. 執行類似commit操作提交一個新的鏡像層
    4. 再基於剛提交的鏡像運行一個新容器
    5. 繼續執行dockerfile中的下一條指令,循環制所有指令完成
  • 保留字

FROM 基礎鏡像,當前鏡像是基於那個鏡像的。
MAINTAINER 作者 郵箱。
RUN 容器構建時需要運行的命令。
EXPOSE 暴露埠號 啟動容器的時候還需使用 –p 指定埠。
WORKDIR 指定在創建容器後,終端默認登錄後進來的工作目錄,一個落腳點,默認根目錄,通常絕對路徑,CMD ENTRYPOINT 都會在這個目錄下執行。
ENV 構建鏡像的過程中設置環境變數, 構建和運行時都有效可以使用$引用。
ADD 將宿主機目錄下的文件拷貝到鏡像且會自動處理URL和 解壓tar 壓縮包。ADD 支援 URL 和 COPY後解壓縮包。
COPY 拷貝文件和目錄到鏡像中,將從構建上下文目錄中<源路徑>的文件/複製到新的一層鏡像內<目標路徑>的位置。一般都用ADD
VOLUME 容器數據卷, 數據保存和持久化。
USER 指定該鏡像由什麼用戶運行 不指定由root 運行。
CMD 指定容器啟動時要運行默認的命令,Dockerfile中可以有多個cmd , 但只有最後一個生效。CMD 會被docker run 之後的參數替換。
ENTERPOINT 指定容器啟動時要運行的命令。ENTERPOINT docker run 之後的參數會被當做參數傳遞給ENTRYPOINT , 之後形成新的命令組合,追加
ONBUILD 觸發器, 當構建一個被繼承的dockerfile時運行命令, 父鏡像在被子繼承後的父鏡像的onbuild 被觸發。
  • CMD 與 ENTERPOINT區別
  • CMD

如 tomcat中,在Dockerfile最後有CMD ["catalina.sh","run"],意思為啟動容器後執行tomcat啟動命令,如果使用命令docker run -it -p 8888:8080 tomcat:8.0.52 ls -l,就會將ls -l這個查詢指令通過參數傳給CMD,這時容器運行就不會啟動,而是查詢目錄。

  • ENTERPOINT

如果是CMD ["ls","-l"]指令,我們需要在加入一個 -a 的參數,那麼CMD將不能完成在構建鏡像後增加參數,這個時候可以把指令改成ENTERPOINT ["ls","-l"] ,我們就可以在後面繼續追加參數而不會替換原來的參數。

5.1 例1 拓展centos

  1. 自建centos
  2. 修改運行後路徑
  3. 使之可以使用vim,ifconfig等命令
  • 創建Dockerfile文件,加入如下內容
#繼承自centos  FROM centos  #作者-郵箱  MAINTAINER Heaton  #創建環境變數mypath  ENV mypath /usr/local/src  #指定創建容器後終端路徑  WORKDIR $mypath  #構建容器時運行命令  RUN yum -y install vim  RUN yum -y install net-tools  #暴露埠號  EXPOSE 80  #容器啟動時要運行默認的命令  CMD echo "success"  CMD /bin/bash  
  • 構建鏡像
docker build -f /root/Dockerfile -t heaton/centos:0.0.1 .  




  • 運行鏡像
docker run -it heaton/centos:0.0.1  

5.2 例2 觸發器

  • 創建Dockerfile1文件,加入如下內容
#繼承自centos  FROM centos  ONBUILD RUN echo "father onbuild----------------------------->"  
  • 構建
docker build -f /root/Dockerfile1 -t heaton/father .  

  • 創建Dockerfile2文件,加入如下內容
#繼承自heaton/father  FROM heaton/father  RUN echo "son------>success"  
  • 構建
docker build -f /root/Dockerfile2 -t heaton/son .