docker入門與實踐之【04-使用dockerfile定製鏡像】

利用dockerfile定製鏡像

Dockerfile 是一個文本文件,其內包含了一條條的指令(Instruction),每一條指令構建一層,所以每一條指令的內容,就是描述該層應當如何構建。html

以定製nginx 鏡像爲例,使用 Dockerfile 來定製。nginx

在一個空白目錄中,創建一個文本文件,並命名爲 Dockerfile:git

$ mkdir mynginx
$ cd mynginx
$ touch Dockerfile

其內容爲:github

FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html

1 FROM 指定基礎鏡像

所謂定製鏡像,那必定是以一個鏡像爲基礎,在其上進行定製.FROM 就是指定基礎鏡像,一個 Dockerfile 中 FROM 是必備的指令,而且必須是第一條指令。redis

2 RUN 執行命令

RUN 指令是用來執行命令行命令的。因爲命令行的強大能力,RUN 指令在定製鏡像時是最經常使用的指令之一。其格式有兩種:docker

  • shell 格式:RUN <命令>,就像直接在命令行中輸入的命令同樣。剛纔寫的 Dockerfile 中的 RUN 指令就是這種格式。
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
  • exec 格式:RUN ["可執行文件", "參數1", "參數2"],這更像是函數調用中的格式。

Dockerfile 中每個指令都會創建一層,RUN 也不例外。每個 RUN 的行爲,就和剛纔咱們手工創建鏡像的過程同樣:新創建一層,在其上執行這些命令,執行結束後,commit 這一層的修改,構成新的鏡像。shell

Union FS 是有最大層數限制的,好比 AUFS,曾經是最大不得超過 42 層,如今是不得超過 127 層。爲了避免生成非必要層,使用RUN指令時,可使用以下方法:函數

FROM debian:jessie
RUN buildDeps='gcc libc6-dev make' \
    && apt-get update \
    && apt-get install -y $buildDeps \
    && wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz" \
    && mkdir -p /usr/src/redis \
    ···

這裏僅僅使用一個 RUN 指令,並使用 && 將各個所需命令串聯起來,將多層簡化爲了 1 層。在撰寫 Dockerfile 的時候,要常常提醒本身,這並非在寫 Shell 腳本,而是在定義每一層該如何構建。工具

Dockerfile 支持 Shell 類的行尾添加 \ 的命令換行方式,以及行首 # 進行註釋的格式。良好的格式,好比換行、縮進、註釋等,會讓維護、排障更爲容易,這是一個比較好的習慣。gitlab

3.構建鏡像

在 Dockerfile 文件所在目錄執行:

$ docker build -t nginx:v3 .
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM nginx
 ---> e43d811ce2f4
Step 2 : RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
 ---> Running in 9cdc27646c7b
 ---> 44aa4490ce2c
Removing intermediate container 9cdc27646c7b
Successfully built 44aa4490ce2c

可使用docker build 命令進行鏡像構建。其格式爲:

docker build [選項] <上下文路徑/URL/->
如:docker build -t nginx:v3 . #指定最終鏡像的名稱: -t nginx:v3

4.鏡像構建上下文(Context)

docker build 命令最後有一個 .。. 表示當前目錄,而 Dockerfile 就在當前目錄,所以很多初學者覺得這個路徑是在指定 Dockerfile 所在路徑,這麼理解實際上是不許確的,這是在指定上下文路徑。

Docker 在運行時分爲 Docker 引擎(也就是服務端守護進程)和客戶端工具。而如 docker 命令這樣的客戶端工具,則是經過這組 API 與 Docker 引擎交互,從而完成各類功能。所以,雖然表面上咱們好像是在本機執行各類 docker 功能,但實際上,一切都是使用的遠程調用形式在服務端(Docker 引擎)完成。

進行鏡像構建的時候,並不是全部定製都會經過 RUN 指令完成,常常會須要將一些本地文件複製進鏡像,好比經過 COPY 指令、ADD 指令等。而 docker build 命令構建鏡像,其實並不是在本地構建,而是在服務端,也就是 Docker 引擎中構建的。

當構建的時候,用戶會指定構建鏡像上下文的路徑,docker build 命令得知這個路徑後,會將路徑下的全部內容打包,而後上傳給 Docker 引擎。這樣 Docker 引擎收到這個上下文包後,展開就會得到構建鏡像所需的一切文件。

總結: docker打包是在服務端,構建時會在上下文路徑下的全部內容打包上傳到服務端進行,後續的構建只會操做該路徑下的內容。

默認狀況下,若是不額外指定 Dockerfile 的話,會將上下文目錄下的名爲 Dockerfile 的文件做爲 Dockerfile。 可使用-f -f /PATH/MyDockerfile 參數指定某個文件做爲 Dockerfile

5.其它 docker build 的用法

5.1 直接用 Git repo 進行構建

docker build 還支持從 URL 構建,好比能夠直接從 Git repo 中構建:

$ docker build https://github.com/twang2218/gitlab-ce-zh.git#:8.14

5.2 用給定的 tar 壓縮包構建

若是所給出的 URL 不是個 Git repo,而是個 tar 壓縮包,那麼 Docker 引擎會下載這個包,並自動解壓縮,以其做爲上下文,開始構建。

docker build http://server/context.tar.gz

5.3 從標準輸入中讀取 Dockerfile 進行構建

若是標準輸入傳入的是文本文件,則將其視爲 Dockerfile,並開始構建。這種形式因爲直接從標準輸入中讀取 Dockerfile 的內容,它沒有上下文,所以不能夠像其餘方法那樣能夠將本地文件 COPY 進鏡像之類的事情。

docker build - < Dockerfile
或 cat Dockerfile | docker build -

5.4 從標準輸入中讀取上下文壓縮包進行構建

若是發現標準輸入的文件格式是 gzip、bzip2 以及 xz 的話,將會使其爲上下文壓縮包,直接將其展開,將裏面視爲上下文,並開始構建。

$ docker build - < context.tar.gz
相關文章
相關標籤/搜索