亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 服務器 > Web服務器 > 正文

理解Docker(2):Docker 鏡像詳細介紹

2024-09-01 13:49:04
字體:
來源:轉載
供稿:網友

本系列文章將介紹Docker的有關知識:

(1)Docker 安裝及基本用法

(2)Docker 鏡像

(3)Docker 容器的隔離性 - 使用 Linux namespace 隔離容器的運行環境

(4)Docker 容器的隔離性 - 使用 cgroups 限制容器使用的資源

(5)Docker 網絡

對于每個軟件,除了它自身的代碼以外,它的運行還需要有一個運行環境和依賴。不管這個軟件是象往常一樣運行在物理機或者虛機之中,還是運行在現在的容器之中,這些都是不變的。在傳統環境中,軟件在運行之前也需要經過 代碼開發->運行環境準備 -> 安裝軟件 -> 運行軟件 等環節,在容器環境中,中間的兩個環節被鏡像制作過程替代了。也就是說,鏡像的制作也包括運行環境準備和安裝軟件等兩個主要環節,以及一些其他環節。因此,Docker 容器鏡像其實并沒有什么新的理論,只是這過程有了新的方式而已。

  鏡像(image)是動態的容器的靜態表示(specification),包括容器所要運行的應用代碼以及運行時的配置。Docker 鏡像包括一個或者多個只讀層( read-only layers ),因此,鏡像一旦被創建就再也不能被修改了。一個運行著的Docker 容器是一個鏡像的實例( instantiation )。從同一個鏡像中運行的容器包含有相同的應用代碼和運行時依賴。但是不像鏡像是靜態的,每個運行著的容器都有一個可寫層( writable layer ,也成為容器層 container layer),它位于底下的若干只讀層之上。運行時的所有變化,包括對數據和文件的寫和更新,都會保存在這個層中。因此,從同一個鏡像運行的多個容器包含了不同的容器層。

 Docker 有兩種方式來創建一個容器鏡像:

  • 創建一個容器,運行若干命令,再使用 docker commit 來生成一個新的鏡像。不建議使用這種方案。
  • 創建一個 Dockerfile 然后再使用 docker build 來創建一個鏡像。大多人會使用 Dockerfile 來創建鏡像。

1. docker build 生成鏡像

1.1 生成過程實例

 在使用 Dockerfile 創建容器之前,需要先準備一個 Dockerfile 文件,然后運行 docker build 命令來創建鏡像。我們通過下面的例子來看看Docker 創建容器的過程。

 FROM ubuntu:14.04MAINTAINER sammy "sammy@sammy.com"RUN apt-get updateRUN apt-get -y install ntpEXPOSE 5555CMD ["/usr/sbin/ntpd"]

這是一個非常簡單的Dockerfile,它的目的是基于 Ubuntu 14.04 基礎鏡像安裝 ntp 從而生成一個新的鏡像??纯雌溥^程:

root@devstack:/home/sammy/ntponubuntu# docker build -t sammy_ntp2 .Sending build context to Docker daemon 2.048 kBStep 1 : FROM ubuntu:14.04 ---> 4a725d3b3b1cStep 2 : MAINTAINER sammy "sammy@sammy.com" ---> Using cache ---> c4299e3f774cStep 3 : RUN apt-get update ---> Using cache ---> 694a19d54103Step 4 : RUN apt-get -y install ntp ---> Running in 9bd153c65a76Reading package lists......Fetched 561 kB in 10s (51.1 kB/s)Selecting previously unselected package libedit2:amd64.(Reading database ... 11558 files and directories currently installed.)...Processing triggers for libc-bin (2.19-0ubuntu6.9) ...Processing triggers for ureadahead (0.100.0-16) ... ---> 9cc05cf6f48dRemoving intermediate container 9bd153c65a76Step 5 : EXPOSE 5555 ---> Running in eb4633151d98 ---> f5c96137bec9Removing intermediate container eb4633151d98Step 6 : CMD /usr/sbin/ntpd ---> Running in e81b1eae3678 ---> af678df648bcRemoving intermediate container e81b1eae3678Successfully built af678df648bc

Dockerfile 中的每個步驟都會對應每一個 docker build 輸出中的 step。

Step 1:FROM ubuntu:14.04

