1. 程式人生 > >構建docker映象

構建docker映象

1.建立Docker Hub賬號

  • 登入
$ sudo docker login

2.用docker commit命令建立映象

  • 建立一個要進行修改的定製容器
$ sudo docker run -i -t ubuntu /bin/bash                   
[email protected]:/# 
  • 在容器中安裝apache軟體包
[email protected]:/# apt-get -yqq update
[email protected]:/# apt-get -y install apache2
  • 提交定製容器
$ sudo docker commit 7dfcf4332617 hiekay/apache2
  • 檢查新建立的映象
$ sudo docker images hiekay/apache2   
          
REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
hiekay/apache2      latest              d36fa6c04e5b        About a minute ago   205MB
  • 提交另一個新的定製容器
$ sudo docker commit -m="A new custom image" --author="hiekay" 7dfcf4332617 hiekay/apache2:webserver

解析: -m 指定提交資訊,–author指定作者資訊, ID:7dfcf4332617 ,hiekay/apache2 使用者名稱和倉庫名, 標籤:webserver

  • 檢視映象的詳細資訊
$ sudo docker inspect  hiekay/apache2:webserver                                                      

 
[
    {
        "Id": "sha256:dfda6a2c29aac1aa25b188f5b5f1a8b0d6cf63c92df0bacb4f062be312ebe9c2",
        "RepoTags": [
            "hiekay/apache2:webserver"
        ],
........
  • 執行新容器
$ sudo docker run -i -t hiekay/apache2:webserver /bin/bash
[email protected]:/# 

3.用Dockerfile建立映象

用Dockerfile的自定義檔案和docker build 命令來構建映象.Dockerfile使用基本的基於DSL語法的指令來構建一個Docker映象,之後使用docker build命令基於該Dockerfile中的指令構建一個新的映象.

建立第一個Dockerfile
  • 建立一個示例倉庫
$ mkdir static_web
$ cd static_web
$ touch Dockerfile

目錄static_web 用來儲存Dockefile ,這個目錄也是我們的構建環境, Docker稱此環境為上下文或者構建上下文. Docker 會在構建映象時將構建上下文和該上下文中的檔案和目錄上傳到Docker守護程序.

  • 第一個Dockerfile 例子: 建立一個空Dockerfile,通過Dockerfile 構建一個能作為Web伺服器的Docker映象.
#Version: 0.0.1
FROM ubuntu:18.04
MAINTAINER hiekay "[email protected]"
RUN apt-get update
RUN apt-get install -y nginx
RUN echo 'Hi,I am in your container' > /usr/share/nginx/html/index.html
EXPOSE 80

該Dockerfile由一系列指令和引數組成. 每條指令,如FROM都必須大寫,後面跟一個引數. 指令會按順序從上到下執行. 每條指令都會去建立一個新的映象層並對映象進行提交.

流程:
  • Docker從基礎映象執行一個容器.
  • 執行一條指令,對容器做出修改.
  • 執行類似docker commit 的操作,提交一個新的映象層.
  • Docker再基於剛提交的映象執行一個新容器.
  • 執行Dockerfile中的下一個指令,直到所有指令都執行完畢. 所以,如果Dockerfile某些原因(某指令失敗了)沒有正常結束.也將得到一個可以使用的映象.
解析
  • 每個Docker的第一條指令都應該是FROM,FROM指令指定了一個已經存在的映象,後續指令都將基於該映象進行,這個映象被稱為基礎映象.
  • MAINTAINER指令設定作者和郵箱
  • RUN指令,會在當前映象中執行指定的命令,預設RUN指令會在shell中使用命令包裝器/bin/sh -c 執行. 如果是在一個不支援shell的平臺或者不希望在shell中執行,可以用exec 格式的RUN指令 如:
RUN [ "apt-get", " install ", "-y", "nginx" ]

在這種方式中,使用一個數組來指定要執行的命令和傳遞給該命令的每個引數.

  • EXPOSE指令,是設定容器的指定埠. 也可以指定多個埠.

4.基於Dockerfile構建新映象

執行docker build 命令時,Dockerfile中的所有命令都會執行並提交,成功結束後返回一個新映象.

  • 執行Dockerfile
$ cd static_web
$ sudo docker build -t="hiekay/static_web" . 
//開始執行
sending build context to Docker daemon  2.048kB
Step 1/6 : FROM ubuntu:18.04
18.04: Pulling from library/ubuntu
Digest: sha256:29934af957c53004d7fb6340139880d23fb1952505a15d69a03af0d1418878cb
Status: Downloaded newer image for ubuntu:18.04
 ---> ea4c82dcd15a
Step 2/6 : MAINTAINER hiekay "[email protected]"
 ---> Running in 82ebf098abd8
Removing intermediate container 82ebf098abd8
 ---> b8405a62db26
Step 3/6 : RUN apt-get update

其中 -t 選項設定了倉庫和名稱. 還可以設定標籤:

sudo docker build -t="hiekay/static_web:v1" . 

如果不設定標籤,預設標籤是latest標籤. 命令最後的 . 告訴Docker到本地目錄去找Dockerfile , 也可以指定一個git 倉庫的源地址來指定Dockerfile的地址 如:

sudo docker build -t="hiekay/static_web:v1" [email protected]:hiekay/docker-static-_web

在該git倉庫根目錄下存摺Dockerfile檔案. 其中: sending build context to Docker daemon 2.048kB 是將構建上下文上傳到Docker守護程序.

  • 注意: 如果在構建上下文的根目錄下存在.dockerignore命名的檔案, 這個該檔案用來設定哪些檔案不會被上傳到構建上下文中.

5.指令失敗時會怎樣

假如在第四部寫錯了:ngin

$ cd static_web
$ sudo docker build -t="hiekay/static_web" . 
//開始執行
Sending build context to Docker daemon  2.048kB
Step 1/6 : FROM ubuntu:18.04
 ---> ea4c82dcd15a
Step 2/6 : MAINTAINER hiekay "[email protected]"
 ---> Using cache
 ---> b8405a62db26
Step 3/6 : RUN apt-get update
 ---> Using cache
 ---> a7b7791c3818
Step 4/6 : RUN apt-get install -y ngin
 ---> Running in fabeeceeefe2
Reading package lists...
Building dependency tree...
Reading state information...
E: Unable to locate package ngin
The command '/bin/sh -c apt-get install -y ngin' returned a non-zero code: 100

報錯,E: Unable to locate package ngin 最後成功的一層ID是:a7b7791c3818

  • 基於最後成功步驟建立新容器 再執行: apt-get install -y ngin 並指定正確的包名,進一步除錯,解決問題.就可以退出容器了,使用正確的報名修改Dockerfile,之後再進行構建.
$ sudo docker run -i -t a7b7791c3818 /bin/bash
[email protected]:/# 
[email protected]:/# apt-get install -y ngin

6.Dockerfile 和構建快取

因為每一步的構建過程都會將結果提交為映象,所以它會將之前的映象層看做快取.

  • 忽略Dockerfile的構建快取
$ sudo docker build --no-cache -t="hiekay/static_web" .

7.基於構建快取的Dockerfile模板

構建快取的好處是可以實現簡單的Dockerfile模板.在自己的Dockerfile檔案頂部使用相同的指令模板,比如Ubuntu.

  • Ubuntu系統的Dockerfile模板
#Version: 0.0.1
FROM ubuntu:18.04
MAINTAINER hiekay "[email protected]"
ENV REFRESHED_AT 2018-11-1
RUN apt-get -qq update
  • 解析: 首先通過FROM指令為映象設定基礎映象Ubuntu:18.04 , 然後使用MAINTAINER 新增自己的資訊. 之後使用 ENV 設定 環境變數.設定REFRESHED_AT的環境變數用來表示該映象模板最後的更新時間 .最後使用RUN指令執行apt-get -qq update 命令. 該指令執行時將會重新整理APT包的快取,用來確保我們能將要安裝的每個軟體包都更新到最新版本.

有了這個模板,如果想重新整理一個構建,只需要修改ENV指令中的日期.這使Docker在命令ENV指令時開始重置這個快取,並執行後續指令無須依賴該快取. 也就是說, RUN apt-get update 這條指令將會被再次執行,包快取也將會被重新整理為最新內容. 可以擴充套件此模板,比如適配到不同的平臺或者新增額外的需求.

  • 比如支援Fedora Dockerfile模板
FROM fedora:20
MAINTAINER hiekay "[email protected]"
ENV REFRESHED_AT 2018-11-1
RUN yum -y -q upgrade 

在Fedora中使用Yum實現了與上面的Ubuntu例子中非常類似的功能.

8.檢視新映象

  • 列出新的Docker映象
$ sudo docker images hiekay/static_web
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hiekay/static_web   latest              7e35e0a7fc62        3 hours ago         169MB

深入探究映象是如何構建出來的,使用docker history命令

  • 使用docker history 命令
$ sudo docker history 7e35e0a7fc62  

IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
7e35e0a7fc62        3 hours ago         /bin/sh -c #(nop)  EXPOSE 80                    0B                  
2f6d2e9be7ac        3 hours ago         /bin/sh -c echo 'Hi,I am in your container' …   26B                 
4c7337c294ac        3 hours ago         /bin/sh -c apt-get install -y nginx             59.7MB              
489c8164d6af        3 hours ago         /bin/sh -c apt-get update                       23.8MB              
c8288775012d        3 hours ago         /bin/sh -c #(nop)  MAINTAINER hiekay "hikay5…   0B                  
ea4c82dcd15a        13 days ago         /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B                  
<missing>           13 days ago         /bin/sh -c mkdir -p /run/systemd && echo 'do…   7B                  
<missing>           13 days ago         /bin/sh -c rm -rf /var/lib/apt/lists/*          0B                  
<missing>           13 days ago         /bin/sh -c set -xe   && echo '#!/bin/sh' > /…   745B                
<missing>           13 days ago         /bin/sh -c #(nop) ADD file:bcd068f67af2788db…   85.8MB

9.從新映象啟動一個容器

$ sudo docker run -d -p 80 --name static_web hiekay/static_web nginx -g "daemon off;"
09bb5531cbc24930ad35da95dd0acd52dd933c5996ae89e238b509053b7f8c1d
  • 解析: docker run命令執行一個名字為static_web的新容器, -d 選項,告訴Docker以分離(detached)的方式在後臺執行.適合執行類似Nginx守護程序這樣的需要長時間執行的程序. 並指定了需要在容器中執行的命令:nginx -g “daemon off;” 這將以前臺執行的方式啟動nginx 來作為我們的Web伺服器. 其中-p標誌,用來控制Docker公開哪些網路埠給外部宿主機. 兩種方法分配埠:

  • Docker可以在宿主機上隨機選擇一個位於49153~65535的一個比較大的埠號來對映到容器中80埠上.

  • 可以在Docker宿主機中指定一個具體的埠號來對映到容器中的80埠上.

  • 檢視Docker埠對映情況

$ sudo docker ps -l
  • dockerport 命令檢視
$ sudo docker port 09bb5531cbc2 80
                                                  
80/tcp -> 127.0.0.1:32768
  • 通過-p選項對映到特定埠
$ sudo docker run -d -p 80:80 --name static_web hiekay/static_web nginx -g "daemon off;"
  • 繫結不同的埠
$ sudo docker run -d -p 8080:80 --name static_web hiekay/static_web nginx -g "daemon off;"
  • 繫結到特定的網路介面
$ sudo docker run -d -p 127.0.0.1:80:80 --name static_web hiekay/static_web nginx -g "daemon off;"

繫結到了宿主機127.0.0.1這個IP的80埠上.

  • 繫結到特定的網路介面的隨機埠
$ sudo docker run -d -p 127.0.0.1::80 --name static_web hiekay/static_web nginx -g "daemon off;"
  • 擴充套件 可以使用 /udp字尾指定UDP埠

其中提供引數-P 用來對外公開在Dockerfile中的EXPOSE指令中設定的所有埠

  • 使用docker run命令對外公開埠
$ sudo docker run -d -P --name static_web hiekay/static_web nginx -g "daemon off;"

該命令會將容器內的80埠對本地宿主機公開,繫結宿主機的隨機埠. 會將用來構建該映象的Dockerfile檔案中EXPOSE指令指定的其他埠也公開.

有了這個埠號,我們可以用本地宿主機IP或者127.0.0.1的localhost 連結到執行中的容器了.

  • 使用curl連線到容器
$ curl localhost:32768

//成功返回:
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

10.將映象推送到Docker Hub

  • docker push 推送Docker映象
$ sudo docker push hiekay/static_web

The push refers to repository [docker.io/hiekay/static_web]
......

成功後,可以在Docker Hub上看到我們上傳的映象. image.png

11.刪除映象

sudo docker rmi hiekay/static_web

如果要刪除一個Docker Hub上的映象倉庫,需要登入Docker Hub後使用Delete repository連結來刪除. image.png

  • 刪除所有映象
sudo docker rmi 'docker images -a -q'

12.執行自己的Docker Registry

  • 執行基於容器的Registry
sudo docker run -p 5000:5000 registry
  • 檢視hiekay/static_web
sudo docker images hiekay/static_web
  • 使用新的Registry 為映象打標籤
sudo docker tag 某個ID docker.example.com:5000/hiekay/static_web
  • 將映象推送到新Registry
sudo docker push docker.example.com:5000/hiekay/static_web
  • 從本地Registry構建新的容器
sudo docker run -t -i docker.example.com:5000/hiekay/static_web /bin/bash