1. 程式人生 > >編寫 Dockerfile 生成自定義映象

編寫 Dockerfile 生成自定義映象

一般情況下我們可以從公共渠道諸如 [DockerHub](https://hub.docker.com) 獲取映象上獲取映象,但是在實際生產過程中,往往需要定製化的映象,例如修改一些配置檔案,增加一些特殊的命令或軟體等需求,這時就需要通過編寫 Dockerfile 來生成自定義的映象檔案。 ## Dockerfile介紹 Dockerfile 是一個文字格式的配置檔案,通過編寫 Dockerfile 指令碼來定義自己需要的映象。Dockerfile 檔案由一行行命令語句組成,檔案中的註釋資訊以 # 開頭。編輯好 Dcokerfile 檔案之後,我們可以通過 `docker build -t .` 命令生成自己定義的映象檔案。 ## Dockerfile基本結構 我們看一下 [alpine](https://github.com/alpinelinux/docker-alpine/blob/f3d17bcb7b1fa51cf9b011403cd58e00fbbcd000/x86_64/Dockerfile) 的 Dockerfile 檔案: ```dockerfile FROM scratch ADD alpine-minirootfs-20201218-x86_64.tar.gz / CMD ["/bin/sh"] ``` Dockerfile 檔案主要由三部分組成: * FROM 屬於配置指令部分,表明基於的映象名稱。`scratch` 指從空白開始。 * ADD 屬於操作指令部分,表示向映象內加入內容。 * CMD 也屬於操作指令部分,一般做為最後一行,表示執行容器時的操作命令。 ## 指令說明 Dockerfile 中指令的一般格式為 `INSTRUCTION arguments` ,指令分兩種 配置指令 和 操作指令,具體如下: * 配置指令 * ARG : 定義建立映象過程中使用的變數,格式為 `ARG [=]` * FROM : 指定所建立映象的基礎映象。格式為 `FROM :` * LABEL : 為生成的映象新增元資料標籤資訊,輔助過濾特定映象。格式為 `LABEL = =` * EXPOSE : 宣告映象內服務監聽的埠。格式為 `EXPOSE [/]` * ENV : 指定環境變數,該變數在容器中存在,也可在容器啟動時覆蓋。格式為 `ENV ` * ENTRYPOINT : 指定映象的預設入口命令,做為容器啟動時的根命令執行。格式為 `ENTRYPOINT ["executable", "param1", "param2"]` 或者 `ENTRYPOINT command param1 param2` * VOLUME : 建立一個數據卷掛載點。格式為 `VOLUME ["/data"]` * USER : 指定容器執行時的使用者名稱或UID,後續的RUN指令也使用該使用者身份。格式為 `USER daemon` * WORKDIR : 配置RUN\CMD\ENTRYPOINT等指令的工作目錄,推薦使用絕對路徑。格式為:`WORKDIR /path/to/workdir` * ONBUILD : 指定當基於所生成映象建立子映象時,自動執行的操作指令。 * STOPSIGNAL : 指定容器接收退出的訊號值。格式為: `STOPSIGNAL signal` * HEALTHCHECK : 配置容器健康檢查命令,自 Docker 1.12 開始支援。格式為: `HEALTHCHECK [OPTIONS] CMD command` * SHELL : 指定預設的shell型別。格式為: `SHELL ["executable", "parameters"]` * 操作指令 * RUN : 執行指定命令。格式為: `RUN ` 或 `RUN ["executable", "param1", "param2"]` 當命令較長時,可以用 \ 來換行。 * CMD : 指定容器啟動時預設執行的命令,每個Dockerfile只能有一條CMD命令。格式有三種,分別為:`CMD ["executable", "param1", "param2"]` 或 `CMD command param1 param2` 或 `CMD ["param1", "param2"]` * ADD : 新增內容到映象中,將SRC內容複製到DEST中。格式為: `ADD ` * COPY : 複製內容到映象中。格式為 : `COPY ` ## 建立映象 建立映象的命令格式為 ```sh $ docker build [OPTIONS] PATH | URL | - ``` docker build 命令讀取指定路徑下的 Dockerfile 檔案,並將該路徑下的所有資料作為上下文傳送給 Docker 服務端。服務端完成 Dockerfile 格式校驗後,按順序執行指令命令,遇到ADD、COPY和RUN指令會生成新一層的映象檔案。映象建立成功後,返回映象ID。 docker build 還有很多選項,最常用的是通過 `-t` 增加標籤。 ```sh $ docker build -t test:0.1 . ``` 當 Dockerfile 所在的資料夾檔案過多時,為避免向服務端上傳上下文過大,可以通過 .dockerignore 檔案來讓 Docker 忽略無關的檔案。 ```sh $ cat .dockerignore *xls *docx README.md ``` ## 實戰案例 總的來說,通過編寫 Dockerfile 生成自定義映象的過程不復雜,但是能生成高效的映象還需要不斷的嘗試和聯絡,一般來說用於生產的映象都儘量保證用途單一,減少映象的層數,選擇合適的基礎映象減小映象檔案大小,形成自己的版本號和標籤管理規則,這樣能提高自己生成映象的質量。 下面就以一個簡單定義 python 基礎映象的例子,基礎的 python 映象缺少很多包例如爬蟲常用的 requests ,自己定義一個包含 requests 包的映象,編寫的 Dockerfile 如下: ```dockerfile FROM python:3.6 RUN pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple requests ``` 執行映象的建立命令 ```sh $ docker build -t python-requests-3.6:0.1 . $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE python-requests-3.6 0.1 3c2bb72b2066 2 minutes ago 884MB python 3.6 85146760634c 7 weeks ago 874MB $ docker run --rm -it -v "$PWD":/usr/src -w /usr/src python-requests-3.6:0.1 python3 Python 3.6.12 (default, Nov 18 2020, 14:46:32) [GCC 8.3.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import requests >>> response = requests.get("http://baidu.com") >>> print(response.text)
``` 可以看到映象內的 python 環境已經支援 requests 包了。利用這種方式,我們不用在本地維護開發環境,特別是多個版本的開發環境,通過 Docker 生成不同版本的映象能夠快速的實現多版本的開發環境,大家可以參考 [利用 Docker 構建一個簡單的 java 開發編譯環境](http://edulinks.cn/2020/11/12/20201111-build-java-devlopment-env-with-docker/) 。自己定義的各種映象,可以上傳到 DockerHub,更換電腦後僅需要安裝 Docker,之前的各種開發環境就回來了。 對於 Docker 有進一步興趣的,可以參考我的其他文章: * [Docker 入門介紹](http://edulinks.cn/2018/06/20/20180620-docker-overview/) * [在Redhat 7.3中採用離線方式安裝Docker](http://edulinks.cn/2018/07/11/20180711-install-docker-ce-in-redhat-73/) * [建立自己的Docker基礎映象](http://edulinks.cn/2018/06/27/20180627-make-your-own-base-docker-image/) * [Docker存出載入映象](http://edulinks.cn/2018/07/16/20180716-docker-save-load-image/) * [Docker Compose 使用介紹](http://edulinks.cn/2020/04/15/20200415-docker-compose/) * [使用 Docker 快速搭建PHP開發環境](http://edulinks.cn/2020/04/17/20200415-qucik-lnmp-dev-environment/) * [Docker Compose 建立ELK叢集](http://edulinks.cn/2020/01/15/20200115-docker-compose-elk-cluster/) 最後說點雜事,2021年剛開始沒幾天,年前立下的雄心壯志馬上被各種無計劃的事打亂了,感覺總是被打斷,感覺總是時間不夠用,原來以為是自己能力不夠用,最近在雲+社群上讀了一個時間管理系列文章,才發現原來是自己堅持不夠,給了自己點信心,2021剛開始還要繼續加油才是,附上這個系列文章的連結,感興趣的朋友可以讀一讀。 ![](https://img2020.cnblogs.com/blog/39469/202101/39469-20210107222052637-12775570