獲取基礎鏡像 ubuntu:14.04. Docker 首先會在本地查找,如果找到了,則直接利用;否則從 Docker registry 中下載。在第一次使用這個基礎鏡像的時候,Docker 會從 Docker Hub 中下載這個鏡像,并保存在本地:

Step 1 : FROM ubuntu:14.0414.04: Pulling from library/ubuntu862a3e9af0ae: Pull complete6498e51874bf: Pull complete159ebdd1959b: Pull complete0fdbedd3771a: Pull complete7a1f7116d1e3: Pull completeDigest: sha256:5b5d48912298181c3c80086e7d3982029b288678fccabf2265899199c24d7f89Status: Downloaded newer image for ubuntu:14.04 ---> 4a725d3b3b1c

以后再使用的時候就直接使用這個鏡像而不再需要下載了。

Step 2:MAINTAINER sammy "sammy@sammy.com"

本例中依然是從 Cache 中環境新的鏡像。在第一次的時候,Docker 會創建一個臨時的容器 1be8f33c1846,然后運行 MAINTAINER 命令,再使用 docker commit 生成新的鏡像

Step 2 : MAINTAINER sammy "sammy@sammy.com" ---> Running in 1be8f33c1846 ---> c4299e3f774c

通過這個臨時容器的過程(create -> commit -> destroy),生成了新的鏡像 c4299e3f774c:

2016-09-16T21:58:09.010886393+08:00 container create 1be8f33c18469f089d1eee8c444dad1ff0c7309be82767092082311379245358 (image=sha256:4a725d3b3b1cc18c8cbd05358ffbbfedfe1eb947f58061e5858f08e2899731ee, name=focused_poitras)
2016-09-16T21:58:09.060071206+08:00 container commit 1be8f33c18469f089d1eee8c444dad1ff0c7309be82767092082311379245358 (comment=, image=sha256:4a725d3b3b1cc18c8cbd05358ffbbfedfe1eb947f58061e5858f08e2899731ee, name=focused_poitras)
2016-09-16T21:58:09.071988068+08:00 container destroy 1be8f33c18469f089d1eee8c444dad1ff0c7309be82767092082311379245358 (image=sha256:4a725d3b3b1cc18c8cbd05358ffbbfedfe1eb947f58061e5858f08e2899731ee, name=focused_poitras)

這個鏡像是基于 ubuntu 14.04 基礎鏡像生成的,layers 沒有變化,只是元數據 CMD 發生了改變:

"Cmd": [        "/bin/sh",        "-c",        "#(nop) ",        "MAINTAINER sammy /"sammy@sammy.com/""      ]

因此可以認為只是鏡像的元數據發生了改變。生成的新的鏡像作為中間鏡像會被保存在 cache 中。

 Step 3: RUN apt-get update

本例中Docker 仍然從緩存中獲取了鏡像。在第一次的時候,Docker 仍然是通過創建臨時容器在執行 docker commit 的方式來創建新的鏡像:
Step 3 : RUN apt-get update

 ---> Running in 8b3b97af3bd7Ign http://archive.ubuntu.com trusty InReleaseGet:1 http://archive.ubuntu.com trusty-updates InRelease [65.9 kB]...Get:22 http://archive.ubuntu.com trusty/universe amd64 Packages [7589 kB]Fetched 22.2 MB in 16min 21s (22.6 kB/s)Reading package lists... ---> 694a19d54103Removing intermediate container 8b3b97af3bd7

通過以上步驟,生成了新的中間鏡像 694a19d54103,它也會被保存在緩存中。你可以使用 docker inspect 694a19d54103 命令查看該中間鏡像,但是無法在docker images 列表中找到它,這是因為 docker images 默認隱藏了中間狀態的鏡像,因此你需要使用 docker images -a 來獲取它:

root@devstack:/home/sammy# docker images -a | grep 694a19d54103<none>         <none>       694a19d54103    11 hours ago    210.1 MB

該鏡像和原始鏡像相比,多了一個 layer,它保存的是 apt-get update 命令所帶來的變化:

