導航:首頁 > 文件處理 > docker鏡像中解壓文件

docker鏡像中解壓文件

發布時間:2022-07-31 05:46:47

A. 如何將docker鏡像打包成tar文件

當想讓一個容器做兩件事情,或者使一個Docker鏡像包含來自兩個不同鏡像的依賴庫時,就需要知道每個鏡像的Dockerfile。本文介紹了如何通過docker history命令來對Docker鏡像進行反向工程,得到它們的Dockerfile

B. docker tomcat 鏡像 怎麼用

前篇筆記中搞定了一個鏡像並安裝了jdk本想著這tomcat會更簡單,後來發現我錯了。且看下面過程:我這個鏡像原始的系統就有openssh,只需要進到鏡像里passwd一個新的密碼。退出後commit一下就添加了一個ssh服務。之後通過以下命令在後台啟動鏡像,執行ssh服務,開放22埠1dockerrun-d-p22ubuntu64:14.04/usr/sbin/sshd-D回車後打出容器的ID號就返回了那我們怎麼知道這容器當前什麼情況呢?1dockerps列出當前還在運行中的容器能看到列表中的容器id。還有一條有用的信息是PORTS列,說明宿主機的49153映射到的容器22埠上了。這時就可以通過putty或scp之類的連接上去進行操作了。現在我已經把tomcat解壓放到/usr/local/java目錄下了。並通過startup.sh啟動測試正常.okexit+commit怎麼能在鏡像啟動時就把tomcat啟起來呢??學著之前的命令1dockerrun-itubuntu_tomcat:7.0.55/usr/local/java/apache-tomcat-7.0.55/bin/startup.sh結果得到了如下的響應:沒有環境變數進到鏡像里,查看/etc/profile,明明是有的。之前通過ssh進去也是可以啟動的,這是為什麼呢?linux的啟動過程里,/etc/profile是在用戶登錄的時候執行,在命令行run的時候可能是不會進行登錄操作,所以沒有相應的環境變數。但是我們啟動了ssh服務,從遠程是通過登錄進的系統,這時候就會有環境變數了。猜出了這原因,怎麼解決呢?run命令是可以掛環境變數參數的。但是這樣命令本身就會很復雜。ok,這個時候就要Dockerfile出場了。Dockerfile是一個用於創建鏡像的工具,它的用法是這樣。在當前目錄建一個名為Dockerfile的文件。執行dockerbuild:1dockerbuild-t="tomcat:7.0.55".就會創建一個tomcat:7.0.55的鏡像。那麼docker怎麼知道這個鏡像怎麼建呢。需求要我們在Dockerfile文件中說明。現在來看一下我這次用的Dockerfile文件的內容:123456FROMubuntu_tomcat:7.0.55ENVJAVA_HOME/usr/local/java/jdk1.7.0_67ENVJRE_HOME$JAVA_HOME/jreENVCLASSPATH.:$JAVA_HOME/lib:$JRE_HOME/libENVPATH$PATH:$JAVA_HOME/binCMD/usr/local/java/apache-tomcat-7.0.55/bin/catalina.shrunFROM指源自哪個鏡像創建ENV指定環境變數CMD鏡像啟動時默認執行的命令,在這里我們默認把tomcat跑起來。執行完build以後用images看一下新的鏡像啟動一下。1dockerrun-d-p80:8080tomcat:7.0.55把宿主機的80埠映射給鏡像的8080。再用ps命令看一下當前容器:鏡像已經正常跑起來了,埠與已經映射好了。訪問宿主機IP,就可以看到大貓圖了。用logs命令可以看到tomcat的日誌。1dockerlogsff5533ff5533就是容器的ID還可以用stop指令關閉容器1dockerstopff5533ok,一個tomcat的服務鏡像就搞定了。

C. docker鏡像導出

1.首先使用docker images命令查看當前系統的鏡像

2.export命令是從容器(container)中導出tar文件,而save命令則是從鏡像(images)中導出 SAVE: docker save -o pod-infrastructure.tar pod-infrastructure:latest 或 docker save > pod-infrastructure.tar pod-infrastructure:latest 或者docker save 鏡像id > pod-infrastructure.tar 其中-o和>表示輸出到文件,pod-infrastructure.tar為目標文件,pod-infrastructure:latest是源鏡...

3.將tar鏡像包scp到目標主機

D. 如何互動式地創建一個Docker鏡像

1. 運行一個Docker實例
Docker首先會嘗試從本地取得並運行所需的鏡像,如果在本地主機上沒有發現,它就會從Docker公共注冊中心拉取。這里,我們將會拉取鏡像並在 Docker 容器中創建一個fedora實例,並連接到它的 tty 上的bash shell。
# docker run -i -t fedora bash

