Create a Image with Dockerfile

Ubuntu: 18.04

Docker: 18.09

在很多狀況下,Docker Hub 上面的 Image ,可能都不太符合我們的使用需求,因此我們就會需要自己客製一個屬於自己的 Docker Image,但如果先隨便建一個 Container 再慢慢裝自己想要的東西,一來指令跟裝的東西不好控管、二來是時間成本太高,這時候就需要 Dockerfile 來幫忙了。

Dockerfile 是一個設置你 Docker Image 的文件,根據文件內容再搭配 Docker build 指令就可以產生出 Docker Image

Dockerfile

在開始之前,先介紹一下在 Dockerfile 中可以使用的指令。

Name Description
FROM 指定 Image
格式為 FROM <image>FROM <image>:<tag>
LABEL 用來指定維護者的資訊,可以用 docker inspect 指令查詢 。
RUN 執行指令,通常用來操作細部動作,例如安裝套件、處理檔案等等。
格式有兩種:
- RUN <command>
- RUN ["executable", "param1", "param2"](使用 exec 執行)
若指令太長可以使用 \ 來換行。
CMD 執行指令,每個 Dockerfile 只能有一條 CMD 命令,通常用在 啟動服務 的指令。有三種使用格式:
- CMD ["executable","param1","param2"](使用 exec 執行)
- CMD command param1 param2(使用 /bin/sh 執行)
- CMD ["param1","param2"](為 ENTRYPOINT 指定參數)
ENTRYPOINT 執行指令,不會被 docker run 的參數覆蓋,且一定會執行;每個 Dockerfile 只能有一條 ENTRYPOINT 命令,通常用在把該 Image 當成一個 執行檔 時使用。
有兩種使用格式:
- ENTRYPOINT ["executable", "param1", "param2"](使用 exec 執行)
- ENTRYPOINT command param1 param2 (使用 /bin/sh 執行)
EXPOSE 用來紀錄該服務使用 port 及 protocol 的 文件(實際綁定還是需要依靠 docker run -p)。
ENV 設定一個環境變數,使其可以在 RUN 的指令中使用。
ADD 複製指定的目錄到Container 中。其中目錄也可以是遠端的檔案(URL),ADD 指令也會自動將 .tar 解壓縮。
COPY 複製本機的目錄到 Container 中。
VOLUME 建立一個將本機目錄掛載進 Container 中的掛載點。
USER 切換到指定的用戶,接下來執行的指令皆由該用戶身份執行。
WORKDIR 指定 Container 執行起來時的預設目錄位置。
ONBUILD 格式為 ONBUILD [INSTRUCTION]
當這個 Image 做為其他人的 Base Image 時所執行的指令。

Usage

一般來說,一個完整的 Dockerfile 至少會有幾個區塊:Base ImageMaintainer 資訊Container 指令操作服務啟動

Dockerfile

# This is a test image

# Base image
FROM ubuntu:19.04

# Maintainer information
LABEL owner="JohnsonLu" version="1.0" description="This is a test service of Apache httpd"

# Command to update the image
RUN apt-get update && apt-get install -y apache2

# Commands when creating a new container
CMD apachectl -DFOREGROUND

Dockerfile 撰寫完成之後,可以透過 docker build 建立 Image

Create Image

; 將特定目錄建置成 Docker Image
; -t 設定 name:tag
; --no-cahce 為不使用 cache 建立 Image
docker build -t johnsonlu/httpd:1.0 --no-cache .

Notice: 該指令會根據該目錄底下的 Dockerfile 檔案進行建置。如果想要指定 Dockerfile,可以使用 -f 參數。

建立完成之後,接著就可以建立 Container 了。

Build Container

; 將本機的 8080 port 綁定到 Container 的 80 port
docker run -d --name apache -p 8080:80 johnsonlu/httpd:1.0

Performance

由於 Docker Image 儲存的方式是以 Layers 的方式儲存,所以會把每個指令之間的紀錄都保存下來,如果在撰寫 Dockerfile 時,冗長的指令太多,就很有可能會導致 Docker Image 肥大。

ADD

Docker 文件 中有提到,雖然 ADD 指令可以下載遠端檔案,但如果用 RUN 搭配 curlpipeline 會更節省空間。

ADD 用法

ADD http://example.com/big.tar.xz /usr/src/things/
RUN tar -xJf /usr/src/things/big.tar.xz -C /usr/src/things
RUN make -C /usr/src/things all

curl用法

RUN mkdir -p /usr/src/things \
    && curl -SL http://example.com/big.tar.xz \
    | tar -xJC /usr/src/things \
    && make -C /usr/src/things all
Categories: Docker