"RootFS": {      "Type": "layers",      "Layers": [        "sha256:102fca64f92471ff7fca48e55807ae2471502822ba620292b0a06ebcab907cf4",        "sha256:24fe29584c046f2a88f7f566dd0bf7b08a8c0d393dfad8370633b0748bba8cbc",        "sha256:530d731d21e1b1bbe356d70d3bca4d72d76fed89e90faab271d29bd58c8ccea4",        "sha256:344f56a35ff9fc747ada7d2b88bd21c49b2ec404872662cbaf0a65201873c0c6",        "sha256:ffb6ddc7582aa7e2e73f102df3ffcd272e59b7cf3f7abefe08d11a7c85dea53a",        "sha256:a1afe95c99b39c30b5c1d3e8fda451bd3f066be304616197f1046e64cf6cda93" #這一層是新加的      ]    }

Step 4: RUN apt-get -y install ntp

和上面 Step 3 過程一樣,這個步驟也會通過創建臨時容器,執行該命令,再使用 docker commit 命令生成一個中間鏡像 9cc05cf6f48d 。和上面步驟生成的鏡像相比,它又多了一層:

root@devstack:/home/sammy# docker images -a | grep 9cc05cf6f48d<none>         <none>       9cc05cf6f48d    10 hours ago    212.8 MBroot@devstack:/home/sammy# docker inspect --format={{'.RootFS.Layers'}} 9cc05cf6f48d[sha256:102fca64f92471ff7fca48e55807ae2471502822ba620292b0a06ebcab907cf4 sha256:24fe29584c046f2a88f7f566dd0bf7b08a8c0d393dfad8370633b0748bba8cbc sha256:530d731d21e1b1bbe356d70d3bca4d72d76fed89e90faab271d29bd58c8ccea4 sha256:344f56a35ff9fc747ada7d2b88bd21c49b2ec404872662cbaf0a65201873c0c6 sha256:ffb6ddc7582aa7e2e73f102df3ffcd272e59b7cf3f7abefe08d11a7c85dea53a sha256:a1afe95c99b39c30b5c1d3e8fda451bd3f066be304616197f1046e64cf6cda93 sha256:a93086f33a2b7ee18eec2454b468141f95a403f5081284b6f177f83cdb3d54ba]

Step 5: EXPOSE 5555

 這一步和上面的 Step 2 一樣,Docker 生成了一個臨時容器,執行 EXPOSE 55 命令,再通過 docker commit 創建了中間鏡像 f5c96137bec9。該鏡像的 layers 沒有變化,但是元數據發生了一些變化,包括:

 "ExposedPorts": {        "5555/tcp": {}      }"Cmd": [        "/bin/sh",        "-c",        "#(nop) ",        "EXPOSE 5555/tcp"      ]

Step 6: CMD ["/usr/sbin/ntpd"]

這一步和上面的步驟相同,最終它創建了鏡像 af678df648bc,該鏡像只是修改了 CMD 元數據:

 "Cmd": [        "/bin/sh",        "-c",        "#(nop) ",        "CMD [/"/usr/sbin/ntpd/"]"      ]

該鏡像也是Docker 根據本 Dockerfile 生成的最終鏡像。它也出現在了 docker images 結果中:

root@devstack:/home/sammy# docker images | grep af678df648bcsammy_ntp2       latest       af678df648bc    11 hours ago    212.8 MB

我們可以使用 docker history 命令查看該鏡像中每一層的信息:

root@devstack:/home/sammy/ntponubuntu# docker history af678df648bcIMAGE        CREATED       CREATED BY                   SIZE        COMMENTaf678df648bc    16 hours ago    /bin/sh -c #(nop) CMD ["/usr/sbin/ntpd"]    0 Bf5c96137bec9    16 hours ago    /bin/sh -c #(nop) EXPOSE 5555/tcp       0 B9cc05cf6f48d    16 hours ago    /bin/sh -c apt-get -y install ntp        2.679 MB694a19d54103    16 hours ago    /bin/sh -c apt-get update            22.17 MBc4299e3f774c    17 hours ago    /bin/sh -c #(nop) MAINTAINER sammy "sammy@sa  0 B4a725d3b3b1c    3 weeks ago     /bin/sh -c #(nop) CMD ["/bin/bash"]       0 B<missing>      3 weeks ago     /bin/sh -c mkdir -p /run/systemd && echo 'doc  7 B<missing>      3 weeks ago     /bin/sh -c sed -i 's/^#/s*/(deb.*universe/)$/  1.895 kB<missing>      3 weeks ago     /bin/sh -c rm -rf /var/lib/apt/lists/*     0 B<missing>      3 weeks ago     /bin/sh -c set -xe  && echo '#!/bin/sh' > /u  194.6 kB<missing>      3 weeks ago     /bin/sh -c #(nop) ADD file:ada91758a31d8de3c7  187.8 MB

以上過程說明:

  • 容器鏡像包括元數據和文件系統,其中文件系統是指對基礎鏡像的文件系統的修改,元數據不影響文件系統,只是會影響容器的配置
  • 每個步驟都會生成一個新的鏡像,新的鏡像與上一次的鏡像相比,要么元數據有了變化,要么文件系統有了變化而多加了一層
  • Docker 在需要執行指令時通過創建臨時鏡像,運行指定的命令,再通過 docker commit 來生成新的鏡像
  • Docker 會將中間鏡像都保存在緩存中,這樣將來如果能直接使用的話就不需要再從頭創建了。關于鏡像緩存,請搜索相關文檔。

1.2 Docker 鏡像分層,COW 和 鏡像大?。╯ize)

1.2.1 鏡像分層和容器層docker,鏡像,docker鏡像和容器,鏡像操作
 

從上面例子可以看出,一個 Docker 鏡像是基于基礎鏡像的多層疊加,最終構成和容器的 rootfs (根文件系統)。當 Docker 創建一個容器時,它會在基礎鏡像的容器層之上添加一層新的薄薄的可寫容器層。接下來,所有對容器的變化,比如寫新的文件,修改已有文件和刪除文件,都只會作用在這個容器層之中。因此,通過不拷貝完整的 rootfs,Docker 減少了容器所占用的空間,以及減少了容器啟動所需時間。

1.2.2 COW 和鏡像大小

  COW,copy-on-write 技術,一方面帶來了容器啟動的快捷,另一方也造成了容器鏡像大小的增加。每一次 RUN 命令都會在鏡像上增加一層,每一層都會占用磁盤空間。舉個例子,在 Ubuntu 14.04 基礎鏡像中運行 RUN apt-get upgrade 會在保留基礎層的同時再創建一個新層來放所有新的文件,而不是修改老的文件,因此,新的鏡像大小會超過直接在老的文件系統上做更新時的文件大小。因此,為了減少鏡像大小起見,所有文件相關的操作,比如刪除,釋放和移動等,都需要盡可能地放在一個 RUN 指令中進行。

比如說,通過將上面的示例 Dockerfile 修改為:

 FROM ubuntu:14.04MAINTAINER sammy "sammy@sammy.com"RUN apt-get update && apt-get -y install ntpEXPOSE 5555CMD ["/usr/sbin/ntpd"]

結果產生的鏡像,不僅層數少了一層(7 -> 6),而且大小減少了 0.001M :),因為這個例子比較特殊,文件都是添加,而沒有更新,因此size 的下降非常小。