2.安裝Apache網路伺服器
現在,在我們的Fedora基本鏡像實例准備好後,我們將會開始互動式地安裝Apache網路伺服器,而不是為它創建Dockerfile。為了做到這點,我們需要在終端或者shell運行以下命令。
# yum update

# yum install httpd

退出容器的 tty。
# exit

3.保存鏡像
現在,我們要去保存在Fedora實例里做的修改。要做到這個,我們首先需要知道實例的容器ID。而為了得到ID,我們又需要運行以下命令(LCTT 譯註:在容器外執行該命令)。
# docker ps -a

然後,我們會保存這些改變為一個新的鏡像,請運行以下命令。
# docker commit c16378f943fe fedora-httpd

這里,修改已經通過使用容器ID保存起來了,鏡像名字叫fedora-httpd。為了確認新的鏡像是否在運行,我們將運行以下命令。
# docker images

4. 添加內容到新的鏡像
我們自己新的Fedora Apache鏡像正成功的運行,現在我們想添加一些我們網站的網頁內容到Apache網路伺服器,使得網站能夠開箱即用。為做到這點,我們需要創建一個新的Dockerfile,它會處理從復制網頁內容到啟用80埠的所有操作。要達到這樣的目的,我們需要使用我們最喜歡的文本編輯器創建Dockerfile文件,像下面演示的一樣。
# nano Dockerfile

