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 Image、Maintainer 資訊、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 搭配 curl 和 pipeline 會更節省空間。
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