1.2.3 使用容器需要避免的一些做法

下面列舉了一些在使用容器時需要避免的做法,包括:

  • 不要在容器中保存數據(Don't store data in containers)
  • 將應用打包到鏡像再部署而不是更新到已有容器(Don't ship your application in two pieces)
  • 不要產生過大的鏡像 (Don't create large images)
  • 不要使用單層鏡像 (Don't use a single layer image)
  • 不要從運行著的容器上產生鏡像 (Don't create images from running containers )
  • 不要只是使用 “latest”標簽 (Don't use only the “latest” tag)
  • 不要在容器內運行超過一個的進程 (Don't run more than one process in a single container )
  • 不要在容器內保存 credentials,而是要從外面通過環境變量傳入 ( Don't store credentials in the image. Use environment variables)
  • 不要使用 root 用戶跑容器進程(Don't run processes as a root user )
  • 不要依賴于IP地址,而是要從外面通過環境變量傳入 (Don't rely on IP addresses )

2. Dockerfile 語法

上面的步驟說明了 Docker 可以通過讀取 Dockerfile 的內容來生成容器鏡像。Dockerfile 的每一行都是 INSTRUCTION arguments 格式,即 “指令 參數”。關于 Dockerfile 的預防,請參考 https://docs.docker.com/engine/reference/builder/。下面只是就一些主要的指令做一些說明。

2.1 幾個主要指令

2.1.1 ADD 和 COPY

Add:將 host 上的文件拷貝到或者將網絡上的文件下載到容器中的指定目錄

# Usage: ADD [source directory or URL] [destination directory]ADD /my_app_folder /my_app_folder

例子:

FROM ubuntu:14.04MAINTAINER Sammy Liu <sammy.liu@unknow.com>ADD temp dockfileENTRYPOINT top

ADD 指令會將本地 temp 目錄中的文件拷貝到容器的 dockfile 目錄下面,從而在鏡像中增加一個 layer。在未指定絕對路徑的時候,會放到 WORKDIR 目錄下面。

root@cc2a5605f905:/# ls dockfile/dockerfile-add dockerfile-cmd dockerfile-env dockerfile-ports dockerfile-user dockerfile-user-hroot@cc2a5605f905:/# pwd/

那兩者有什么區別呢?

  • ADD 多了2個功能, 下載URL和對支持的壓縮格式的包進行解壓.  其他都一樣。比如 ADD http://foo.com/bar.go /tmp/main.go 會將文件從因特網上方下載下來,ADD /foo.tar.gz /tmp/ 會將壓縮文件解壓再COPY過去
  • 如果你不希望壓縮文件拷貝到container后會被解壓的話, 那么使用COPY。
  • 如果需要自動下載URL并拷貝到container的話, 請使用ADD

2.1.2 CMD

CMD:在容器被創建后執行的命令,和 RUN 不同,它是在構造容器時候所執行的命令

# Usage 1: CMD application "argument", "argument", ..CMD "echo" "Hello docker!"

CMD 有三種格式:

  • CMD ["executable","param1","param2"] (like an exec, preferred form)
  • CMD ["param1","param2"] (作為 ENTRYPOINT 的參數)
  • CMD command param1 param2 (作為 shell 運行)

一個Dockerfile里只能有一個CMD,如果有多個,只有最后一個生效。

2.1.3 ENTRYPOINT

ENTRYPOINT :設置默認應用,會保證每次容器被創建后該應用都會被執行。CMD 和 ENTRYPOINT 的關系會在下面詳細解釋。

2.1.4 ENV:設置環境變量,可以使用多次

# Usage: ENV key valueENV SERVER_WORKS 4

設置了后,后續的RUN命令都可以使用,并且會作為容器的環境變量。舉個例子,下面是 dockfile:

FROM ubuntu:14.04ENV abc=1ENV def=2ENTRYPOINT top

生成鏡像:docker build -t envimg4 -f dockerfile-env . 其元數據包括了這兩個環境變量:

"Env": [        "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",        "abc=1",        "def=2"      ],

啟動容器:docker run -it --name envc41 envimg4。也能看到:

"Env": [        "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",        "abc=1",        "def=2"      ]

進入容器:能看到定義的 abc 和 def 變量

root@devstack:/home/sammy/ntponubuntu# docker exec -it envc41 bashroot@ba460e0e9dc4:/# echo $abcroot@ba460e0e9dc4:/# echo $def

2.1.5 EXPOSE :向容器外暴露一個端口

# Usage: EXPOSE [port]EXPOSE 8080

2.1.6 FROM:指定進行的基礎鏡像,必須是第一條指令

# Usage: FROM [image name]FROM ubuntu

2.1.7 MAINTAINER:可以在任意地方使用,設置鏡像的作者

# Usage: MAINTAINER [name]MAINTAINER authors_name

2.1.8 RUN:運行命令,結果會生成鏡像中的一個新層

# Usage: RUN [command]RUN aptitude install -y ntp

2.1.9 USER:設置該鏡像的容器的主進程所使用的用戶,以及后續 RUN, CMD 和 ENTRYPOINT 指令運行所使用的用戶

語法:

# Usage: USER [UID]USER 751 

Dockerfile 中的默認用戶是基礎鏡像中所使用的用戶。比如,你的鏡像是從一個使用非 root 用戶 sammy 的鏡像繼承而來的,那么你的 Dockerfile 中 RUN 指定運行的命令的用戶就會使用 sammy 用戶。

舉例:

(1)創建 dockerfile 文件

root@devstack:/home/sammy/dockerfile# cat dockerfile-userFROM ubuntu:14.04USER 1000ENTRYPOINT top

(2)創建鏡像:docker build -t dockerfile-user-1000 -f dockerfile-user .

(3)啟動容器:docker run -it --name c-user-1000-3 dockerfile-user-1000 top

能看出來當前用戶ID 為 1000:

PID USER   PR NI  VIRT  RES  SHR S %CPU %MEM   TIME+ COMMAND  1 1000   20  0  4440  648  548 S 0.0 0.0  0:00.00 sh  5 1000   20  0  19840  1296  984 R 0.0 0.1  0:00.00 top 

(4)基于該鏡像再創造一個鏡像,然后再啟動一個容器,可以發現容器中進程所使用的用戶ID 同樣為 1000.

2.1.10 VOLUME:允許容器訪問host上某個目錄

# Usage: VOLUME ["/dir_1", "/dir_2" ..]VOLUME ["/my_files"]

2.1.11 WORKDIR:設置 CMD 所指定命令的執行目錄

# Usage: WORKDIR /pathWORKDIR ~/

2.1.12 HEALTHCHECK: 容器健康檢查

這是 Docker 1.12 版本中新引入的指令,其語法為 HEALTHCHECK [OPTIONS] CMD command。 來看一個例子:

FROM ubuntu:14.04MAINTAINER Sammy Liu <sammy.liu@unknow.com>RUN apt-get updateRUN apt-get -y install curlEXPOSE 8888CMD while true; do echo 'hello world' | nc -l -p 8888; doneHEALTHCHECK --interval=10s --timeout=2s CMD curl -f http://localhost:8888/ || exit 1

在啟動容器后,其health 狀態首先是 starting,然后在過了10秒做了第一次健康檢查成功后,變為 healthy 狀態。

root@devstack:/home/sammy/dockerfile# docker ps | grep c-health24c459eef1894    img-health2     "/bin/sh -c 'while tr"  7 seconds ago    Up 6 seconds (health: starting)  8888/tcp         c-health2root@devstack:/home/sammy/dockerfile# docker ps | grep c-health24c459eef1894    img-health2     "/bin/sh -c 'while tr"  9 seconds ago    Up 8 seconds (health: starting)  8888/tcp         c-health2root@devstack:/home/sammy/dockerfile# docker ps | grep c-health24c459eef1894    img-health2     "/bin/sh -c 'while tr"  11 seconds ago   Up 11 seconds (healthy)   8888/tcp         c-health2

需要注意的是 CMD 是在容器之內運行的,因此,你需要確保其命令或者腳本存在于容器之內并且可以被運行。

2.2 幾個比較繞的地方

2.2.1 EXPOSE 和 docker run -p -P 之間的關系

容器的端口必須被發出(publish)出來后才能被外界使用。Dockerfile 中的 EXPOSE 只是“標記”某個端口會被暴露出來,只有在使用了 docker run -p 或者 -P 后,端口才會被“發出”出來,此時端口才能被使用。

舉例:

(1)Dockerfile

FROM ubuntu:14.04MAINTAINER Sammy Liu <sammy.liu@unknow.com>CMD while true; do echo 'hello world' | nc -l -p 8888; done

(2)創建鏡像:docker build -t no-exposed-ports -f dockerfile-ports .

(3)啟動容器1:docker run -d --name no-exposed-ports1 no-exposed-ports。此容器沒有 exposed 和 published 任何端口。

(4)啟動容器2:docker run -d --name no-exposed-ports2 -p 8888:8888 no-exposed-ports

此時容器的 8888 端口被發布為主機上的 8888 端口:

"Ports": {        "8888/tcp": [          {            "HostIp": "0.0.0.0",            "HostPort": "8888"          }        ]      }


該端口會正確返回:

root@devstack:/home/sammy/dockerfile# telnet 0.0.0.0 8888Trying 0.0.0.0...Connected to 0.0.0.0.Escape character is '^]'.hello worldConnection closed by foreign host.

(5)使用 -P 參數:docker run -d --name no-exposed-ports3 -P no-exposed-ports

此時沒有任何端口被 published,說明 Docker 在使用了 “-P” 情形下只是自動將 exposed 的端口 published。

(6)使用 -p 加上一個不存在的端口:docker run -d --name no-exposed-ports4 -p 8889:8889 no-exposed-ports

此時,8889 端口會被暴露,但是沒法使用。說明 -p 會將沒有 exposed 的端口自動 exposed 出來。

(7)修改 dockerfile 為:

FROM ubuntu:14.04MAINTAINER Sammy Liu <sammy.liu@unknow.com>EXPOSE 8888CMD while true; do echo 'hello world' | nc -l -p 8888; done

創建鏡像exposed-ports, 再運行 docker run -d --name exposed-ports1 -P exposed-ports 創建一個容器,此時 8888 端口自動被 published 為主機上的 32776 端口:

"Ports": {        "8888/tcp": [          {            "HostIp": "0.0.0.0",            "HostPort": "32776"          }        ]      }

可見:

  • EXPOSE或者--expose只是為其他命令提供所需信息的元數據,或者只是告訴容器操作人員有哪些已知選擇。它只是作為記錄機制,也就是告訴用戶哪些端口會提供服務。它保存在容器的元數據中。
  • 使用 -p 發布特定端口。如果該端口已經被 exposed,則發布它;如果它還沒有被 exposed,則它會被 exposed 和 published。Docker 不會檢查容器端口的正確性。
  • 使用 -P 時 Docker 會自動將所有已經被 exposed 的端口發出出來。

2.2.2 CMD 和 ENTRYPOINT

這兩個指令都指定了運行容器時所運行的命令。以下是它們共存的一些規則:

  • Dockerfile 至少需要指定一個 CMD 或者 ENTRYPOINT 指令
  • CMD 可以用來指定 ENTRYPOINT 指令的參數

 

  沒有 ENTRYPOINT ENTRYPOINT exec_entry p1_entry ENTRYPOINT [“exec_entry”, “p1_entry”]
沒有 CMD 錯誤,不允許 /bin/sh -c exec_entry p1_entry  exec_entry p1_entry
CMD [“exec_cmd”, “p1_cmd”]  exec_cmd p1_cmd  /bin/sh -c exec_entry p1_entry exec_cmd p1_cmd  exec_entry p1_entry exec_cmd p1_cmd
CMD [“p1_cmd”, “p2_cmd”]  p1_cmd p2_cmd  /bin/sh -c exec_entry p1_entry p1_cmd p2_cmd  exec_entry p1_entry p1_cmd p2_cmd
CMD exec_cmd p1_cmd  /bin/sh -c exec_cmd p1_cmd  /bin/sh -c exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd  exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd
備注 只有 CMD 時,執行 CMD 定義的指令  CMD 和 ENTRYPOINT 都存在時,CMD 的指令作為 ENTRYPOINT 的參數  

 

 舉例:

(1)同時有 CMD 和 ENTRYPOINT

FROM ubuntu:14.04MAINTAINER Sammy Liu <sammy.liu@unknow.com>CMD topENTRYPOINT ps

此時會運行的指令為 /bin/sh -c ps /bin/sh -c top

但是實際上只是運行了 ps:

root@devstack:/home/sammy/dockerfile# /bin/sh -c ps /bin/sh -c top PID TTY     TIME CMDpts/3  00:00:00 supts/3  00:00:00 bashpts/3  00:00:00 shpts/3  00:00:00 psroot@devstack:/home/sammy/dockerfile# /bin/sh -c ps PID TTY     TIME CMDpts/3  00:00:00 supts/3  00:00:00 bashpts/3  00:00:00 shpts/3  00:00:00 ps

(2)CMD 作為 ENTRYPOINT 的參數

FROM ubuntu:14.04MAINTAINER Sammy Liu <sammy.liu@unknow.com>CMD ["-n", "10"]ENTRYPOINT top

啟動容器后運行的命令為 /bin/sh -c top -n 10.

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品中文字幕在线| 国产精品美乳在线观看| 久久精品国产亚洲一区二区| 欧美精品第一页在线播放| 日韩亚洲欧美中文高清在线| 日韩美女毛茸茸| 国产福利精品在线| 国产亚洲欧美aaaa| 懂色av一区二区三区| 亚洲精品理论电影| 久久久久久久999| 亚洲韩国日本中文字幕| 精品国产一区二区三区久久狼黑人| 亚洲欧洲一区二区三区久久| 69**夜色精品国产69乱| 欧美一级黄色网| 日韩一区二区在线视频| 91精品视频在线播放| 国产精品1区2区在线观看| 精品国产一区av| 国产精品美女主播| 亚洲精品91美女久久久久久久| 黄色成人在线免费| 欧美高清视频在线| 国产91对白在线播放| 久久久久久久色| 大量国产精品视频| 色综合久久久888| 91日韩在线视频| 欧美激情在线一区| 91成品人片a无限观看| 欧美日韩国产一区中文午夜| 欧美日韩亚洲视频一区| 麻豆国产精品va在线观看不卡| 国产精品青草久久久久福利99| 日韩精品免费观看| 欧美激情xxxx| 97av在线影院| 久久艹在线视频| 国产精品视频免费观看www| 亚洲在线观看视频网站| 国产网站欧美日韩免费精品在线观看| 不卡在线观看电视剧完整版| 日产精品99久久久久久| 成人精品久久av网站| 日韩在线观看免费| 欧美亚洲国产成人精品| 91高清视频免费观看| 亚洲欧美另类在线观看| 久久久久国产一区二区三区| 久久国内精品一国内精品| 5566成人精品视频免费| 亚洲人永久免费| 久久精品国产亚洲精品2020| 国产精品日日做人人爱| 日韩hd视频在线观看| 日韩精品视频免费专区在线播放| 国产午夜精品一区理论片飘花| 欧美与黑人午夜性猛交久久久| 久热精品视频在线免费观看| 中文字幕av一区二区三区谷原希美| 亚洲精品免费在线视频| 日韩欧美在线字幕| 国产+人+亚洲| 欧美一级片一区| 91精品国产沙发| 最新国产成人av网站网址麻豆| 欧美性猛交xxxx乱大交| 国产精品久久婷婷六月丁香| 2018中文字幕一区二区三区| 成人激情av在线| 亚洲综合在线中文字幕| 久久久国产一区| 欧美日韩国产中字| 午夜精品久久久久久久男人的天堂| 国产综合在线观看视频| 日韩av电影在线播放| 欧美性资源免费| 国产精品久久久久免费a∨大胸| 懂色av中文一区二区三区天美| 久久久精品免费视频| 国产成人黄色av| 大荫蒂欧美视频另类xxxx| 亚洲天堂免费视频| 精品国内自产拍在线观看| 欧美激情中文网| 亚洲xxxx视频| 4444欧美成人kkkk| 亚洲成人网久久久| 国产不卡av在线免费观看| 亚洲成人久久久久| 日韩hd视频在线观看| 91国产美女在线观看| 中文字幕久热精品视频在线| 日韩国产高清污视频在线观看| 欧美激情第三页| 精品一区二区三区四区在线| 91中文在线视频| 欧美亚洲国产精品| 欧美亚洲国产精品| 日本精品一区二区三区在线播放视频| 国产福利视频一区二区| 亚洲欧美色图片| 91极品女神在线| 亚洲精选在线观看| 成人中文字幕+乱码+中文字幕| 51ⅴ精品国产91久久久久久| 国产一区av在线| 亚洲一区美女视频在线观看免费| 欧美性色xo影院| 日韩视频在线免费| 国产有码在线一区二区视频| 日韩欧美高清视频| 成人免费视频网址| 少妇激情综合网| 久久人人爽人人爽人人片av高清| 国产欧美日韩精品专区| 国产欧美日韩视频| 欧美壮男野外gaytube| 中文在线不卡视频| 九九热精品视频在线播放| 亚洲va欧美va国产综合久久| 欧美激情欧美激情| 亚洲加勒比久久88色综合| 国产精品看片资源| 亚洲免费中文字幕| 成人免费网视频| 91精品在线影院| 久久亚洲精品国产亚洲老地址| 最好看的2019年中文视频| 中文字幕视频一区二区在线有码| 中文字幕国产亚洲2019| 国产精品电影观看| 神马久久久久久| 97超碰色婷婷| 久久网福利资源网站| 国产成人av在线播放| 不卡av日日日| 亚洲国产欧美一区二区三区同亚洲| 高清日韩电视剧大全免费播放在线观看| 亚洲视频综合网| 欧美丰满少妇xxxxx| 国产精品嫩草视频| 一区二区三区视频免费在线观看| 欧美在线观看www| 成人免费淫片视频软件| 欧美黑人一级爽快片淫片高清| 欧美在线一级va免费观看| 欧美亚洲视频在线看网址| 成人免费激情视频| 精品亚洲一区二区三区在线播放| 久久偷看各类女兵18女厕嘘嘘| 久久久成人精品视频| 欧美日韩中文字幕综合视频| 欧洲成人在线视频| 日韩一区av在线| 亚洲第一色中文字幕| 欧美视频第一页| 中文字幕亚洲欧美| 久久频这里精品99香蕉| 国产视频一区在线| 国产精品91久久久| 国产精品美女久久久久久免费| 久久精品国产亚洲|