[Docker] 透過 Dockerfile 來創建 Image

Dockerfile 就像一個告訴 Docker 所需要的環境大概長什麼樣子的描述檔,可以在文件中定義創建後的 Image,並且可以在 Container 建立完成後,執行所制定的操作,有助於環境轉移之後,更便利於與其他共事的夥伴同步環境相當方便。

前言

上一篇文章「[Docker] Container 進階操作」中有提及到一個觀點,現在多數 Docker 除了被當作是環境建置以外,也有些人將其當成工具包使用,故在一些 Github 上的專案、工具都會提供 Dockerfile 讓使用者快速建置相同環境,這也是本篇主要探討的主題。

What’s Dockerfile

可以將 Dockerfile 稱作建立 Image 的描述檔或腳本,當使用 docker build 指令時,首先會查看當前目錄是否存在 Dockerfile,如果有則會進行解析並執行,至於執行的內容則可以藉由操作撰寫 Dockerfile 自行定義。

Create Dockerfile

要創建一個有效的 Dockerfile 則需要了解如何撰寫,下列會逐一說明語法的用法。

FROM

用途:指定要使用的 Image 名稱

FROM ubuntu:latest

ENV

用途:設定 Container 的環境變數

EVN NGINX_VERSION=1.8

RUN

用途:設定 Image 在被建立完成後所要執行的指令

RUN apt update
RUN apt install nginx=${NGINX_VERSION} -y

EXPOSE

用途:設定 Container 所要使用的 Port

EXPOSE 80

CMD

用途:設定 Container 啟動完成之後要執行的指令,這邊要注意與 RUN 不同,RUN 是在被建立之後才執行,CMD 則是在啟動時(包含在自動啟動的情況下)。

CMD ["nginx", "-g", "daemon off;"]

MAINTAINER

用途:設定 Dockerfile 的作者資訊

MAINTAINER By MksYi

WORKDIR

用途:設定工作路徑,可以當作平常在 Terminal 下使用 cd 指令。

WORKDIR /tmp

ADD

用途:將檔案或目錄加入到 Image 的指定路徑底下,此外如果指定加入的檔案為 tar 則會自動解壓縮至指定目錄。

ADD index.html /user/share/nginx/html
ADD my_website.tar /user/share/nginx/html

COPY

用途:用途與 ADD 相同,不同的的是將檔案或目錄放置於 Container 之中,官方建議以使用 COPY 為主,除非有解壓縮需求才使用 ADD。

COPY index.html /usr/share/nginx/html

ENTRYPOINT

用途:功能與 CMD 雷同,主要差異在於使用 docker run -it <Container> <Command> 時,會將 Command 當作 Options 放置在所設置的 ENTRYPOINT 指令後面,以下做個簡單範例。

ENTRYPOINT ['/bin/bash']

並且建立 Container 嘗試使用 -it 指令。

docker build -t ubuntu-entrypoint .
docker run -it ubuntu-entrypoint ls

由於設置 ENTRYPOINT ['/bin/bash'] 的關係,所以當我執行 ls 指令時,會自動變成 /bin/bash ls

LABEL

用途:用於新增 Image 資訊,可於 docker image inspect <Image> 查看 LABEL 內容。

LABEL version=1.0 description="test"

USER

用途:Docker 的預設使用者為 root,如果想自己建立新的使用者可以先透過 RUN 建立,並透過 USER 指定使用者。

RUN useradd -ms /bin/bash mksyi
USER mksyi
WORKDIR /home/mksyi

VOLUME

用途:如同「[Docker] Container 進階操作」所提及到的 Volume 一樣,可以在 Dockerfile 下建立掛載點。

VOLUME /usr/share/nginx/html /var/log/nginx

ARG

用途:可以透過 ARG 將條件參數化,好處在於可以不用為了調整條件而修改 dockerfile

ARG NGINX_VERSION=1.8

在建置時可以使用 --build-arg <ARG_Key>=<ARG_Value> 來控制。

docker build -t nginx-arg . --build-arg NGINX_VERSION=1.4
  • 如果 ENV 與 ARG 同時使用時,則須注意會以 ENV 為主。

簡單 Demo 範例

Dockerfile

FROM ubuntu:latest

RUN apt update
RUN apt install nginx -y

COPY index.html /var/www/html

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Test Page</title>
</head>
<body>
    <h1>This is a Test Page.</h1>
</body>
</html>

創建 Image

# docker build -t <Image Name>:<Tag Name> .
docker build -t nginx-service:mksyi-demo .

啟動 Container

Get ImageID

docker images
REPOSITORY            TAG          IMAGE ID       CREATED        SIZE
nginx-service      mksyi-demo   ca1a8207d300   a minutes ago     164MB

Run Container

# docker run -p "<output port>:<default port>" <ImageID>
docker run -p "9999:80" ca1a8207d300

匯出匯入 Image 或 Container

匯出

docker save -o <Image File Name> <Export Image Name>:<Version>
docker export -o <Image File Name> <Export Container>

匯入

docker load -i <Image File>
docker import -o <Image File Name> <Import Image Name>:<Version>

[Windows] 為什麼選擇從 WSL2 降回 WSL1

身為一個 WSL 的重度使用者來說,基本上已經無法脫離 WSL 所帶來的便利,快速的啟動時間,並且任意的在 Windows 與 Linux 環境間自由切換,如需要使用 Linux Only 的工具時,僅需要打開 Windows Terminal 即可直接使用,不用在仰賴 VM,不必等待沉長的開機時間,更不用消耗虛擬機所帶來的資源消耗(CPU、RAM、Disk)。

Read More