docker 學習筆記之實戰 lnmp 環境搭建系列 (3) ------ dockerfile 定製屬於自己的映象

bossaiguo發表於2019-04-14

從映象中產生的容器應該儘量輕量化,能在足夠短的時間內停止、銷燬、重新生成並替換原來的容器。為了減少映象的大小,減少依賴,僅安裝需要的軟體包。我們就得擁有最適合自己專案的映象。接下來就引入我們得下一個知識點 —— dockerfile

映象的定製實際上就是定製每一層所新增的配置、檔案。我們可以把每一層修改、安裝、構建、操作的命令都寫入一個指令碼,用這個指令碼來構建、定製映象。使用dockerfile可以解決docker複用性、安全性、透明性等問題。接下來我們先了解下dockerfile的一些基本命令吧。

dockerfile 基本命令介紹

FROM 指定基礎映象

FROM 指令用於指定其後構建新映象所使用的基礎映象。FROM 指令必是 Dockerfile 檔案中的首條命令,啟動構建流程後,Docker 將會基於該映象構建新映象,FROM 後的命令也會基於這個基礎映象。

//語法格式
// FROM <image>:<tag>
FROM centos:latest

MAINTAINER 映象建立者

//語法格式
//MAINTAINER info
MAINTANWE bossaiguo@qq.com

RUN 映象構建過程中執行命令

在映象的構建過程中執行特定的命令(注意區分 CMD 和 ENTRYPOINT) RUN 指令在定製映象時是最常用的指令之一。其格式有兩種

shell 格式:RUN <命令>,就像直接在命令列中輸入的命令一樣。剛才寫的 Dockerfile 中的 RUN 指令就是這種格式。
exec 格式:RUN ["可執行檔案", "引數1", "引數2"],這更像是函式呼叫中的格式。

注意:Dockerfile 中每一個指令都會建立一層,RUN 也不例外。每一個 RUN 的行為就會新建立一層,在其上執行這些命令,執行結束後,commit 這一層的修改,構成新的映象。因此,這裡沒有使用很多個 RUN 對一一對應不同的命令,而是僅僅使用一個 RUN 指令,並使用 && 將各個所需命令串聯起來。

//shell 格式
RUN echo 'Hello, Docker!' 
//exec 格式
RUN["/bin/bash", "-c", "echo hello world"]

CMD 容器啟動後所要執行的命令

CMD service nginx start
shell格式: CMD <命令> \
exec格式:CMD [“可執行檔案”,”引數1”,”引數2”]

//錯誤示範
CMD service nginx start

發現容器執行後就立即退出了。甚至在容器內去使用 **systemctl** 命令結果卻發現根本執行不了。這就是因為沒有搞明白前臺、後臺的概念,沒有區分容器和虛擬機器的差異,依舊在以傳統虛擬機器的角度去理解容器。

對於容器而言,其啟動程式就是容器應用程式,容器就是為了主程式而存在的,主程式退出,容器就失去了存在的意義,從而退出,其它輔助程式不是它需要關心的東西。

而使用 `service nginx start` 命令,則是希望 **upstart** 來以後臺守護程式形式啟動 **nginx** 服務。而剛才說了 `CMD service nginx start` 會被理解為
    CMD [ "sh", "-c", "service nginx start"]
因此主程式實際上是 **sh**。那麼當 `service nginx start` 命令結束後,**sh** 也就結束了,**sh** 作為主程式退出了,自然就會令容器退出。

正確的做法是直接執行 nginx 可執行檔案,並且要求以前臺形式執行。比如:
    CMD ["nginx", "-g", "daemon off;"]

#### CMD 容器啟動後所要執行的命令

ENTRYPOINT 的 Exec 格式用於設定容器啟動時要執行的命令及其引數,同時可通過CMD命令或者命令列引數提供額外的引數。ENTRYPOINT 中的引數始終會被使用,這是與CMD命令不同的一點。

ENTRYPOINT ["/bin/echo", "Hello"]  

RUN CMD ENTRYPOINT 區別

  1. RUN命令執行命令並建立新的映象層,通常用於安裝軟體包
  2. CMD命令設定容器啟動後預設執行的命令及其引數,但CMD設定的命令能夠被docker run命令後面的命令列引數替換
  3. ENTRYPOINT配置容器啟動時的執行命令(不會被忽略,一定會被執行,即使執行 docker run時指定了其他命令)

    COPY 複製檔案

    和 RUN 指令一樣,也有兩種格式,一種類似於命令列,一種類似於函式呼叫。COPY 指令將從構建上下文目錄中 <源路徑> 的檔案/目錄複製到新的一層的映象內的<目標路徑>位置。

    COPY package.json /usr/src/app/

    ADD 更高階的複製檔案

    ADD 指令和 COPY 的格式和性質基本一致。但是在 COPY 基礎上增加了一些功能。比如<源路徑>可以是一個 URL,這種情況下,Docker 引擎會試圖去下載這個連結的檔案放到<目標路徑>去。而且會將檔案自動解壓

ENV 設定環境變數

這個指令很簡單,就是設定環境變數而已,無論是後面的其它指令,如 RUN,還是執行時的應用,都可以直接使用這裡定義的環境變數

ENV VERSION=1.0 DEBUG=on 

EXPOSE

EXPOSE 指令並不會讓容器監聽 host 的埠,如果需要,需要在 docker run 時使用 -p-P 引數來發布容器埠到 host 的某個埠上

VOLUME 定義匿名卷

VOLUME用於建立掛載點,即向基於所構建映象創始的容器新增捲

dockerfile 示例

構建php映象

FROM centos:latest
MAINTAINER https://blog.51cto.com/andyxu
ENV TIME_ZOME Asia/Shanghai
ARG PV="php-7.2.11"

ADD $PV.tar.gz /tmp
RUN yum -y install gcc gcc-c++ make gd-devel libxml2-devel libcurl-devel libjpeg-devel libpng-devel openssl-devel bison \
    && mkdir /data \
    && cd /tmp/$PV \
    && ./configure --prefix=/data/php \
        --with-config-file-path=/data/php/etc \
        --with-gd --with-mysqli \
        --with-openssl --with-zlib --with-curl \
        --with-jpeg-dir --with-png-dir --with-iconv \
        --enable-fpm --enable-zip --enable-mbstring \
    && make -j 4 \
    && make install \
    && cp /data/php/etc/php-fpm.conf.default /data/php/etc/php-fpm.conf \
    && cp /data/php/etc/php-fpm.d/www.conf.default /data/php/etc/php-fpm.d/www.conf \
    && sed -i '/;daemonize/a\daemonize = no' /data/php/etc/php-fpm.conf \
    && sed -i 's/127.0.0.1/0.0.0.0/g' /data/php/etc/php-fpm.d/www.conf \
    && echo "${TIME_ZOME}" > /etc/timezone \
    && ln -sf /usr/share/zoneinfo/${TIME_ZOME} /etc/localtime \
    && rm -rf /tmp/php* \
    && yum clean all \
    && yum -y remove gcc gcc-c++ make

WORKDIR /data/php/
EXPOSE 9000
CMD ["sbin/php-fpm","-c","etc/php-fpm.conf"]
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章