現在,我們需要添加以下的命令行到文件中。
FROM fedora-httpd
ADD mysite.tar /tmp/
RUN mv /tmp/mysite/* /var/www/html
EXPOSE 80
ENTRYPOINT [ "/usr/sbin/httpd" ]
CMD [ "-D", "FOREGROUND" ]

這里,上述的Dockerfile中,放在mysite.tar里的網頁內容會自動解壓到/tmp/文件夾里。然後,整個站點會被移動到Apache的網頁根目錄/var/www/html/,命令expose 80會打開80埠,這樣網站就能正常訪問了。其次,入口點放在了/usr/sbin/https裡面,保證Apache伺服器能夠執行。
5. 構建並運行一個容器
現在,我們要用剛剛創建的Dockerfile創建我們的容器,以便將我們的網站添加到上面。為做到這,我們需要運行以下命令。
# docker build -rm -t mysite .

建立好我們的新容器後,我們需要要用下面的命令來運行容器。
# docker run -d -P mysite

E. 如何使用Dockerfile構建鏡像

你好,使用方法如下:
Dockerfile結構
dockerfile由4部分信息組成:基礎鏡像信息、維護者信息、鏡像操作指令和容器啟動時執行指令。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# This dockerfile uses the ubuntu image
# VERSION 2 - EDITION 1
# Author: docker_user
# Command format: Instruction [arguments / command] ..

# Base image to use, this must be set as the first line
FROM ubuntu

# Maintainer: docker_user <docker_user at email.com> (@docker_user)
MAINTAINER docker_user [email protected]

# Commands to update the image
RUN echo "deb http://archive.ubuntu.com/ubuntu/ raring main universe" >> /etc/apt/sources.list
RUN apt-get update && apt-get install -y nginx
RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf

# Commands when creating a new container
CMD /usr/sbin/nginx

其中#表注釋,可以標注一些說明性的文字。
FROM關鍵字指定鏡像的來源,默認為DockerHub,也可以寫私有倉庫的鏡像,例如:localhost:5000/centos:6.7,如果本地已經存在指定的鏡像名稱,則會從本地緩存直接獲取。MAINTAINER 指定鏡像的作者,之後為鏡像操作執行RUN、ADD等,最後是容器啟動時發起的指令。
Dockerfile中的指令
FROM: 指定鏡像名稱,格式為FROM <image> 或FROM <image>:<tag>,例如FROM ubuntu 或 FROM ubuntu:12.04
MAINTAINER: 鏡像作者 ,格式為 MAINTAINER <name>
RUN:格式為 RUN <command> 或 RUN ["executable", "param1", "param2"]。
前者將在 shell 終端中運行命令,即 /bin/sh -c;後者則使用 exec 執行。指定使用其它終端可以通過第二種方式實現,例如 RUN ["/bin/bash", "-c", "echo hello"]。
每條 RUN 指令將在當前鏡像基礎上執行指定命令,並提交為新的鏡像。當命令較長時可以使用 \ 來換行。
CMD:支持三種格式
1.CMD ["executable","param1","param2"] 使用 exec 執行,推薦方式;
2.CMD command param1 param2 在 /bin/sh 中執行,提供給需要交互的應用;
3.CMD ["param1","param2"] 提供給 ENTRYPOINT 的默認參數;
指定啟動容器時執行的命令,每個 Dockerfile 只能有一條 CMD 命令。如果指定了多條命令,只有最後一條會被執行。如果用戶啟動容器時候指定了運行的命令,則會覆蓋掉 CMD 指定的命令。
EXPOSE:格式為 EXPOSE <port> [<port>...]。
告訴 Docker 服務端容器暴露的埠號,供互聯系統使用。在啟動容器時需要通過 -P,Docker 主機會自動分配一個埠轉發到指定的埠。
ENV:格式為 ENV <key> <value>。 指定一個環境變數,會被後續 RUN 指令使用,並在容器運行時保持。這就對應程序語言中的變數定義,可在需要的時候引用。例如:

1
2
3
4

ENV PG_MAJOR 9.3
ENV PG_VERSION 9.3.4
RUN curl -SL http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC /usr/src/postgress && …
ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH

ADD:格式為 ADD <src> <dest>。
該命令將復制指定的 <src> 到容器中的 <dest>。 其中 <src> 可以是Dockerfile所在目錄的一個相對路徑;也可以是一個 URL;還可以是一個 tar 文件(自動解壓為目錄)。
COPY:格式為 COPY <src> <dest>。
復制本地主機的 <src>(為 Dockerfile 所在目錄的相對路徑)到容器中的 <dest>。當使用本地目錄為源目錄時,推薦使用 COPY。
COPY和ADD的不同就是:ADD多了自動解壓和支持URL路徑的功能。
ENTRYPOINT:
兩種格式:
ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2(shell中執行)。
配置容器啟動後執行的命令,並且不可被 docker run 提供的參數覆蓋。
每個 Dockerfile 中只能有一個 ENTRYPOINT,當指定多個時,只有最後一個起效。
CMD和ENTRYPOINT比較:兩個命令都是只能使用一次,並且都是在執行docker run指令時運行,如果有多個,只執行最後一條。
兩者的不同在於參數的傳遞方式,如果在Dockerfile中定義如下指令

1

CMD echo hello



1

ENTRYPOINT ["echo","hello"]

那麼在運行命令docker run containerId echo hello時,指定了CMD的輸入結果為world,可以看出Dockerfile中指定的命令被覆蓋了,而指定了ENTRYPOINT時,輸出結果為hello echo world,可以看出指定的命令被作為ENTRYPOINT指定指令的參數了。

VOLUME:格式為 VOLUME ["/data"]。創建一個可以從本地主機或其他容器掛載的掛載點,一般用來存放資料庫和需要保持的數據等。不過此屬性在Dockerfile中指定並沒有什麼意義,因為沒有辦法指定本地主機的目錄。如果需要指定掛載點可以在執行docker run命令時指定:

1

docker run -it -v /home/fengzheng/ftp/:/data 859666d51c6d /bin/bash

USER:格式為 USER daemon。指定運行容器時的用戶名或 UID,後續的 RUN 也會使用指定用戶。
當服務不需要管理員許可權時,可以通過該命令指定運行用戶。並且可以在之前創建所需要的用戶,例如:RUN groupadd -r postgres && useradd -r -g postgres postgres。要臨時獲取管理員許可權可以使用 gosu,而不推薦 sudo。
WORKDIR:格式為 WORKDIR /path/to/workdir。為後續的 RUN、CMD、ENTRYPOINT 指令配置工作目錄。可以使用多個 WORKDIR 指令,後續命令如果參數是相對路徑,則會基於之前命令指定的路徑。例如

1
2
3
4

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd

則最終路徑為 /a/b/c。
ONBUILD:格式為 ONBUILD [INSTRUCTION]。
配置當所創建的鏡像作為其它新創建鏡像的基礎鏡像時,所執行的操作指令。
例如,Dockerfile 使用如下的內容創建了鏡像 image-A。

1
2
3
4

[...]
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
[...]

如果基於 image-A 創建新的鏡像時,新的Dockerfile中使用 FROM image-A指定基礎鏡像時,會自動執行ONBUILD 指令內容,等價於在後面添加了兩條指令。

1
2
3
4
5

FROM image-A

#Automatically run the following
ADD . /app/src
RUN /usr/local/bin/python-build --dir /app/src

使用 ONBUILD 指令的鏡像,推薦在標簽中註明,例如 ruby:1.9-onbuild。
基於CentOS6.7並源碼安裝nginx
首先准備了nginx-1.9.9.tar.gz安裝包和CentOS6-Base-163.repo(163源),將這兩個文件放到同一目錄下,並在此目錄下創建名稱為Dockerfile的文件。之後在此文件中實現源替換、nginx編譯安裝、及一些依賴包的安裝,Dockerfile內容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# this is a test ubuntu 12.04 image dockerfile
# Author:fengzheng

# Base image,this must be set as the first line
#localhost:5000/centos:6.7是我的私有倉庫的鏡像,可替換為centos:6.7(DockerHub中的鏡像)
FROM localhost:5000/centos:6.7

MAINTAINER fengzheng

# Commands to update the image

RUN mkdir /usr/nginx1.9.9
ADD nginx-1.9.9.tar.gz /usr/nginx1.9.9/
#RUN yum -y install tar
#RUN tar -zxvf /usr/nginx1.9.9/nginx-1.9.9.tar.gz
RUN cd /etc/yum.repos.d/ && mv CentOS-Base.repo CentOS-Base.repo.bak
ADD CentOS6-Base-163.repo /etc/yum.repos.d/
RUN cd /etc/yum.repos.d/ && mv CentOS6-Base-163.repo CentOS-Base.repo \
&& yum clean all && yum makecache \
&& yum -y install gcc \
&& yum -y install yum install -y pcre-devel \
&& yum -y install zlib zlib-devel \
&& yum -y install openssl openssl--devel \
&& cd /usr/nginx1.9.9/nginx-1.9.9/ && ./configure && make && make install

#如果設置daemon off; nginx無法啟動
#RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf

# Commands when creating a new container
# 啟動nginx 需進入/usr/local/nginx/sbin 執行./configure
CMD /bin/bash

最後執行命令"docker build -t nginx-centos:6.7 ."
其中.表示在當前目錄下搜索Dockerfile文件,-t參數指定鏡像名稱和tag。

F. 如何從Docker Registry中導出鏡像

一、目錄結構

Registry的配置文件中可以指定registry的運行目錄(實驗用本地文件系統作為後端存儲),registry會在這個目錄中建立相應的目錄結構,我在本地啟動一個registry服務,然後只push一個centos鏡像上去。鏡像名稱是localhost:5000/library/centos:latest,然後registry在本地創建了如圖1所示的目錄。

圖 1 registry目錄

為了顯示方便,我只截取了64位ID的前一部分。可以看到,目錄大體分為兩個:一個是blobs,一個是repositories。blobs中主要存放數據文件,可以看出都是經過sha256計算後的ID。repositories目錄中放鏡像的描述信息,記錄了一個鏡像有哪些layer,tag對應的manifest文件,link文件是一個文本文件,內容是一個形如「sha256:cf34a09a90b54c…」的64位ID,這個ID對應在blob中的文件其實就是這個image的manifest文件。

二、Manifest文件

manifest文件描述了一個鏡像的元信息,包括了layer的數據ID,layer的配置等,文件格式是json形式的文本文件。

docker鏡像可以分為V1和V2,在1.9以後鏡像格式有一些變化。為了向前兼容V1版本的docker,docekr
registryV2使用的manifest也對應地分為Schema1和Schema2,兩者可以通過官方對於manifest的解釋可以參考[1]和[2]。這里實驗都是在schema1上做的。

Schema1主要包含如下信息:

name:image的倉庫(repository)名,比如localhost:5000/library/centos:latest這個鏡像的repository name是library/centos
tag:該鏡像的tag
architecture:指該鏡像的宿主機的操作系統架構,如「amd64」
fsLayers:該欄位是一個數組,數組中的元素分別指明了各層對應的數據文件的sha256ID,數組的第1個就是鏡像的最頂層,第2個是次頂層…以此類推,值得注意的是,不同層的fsLayer
ID
有可能一樣,是因為有些層是空的,只有一些配置信息。當執行了一個不涉及文件操作的命令,這時候就會形成空fsLayer,空fsLayer計算出來的sha256ID也都是一樣的了。鏡像的一個layer,是由文件系統(比如新增的文件)fsLayer以及配置信息構成的,layer在docker的代碼層面又被稱為image,因為任意一個layer都可以作為頂層layer,被docker
image信息引用,從而成為一個image。所以需要區分fsLayer與layer。
history:該欄位也是一個數組,是為了兼容v1而設置的,指明了每個layer的配置信息,數組第一項對應的是鏡像的最頂層,與fslayer一起構成了一個layer。數組元素是一個json格式的map對象,key為「v1Compatibility」,值為一個字元串,該字元串就是layer的配置信息,可以直接用json.Unmrashal成為一個V1Image結構體(定義可以參考代碼github.com/docker/docker/image/image.go
L31)
schemaVersion:該manifest的版本,一個int型,如 1。

三、Tar包形式的鏡像

Docker中有個save和load命令。save命令可以將一個docker鏡像導出,把這個鏡像從最頂層到最底層的所有layer一起導出到一個tar包中,然後就可以隨意拷貝、發送這個tar包到別的機器,最後可以用load命令把這個鏡像重新載入進docker。

如果我們把一個鏡像從registry里拿出來,按照save成的tar包格式來組織,然後使用load命令載入,這樣就實現了不通過docker pull命令來下載鏡像,可以根據這個原理做第三方鏡像下載工具。

所以我們先來看一下鏡像的tar包形式是什麼樣的,我使用save命令導出了centos鏡像,解壓後目錄結構如圖2所示:

圖 2 鏡像tar包解壓後的目錄

下面對各文件進行解釋:

根目錄下的repositories文件,描述了這個鏡像的名字,tage,還有頂層layer的id

不同的文件夾代表了不同的layer。

json:layer的配置信息,如創建時間,執行命令等。

layer.tar:layer中包含的文件,如果是空layer,layer.tar解壓後就是空的。

VERSION: 版本信息。

四、從registry導出鏡像

我們對比tar包中的文件和registry中的文件,不難發現其中的對應關系,json、VERSION還有repositories文件都是可以從manifest中導出。

json文件其實就是之前提到的history欄位中v1Compatibilitiy,不同的是manifest中的這個欄位中有很多轉義符,我們需要去掉這些轉義符,方法是先Unmarshal成為一個V1Image結構體,然後在json.Marshal轉回字元串就好。

layer.tar其實就是blobs中對應的data文件,直接復制出來然後改個名字就可以。

VERSION是manifest中的schemaVersion。

repositories文件內容很簡單,格式是{「imageName」:{「tag」:」topLayerID」}},所以按照這個格式從manifest中找到對應的數據填進去就ok。

這些文件都准備好了以後,就可以准備打包成tar包了,直接使用linux中自帶的tar命令,這里需要注意的一點是,應該使用「只打包不壓縮」的選項。生成tar包後就可以直接使用docker load命令導入了。

我這么做了,是可以成功地導入一個鏡像。但是發現存在一個問題:使用上述方式導入的鏡像,每個layer的ID和我直接用docker
pull命令下載下的不一樣,而且docker
pull得到的ID從未在manifest和registry中的任何地方出現過。而且不管我使用新的機器還是重新pull,得到的ID都是一樣的。經過閱讀docker的代碼我才發現,layerID不是隨機生成的,也不是manifest中寫道的id,而是算出來的。下面就說一下計算過程。

我們最終需要的layerID在docker源碼中叫做StrongID,StrongID是把一個byte數組做Hash後得到的,這個byte數組的生成需要三個對象:v1Compatibility,blobSum(manifest中的fsLayerID),parent(父layer的StrongID),數組生成方法參考image.go中的MakeImageConfig方法(docker
1.9),基本操作就是把一個json對象轉成位元組數組。因為有parent欄位的存在,需要從最底層的layer開始計算,逐步迭代,最終的到top
layer的ID。最後要做的工作就是替換json文件中的id欄位和parent欄位成為新計算出來的ID即可。同樣地,文件夾名也要做相應改變。

增量導入:如果本地已經存在某些layer的情況,我們只用打包新的layer即可,因為導入時候docker會檢測這個layer是否存在,而且有parent信息來保證layer之間的關系。

G. 如何在Docker中安裝DzzOffice

在Github上面找到塗飛平的dzzwithdocker項目
1、下載項目
Git的項目,你可以clone或者直接下載zip包到本地,然後解壓到一個目錄下面,這里假定你把系統解壓到/home/cores/dockers/dzz1.0目錄下面
2、創建dzz鏡像 進入到dzz1.0目錄中,通過執行 docker build -t dzz10
.生成dzz10鏡像,由於國內網路情況,這是一個漫長的過程,我花費了大概半個小時(還不包含ubuntu鏡像的下載時間,因為之前已經下載完成該部分鏡像)
如果安裝失敗,請重復執行幾次,肯定能成功的。 然後執行 docker
images命令查看是否有dzz10名稱的image是否創建成功。 3、啟動dzz容器 完成dzz1.0鏡像的構建,通過 docker
run命令啟動一個容器,並將80和22埠映射到宿主機器埠上面,便於我們在瀏覽器中訪問,我這里將80埠映射到8081埠(因為我的80,8080都已經映射給其他服務的docker容器 :-( ),命令如下 docker run -d -p 8081:80 -p 2221:22 dzz10 4、配置DzzOffice 在瀏覽器中輸入http://127.0.0.1:80801來訪問系統,如果看到如圖界面,恭喜您,安裝DzzOffice成功了,剩下就是配置了
經過一番配置,可以看到華麗麗的界面了 :-) 三、單機安裝
為了在Github上面創建dzzwithdocker項目,我在我的本子(ThinkpadT420i 8G內存)上使用Vageant +
VirtualBox方式部署coreos系統,然後在coreos環境中下載dzzwithdocker項目文件,解壓,然後構建docker鏡像,運行容器,通過瀏覽器(Chrome)設置,訪問,一切正常,下面是整個系統的圖示。
又是華麗麗的界面 :-) 希望能夠幫到您哦。

H. 請問我從U盤下載下來的docker鏡像tar文件怎麼導入虛擬機內並使用

說兩種情況吧!
如果有安裝vmware-tools,那就簡單了,只需要讓虛擬機為當前活動窗口,保持滑鼠點在虛擬機中,插上U盤,就會自動掛載支虛擬機下,然後正常讀取就好了
如果沒有安裝vmware-tools,則建議使用共享文件夾方式,具體方法網上找找。因為不同版本和安裝的軟體,不太一樣,不會太難的。

I. 如何構建sles12的docker鏡像

1. Dockerfile的書寫規則及指令使用方法

Dockerfile的指令是忽略大小寫的,建議使用大寫,使用 # 作為注釋,每一行只支持一條指令,每條指令可以攜帶多個參數。
Dockerfile的指令根據作用可以分為兩種,構建指令和設置指令。構建指令用於構建image,其指定的操作不會在運行image的容器上執行;設置指令用於設置image的屬性,其指定的操作將在運行image的容器中執行。

(1)FROM(指定基礎image)
構建指令,必須指定且需要在Dockerfile其他指令的前面。後續的指令都依賴於該指令指定的image。FROM指令指定的基礎image可以是官方遠程倉庫中的,也可以位於本地倉庫。
該指令有兩種格式:

[plain] view
plain

FROM <image>

指定基礎image為該image的最後修改的版本。或者:

[plain] view
plain

FROM <image>:<tag>

指定基礎image為該image的一個tag版本。

(2)MAINTAINER(用來指定鏡像創建者信息)
構建指令,用於將image的製作者相關的信息寫入到image中。當我們對該image執行docker inspect命令時,輸出中有相應的欄位記錄該信息。
格式:

[plain] view
plain

MAINTAINER <name>

(3)RUN(安裝軟體用)
構建指令,RUN可以運行任何被基礎image支持的命令。如基礎image選擇了ubuntu,那麼軟體管理部分只能使用ubuntu的命令。
該指令有兩種格式:

[plain] view
plain

RUN <command> (the command is run in a shell - `/bin/sh -c`)
RUN ["executable", "param1", "param2" ... ] (exec form)

(4)CMD(設置container啟動時執行的操作)
設置指令,用於container啟動時指定的操作。該操作可以是執行自定義腳本,也可以是執行系統命令。該指令只能在文件中存在一次,如果有多個,則只執行最後一條。
該指令有三種格式:

[plain] view
plain

CMD ["executable","param1","param2"] (like an exec, this is the preferred form)
CMD command param1 param2 (as a shell)

當Dockerfile指定了ENTRYPOINT,那麼使用下面的格式:

[plain] view
plain

CMD ["param1","param2"] (as default parameters to ENTRYPOINT)

ENTRYPOINT指定的是一個可執行的腳本或者程序的路徑,該指定的腳本或者程序將會以param1和param2作為參數執行。所以如果CMD指令使用上面的形式,那麼Dockerfile中必須要有配套的ENTRYPOINT。

(5)ENTRYPOINT(設置container啟動時執行的操作)
設置指令,指定容器啟動時執行的命令,可以多次設置,但是只有最後一個有效。
兩種格式:

[plain] view
plain

ENTRYPOINT ["executable", "param1", "param2"] (like an exec, the preferred form)
ENTRYPOINT command param1 param2 (as a shell)

該指令的使用分為兩種情況,一種是獨自使用,另一種和CMD指令配合使用。
當獨自使用時,如果你還使用了CMD命令且CMD是一個完整的可執行的命令,那麼CMD指令和ENTRYPOINT會互相覆蓋只有最後一個CMD或者ENTRYPOINT有效。

[plain] view
plain

# CMD指令將不會被執行,只有ENTRYPOINT指令被執行
CMD echo 「Hello, World!」
ENTRYPOINT ls -l

另一種用法和CMD指令配合使用來指定ENTRYPOINT的默認參數,這時CMD指令不是一個完整的可執行命令,僅僅是參數部分;ENTRYPOINT指令只能使用JSON方式指定執行命令,而不能指定參數。

[plain] view
plain

FROM ubuntu
CMD ["-l"]
ENTRYPOINT ["/usr/bin/ls"]

(6)USER(設置container容器的用戶)
設置指令,設置啟動容器的用戶,默認是root用戶。

[plain] view
plain

# 指定memcached的運行用戶
ENTRYPOINT ["memcached"]
USER daemon

ENTRYPOINT ["memcached", "-u", "daemon"]

(7)EXPOSE(指定容器需要映射到宿主機器的埠)

置指令,該指令會將容器中的埠映射成宿主機器中的某個埠。當你需要訪問容器的時候,可以不是用容器的IP地址而是使用宿主機器的IP地址和映射後的端
口。要完成整個操作需要兩個步驟,首先在Dockerfile使用EXPOSE設置需要映射的容器埠,然後在運行容器的時候指定-p選項加上
EXPOSE設置的埠,這樣EXPOSE設置的埠號會被隨機映射成宿主機器中的一個埠號。也可以指定需要映射到宿主機器的那個埠,這時要確保宿主
機器上的埠號沒有被使用。EXPOSE指令可以一次設置多個埠號,相應的運行容器的時候,可以配套的多次使用-p選項。
格式:

[plain] view
plain

EXPOSE <port> [<port>...]

[plain] view
plain

# 映射一個埠
EXPOSE port1
# 相應的運行容器使用的命令
docker run -p port1 image

# 映射多個埠
EXPOSE port1 port2 port3
# 相應的運行容器使用的命令
docker run -p port1 -p port2 -p port3 image
# 還可以指定需要映射到宿主機器上的某個埠號
docker run -p host_port1:port1 -p host_port2:port2 -p host_port3:port3 image


口映射是docker比較重要的一個功能,原因在於我們每次運行容器的時候容器的IP地址不能指定而是在橋接網卡的地址范圍內隨機生成的。宿主機器的IP
地址是固定的,我們可以將容器的埠的映射到宿主機器上的一個埠,免去每次訪問容器中的某個服務時都要查看容器的IP的地址。對於一個運行的容器,可以
使用docker port加上容器中需要映射的埠和容器的ID來查看該埠號在宿主機器上的映射埠。

(8)ENV(用於設置環境變數)
構建指令,在image中設置一個環境變數。
格式:

[plain] view
plain

ENV <key> <value>

設置了後,後續的RUN命令都可以使用,container啟動後,可以通過docker inspect查看這個環境變數,也可以通過在docker run --env key=value時設置或修改環境變數。
假如你安裝了JAVA程序,需要設置JAVA_HOME,那麼可以在Dockerfile中這樣寫:
ENV JAVA_HOME /path/to/java/dirent

(9)ADD(從src復制文件到container的dest路徑)

建指令,所有拷貝到container中的文件和文件夾許可權為0755,uid和gid為0;如果是一個目錄,那麼會將該目錄下的所有文件添加到
container中,不包括目錄;如果文件是可識別的壓縮格式,則docker會幫忙解壓縮(注意壓縮格式);如果<src>是文件
且<dest>中不使用斜杠結束,則會將<dest>視為文件,<src>的內容會寫入<dest>;
如果<src>是文件且<dest>中使用斜杠結束,則會<src>文件拷貝到<dest>目錄下。
格式:

[plain] view
plain

ADD <src> <dest>

<src> 是相對被構建的源目錄的相對路徑,可以是文件或目錄的路徑,也可以是一個遠程的文件url;
<dest> 是container中的絕對路徑

(10)VOLUME(指定掛載點))

置指令,使容器中的一個目錄具有持久化存儲數據的功能,該目錄可以被容器本身使用,也可以共享給其他容器使用。我們知道容器使用的是AUFS,這種文件系
統不能持久化數據,當容器關閉後,所有的更改都會丟失。當容器中的應用有持久化數據的需求時可以在Dockerfile中使用該指令。
格式:

[plain] view
plain

VOLUME ["<mountpoint>"]

[plain] view
plain

FROM base
VOLUME ["/tmp/data"]

運行通過該Dockerfile生成image的容器,/tmp/data目錄中的數據在容器關閉後,裡面的數據還存在。例如另一個容器也有持久化數據的需求,且想使用上面容器共享的/tmp/data目錄,那麼可以運行下面的命令啟動一個容器:

[plain] view
plain

docker run -t -i -rm -volumes-from container1 image2 bash

container1為第一個容器的ID,image2為第二個容器運行image的名字。

(11)WORKDIR(切換目錄)
設置指令,可以多次切換(相當於cd命令),對RUN,CMD,ENTRYPOINT生效。
格式:

[plain] view
plain

WORKDIR /path/to/workdir

[plain] view
plain

# 在 /p1/p2 下執行 vim a.txt
WORKDIR /p1 WORKDIR p2 RUN vim a.txt

(12)ONBUILD(在子鏡像中執行)

[plain] view
plain

ONBUILD <Dockerfile關鍵字>

ONBUILD 指定的命令在構建鏡像時並不執行,而是在它的子鏡像中執行。
詳細資料可參考https://www.dockboard.org/docker-quicktip-3-onbuild

2. 創建Dockerfile,構建jdk+tomcat環境

Dockerfile文件

[html] view
plain

# Pull base image
FROM ubuntu:13.10

MAINTAINER zing wang "[email protected]"

# update source
RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe"> /etc/apt/sources.list
RUN apt-get update

# Install curl
RUN apt-get -y install curl

# Install JDK 7
RUN cd /tmp && curl -L 'http://download.oracle.com/otn-pub/java/jdk/7u65-b17/jdk-7u65-linux-x64.tar.gz' -H 'Cookie: oraclelicense=accept-securebackup-cookie; gpw_e24=Dockerfile' | tar -xz
RUN mkdir -p /usr/lib/jvm
RUN mv /tmp/jdk1.7.0_65/ /usr/lib/jvm/java-7-oracle/

# Set Oracle JDK 7 as default Java
RUN update-alternatives --install /usr/bin/java java /usr/lib/jvm/java-7-oracle/bin/java 300
RUN update-alternatives --install /usr/bin/javac javac /usr/lib/jvm/java-7-oracle/bin/javac 300

ENV JAVA_HOME /usr/lib/jvm/java-7-oracle/

# Install tomcat7
RUN cd /tmp && curl -L 'http://archive.apache.org/dist/tomcat/tomcat-7/v7.0.8/bin/apache-tomcat-7.0.8.tar.gz' | tar -xz
RUN mv /tmp/apache-tomcat-7.0.8/ /opt/tomcat7/

ENV CATALINA_HOME /opt/tomcat7
ENV PATH $PATH:$CATALINA_HOME/bin

ADD tomcat7.sh /etc/init.d/tomcat7
RUN chmod 755 /etc/init.d/tomcat7

# Expose ports.
EXPOSE 8080

# Define default command.
ENTRYPOINT service tomcat7 start && tail -f /opt/tomcat7/logs/catalina.out

tomcat7.sh

[plain] view
plain

export JAVA_HOME=/usr/lib/jvm/java-7-oracle/
export TOMCAT_HOME=/opt/tomcat7

case $1 in
start)
sh $TOMCAT_HOME/bin/startup.sh
;;
stop)
sh $TOMCAT_HOME/bin/shutdown.sh
;;
restart)
sh $TOMCAT_HOME/bin/shutdown.sh
sh $TOMCAT_HOME/bin/startup.sh
;;
esac
exit 0

我已經把這些文件上傳到了Github https://github.com/agileshell/dockerfile-jdk-tomcat.git

3. 構建鏡像
腳本寫好了,需要轉換成鏡像:

[plain] view
plain

docker build -t zingdocker/jdk-tomcat .
docker run -d -p 8090:8080 zingdocker/jdk-tomcat

默認情況下,tomcat會佔用8080埠,剛才在啟動container的時候,指定了 -p 8090:8080,映射到宿主機埠就是8090。

http://<host>:8090 host為主機IP

J. Docker鏡像文件中怎麼看分層目錄結構

dockerfile中的每一條命令,都會構建一層文件,可以通過docker save 鏡像名 > 鏡像名.tar 用解壓工具打開這個鏡像名.tar文件,你會發現裡面有很多ID命令的文件夾,和你在docker build時控制台輸入的ID號應該是對應的。可以去試試看

閱讀全文

與docker鏡像中解壓文件相關的資料

熱點內容
aspnetjavaphp 瀏覽:397
程序員畢業時間 瀏覽:285
程序員用戶免費軟體 瀏覽:753
51單片機匯編語言指令 瀏覽:139
女程序員好難 瀏覽:687
三田壓縮機與電裝 瀏覽:710
重生細胞安卓版沒鍵盤怎麼玩 瀏覽:994
小米nfc手機刷加密卡 瀏覽:290
linux如何下載文件 瀏覽:808
linuxrpm依賴 瀏覽:370
匯率pdf 瀏覽:353
帶分數的演算法思維 瀏覽:115
如何讓伺服器支持asp文件 瀏覽:48
python網站自動簽到腳本 瀏覽:889
程序員和語言框架哪個重要 瀏覽:777
文件伺服器上面有什麼 瀏覽:383
需求不清是程序員面臨的真正挑戰 瀏覽:953
放療有關的演算法 瀏覽:750
java和python交互 瀏覽:648
貴州網路伺服器機櫃雲主機 瀏覽:267