1. 程式人生 > >docker之dockerFile(解決hosts,hostname問題)

docker之dockerFile(解決hosts,hostname問題)

以前自己使用docker的方式都是直接使用映象來進行建立,今天嘗試了一下使用dockerfile來進行建立,發現似乎這才更加符合docker的思想-----在原始映象上面新增改動層,然後更具改動建立自己的映象檔案。(不知道理解是否有錯誤)。首先我們來了解一些dockerfile的基本語法:

在Dockerfile中用到的命令有
FROM
    FROM指定一個基礎映象, 一般情況下一個可用的 Dockerfile一定是 FROM 為第一個指令。至於image則可以是任何合理存在的image映象。
    FROM 一定是首個非註釋指令 Dockerfile.
    FROM 可以在一個 Dockerfile 中出現多次,以便於建立混合的images。
    如果沒有指定 tag ,latest 將會被指定為要使用的基礎映象版本。
MAINTAINER
    這裡是用於指定映象製作者的資訊
RUN
    RUN命令將在當前image中執行任意合法命令並提交執行結果。命令執行提交後,就會自動執行Dockerfile中的下一個指令。
    層級 RUN 指令和生成提交是符合Docker核心理念的做法。它允許像版本控制那樣,在任意一個點,對image 映象進行定製化構建。
    RUN 指令快取不會在下個命令執行時自動失效。比如 RUN apt-get dist-upgrade -y 的快取就可能被用於下一個指令. --no-cache 標誌可以被用於強制取消快取使用。
ENV
    ENV指令可以用於為docker容器設定環境變數
    ENV設定的環境變數,可以使用 docker inspect命令來檢視。同時還可以使用docker run --env <key>=<value>來修改環境變數。
USER
    USER 用來切換執行屬主身份的。Docker 預設是使用 root,但若不需要,建議切換使用者身分,畢竟 root 許可權太大了,使用上有安全的風險。
WORKDIR
    WORKDIR 用來切換工作目錄的。Docker 預設的工作目錄是/,只有 RUN 能執行 cd 命令切換目錄,而且還只作用在當下下的 RUN,也就是說每一個 RUN 都是獨立進行的。如果想讓其他指令在指定的目錄下執行,就得靠 WORKDIR。WORKDIR 動作的目錄改變是持久的,不用每個指令前都使用一次 WORKDIR。
COPY
    COPY 將檔案從路徑 <src> 複製新增到容器內部路徑 <dest>。
    <src> 必須是想對於原始檔夾的一個檔案或目錄,也可以是一個遠端的url,<dest> 是目標容器中的絕對路徑。
    所有的新檔案和資料夾都會建立UID 和 GID 。事實上如果 <src> 是一個遠端檔案URL,那麼目標檔案的許可權將會是600。
ADD
    ADD 將檔案從路徑 <src> 複製新增到容器內部路徑 <dest>。
    <src> 必須是想對於原始檔夾的一個檔案或目錄,也可以是一個遠端的url。<dest> 是目標容器中的絕對路徑。
    所有的新檔案和資料夾都會建立UID 和 GID。事實上如果 <src> 是一個遠端檔案URL,那麼目標檔案的許可權將會是600。
VOLUME
    建立一個可以從本地主機或其他容器掛載的掛載點,一般用來存放資料庫和需要保持的資料等。
EXPOSE
    EXPOSE 指令指定在docker允許時指定的埠進行轉發。

CMD
    Dockerfile.中只能有一個CMD指令。 如果你指定了多個,那麼最後個CMD指令是生效的。
    CMD指令的主要作用是提供預設的執行容器。這些預設值可以包括可執行檔案,也可以省略可執行檔案。
    當你使用shell或exec格式時,  CMD 會自動執行這個命令。
ONBUILD
    ONBUILD 的作用就是讓指令延遲執行,延遲到下一個使用 FROM 的 Dockerfile 在建立 image 時執行,只限延遲一次。
    ONBUILD 的使用情景是在建立映象時取得最新的原始碼 (搭配 RUN) 與限定系統框架。
ARG
    ARG是Docker1.9 版本才新加入的指令。
    ARG 定義的變數只在建立 image 時有效,建立完成後變數就失效消失
LABEL
    定義一個 image 標籤 Owner,並賦值,其值為變數 Name 的值。(LABEL Owner=$Name )

ENTRYPOINT
    是指定 Docker image 執行成 instance (也就是 Docker container) 時,要執行的命令或者檔案。

上面就是我們建立的基本語法,必須以FROM開始。但是有一個問題,我們在對docker容器中的hosts,hostname等檔案進行修改時只是進行了臨時的改變,我們下一次啟動同一個容器的時候又恢復為了預設值。這樣我們就需要每次啟動都需要進行相關的修改。感覺這樣做太繁瑣了。

想想docker是幹什麼的?就是在基礎映象上面新增改動層,這種思想其實是很方便的,我們不需要去更改作業系統的原始碼,或者是顯示的更改docker的映象檔案就可以從系統層面上進行修改。那麼我們可以直接新增一個改動層,讓改動層來支援我們進行這些檔案的操作。再stackoverflow上面看到一中改動的方法是這樣的:

FROM ubuntu:14.04
RUN cp /etc/hosts /tmp/hosts
RUN mkdir -p -- /lib-override && cp /lib/x86_64-linux-gnu/libnss_files.so.2 /lib-override
RUN sed -i 's:/etc/hosts:/tmp/hosts:g' /lib-override/libnss_files.so.2
ENV LD_LIBRARY_PATH /lib-override
就是把啟動時載入的檔案給他進行相關的替換,替換成我們所制定的檔案,經過測試,此方法可行。

那麼hostname的更改呢?那就挺方便了,我們只需要將上面的dockerfile build生成一個新的映象,然後在啟動這個映象的時候通過-h 指定hostname就可以了。如下:

sudo docker run -h slave -it --name slave ubuntu /bin/bash