Dockerfile總結:常用指令、注意事項、常見錯誤(no such file or directory、Permission denied)

什麼是 Dockerfile?

Dockerfile 是一個用來構建鏡像的文本文件,文本內容包含了一條條構建鏡像所需的指令和說明。


指令詳解

點擊參考:使用 Dockerfile 定製鏡像

注意事項

  • RUN (docker鏡像越來越大的原因之一)

    RUN <命令行命令> # <命令行命令> 等同於,在終端操作的 shell 命令。

    注意: Dockerfile 的指令每執行一次都會在 docker 上新建一層。所以過多無意義的層,會造成鏡像膨脹過大。例如:

    FROM centos
    RUN yum install wget
    RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
    RUN tar -xvf redis.tar.gz
    
    以上執行會創建 3 層鏡像。可簡化爲以下格式:
    
    FROM centos
    RUN yum install wget \
        && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
        && tar -xvf redis.tar.gz
    

    如上,以 && 符號連接命令,這樣執行後,只會創建 1 層鏡像。

  • CMD

    作用:爲啓動的容器指定默認要運行的程序,程序運行結束,容器也就結束。CMD 指令指定的程序可被 docker run 命令行參數中指定要運行的程序所覆蓋。

    注意:如果 Dockerfile 中如果存在多個 CMD 指令,僅最後一個生效。

    格式:
    CMD <shell 命令>
    CMD ["<可執行文件或命令>","","",…]
    CMD ["","",…] # 該寫法是爲 ENTRYPOINT 指令指定的程序提供默認參數

    推薦使用第二種格式,執行過程比較明確。第一種格式實際上在運行的過程中也會自動轉換成第二種格式運行,並且默認可執行文件是 sh。

  • ENTRYPOINT

    類似於 CMD 指令,但其不會被 docker run 的命令行參數指定的指令所覆蓋,而且這些命令行參數會被當作參數送給 ENTRYPOINT 指令指定的程序。

    但是, 如果運行 docker run 時使用了 --entrypoint 選項,此選項的參數可當作要運行的程序覆蓋 ENTRYPOINT 指令指定的程序。

    優點:在執行 docker run 的時候可以指定 ENTRYPOINT 運行所需的參數。

    注意:如果 Dockerfile 中如果存在多個 ENTRYPOINT 指令,僅最後一個生效。

    格式:

    ENTRYPOINT ["","","",…]

    可以搭配 CMD 命令使用:一般是變參纔會使用 CMD ,這裏的 CMD 等於是在給 ENTRYPOINT 傳參。

    示例:

    假設已通過 Dockerfile 構建了 nginx:test 鏡像:

    FROM nginx

    ENTRYPOINT [“nginx”, “-c”] # 定參
    CMD ["/etc/nginx/nginx.conf"] # 變參

    1、不傳參運行

      docker run  nginx:test
    

    容器內會默認運行以下命令,啓動主進程。

      nginx -c /etc/nginx/nginx.conf
    

    2、傳參運行

      docker run  nginx:test -c /etc/nginx/new.conf
    

    容器內會默認運行以下命令,啓動主進程(/etc/nginx/new.conf:假設容器內已有此文件)

      nginx -c /etc/nginx/new.conf
    
  • FROM

    多個FROM聲明
    嘗試使用多個FROM聲明來將不同的鏡像組合到一起,這樣不會起任何作用。Docker僅使用最後一個FROM並且忽略前面所有的。

    所以如果你有這樣的Dockerfile:

    # !!! ANTIPATTERN !!!
    FROM node:6.2.1
    FROM python:3.5
    CMD ["sleep", "infinity"]
    # !!! ANTIPATTERN !!! 
    

    那麼docker exec進入運行的容器中,會得到下面的結果:

    $ docker exec -it d86fcf0775d3 bash
    root@d86fcf0775d3:/# which python
    /usr/local/bin/python
    root@d86fcf0775d3:/# which node
    root@d86fcf0775d3:/#
    

    這其實是GitHub上的一個問題:合併不同的鏡像,但它看起來不會很快就增加的功能。


dockerfile常見錯誤

  • COPY時提示no such file or directory

    例如如下錯誤信息:

      COPY failed: stat /var/lib/docker/..... no such file or directory
    

    可能的原因:

      文件不存在
      文件路徑寫法錯誤
    

    docker鏡像打包的COPY 指令將從構建上下文目錄中 <源路徑> 的文件/目錄複製到新的一層的鏡像內的 <目標路徑> 位置。
    實際操作中正確的方式和錯誤的方式參考如下:
    正確:

    COPY ./package.json /app/
    COPY package.json /usr/src/app/
    

    錯誤:

    COPY ../package.json /app
    或者
    COPY /opt/xxxx /app
    
  • Permission denied問題

    執行

      RUN chmod +x configure
    

    時報錯

      chmod: cannot access 'configure': Permission denied
    

    提升權限即可,如數據/程序在‘/home/’

      RUN chmod 777 /home/
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章