1. 程式人生 > >Docker教程:映象構建和自動映象構建dockerfile

Docker教程:映象構建和自動映象構建dockerfile

Docker透過Dockerfile來記錄建立Container映象檔案的每一個步驟,可以將建立應用程式執行環境的過程和配置引數,完整地記錄下來。開發人員和維運人員之間可以利用Dockerfile來溝通對執行環境的討論。甚至結合版本控制服務如GitHub,可以讓Dockerfile具備版本控制功能,能將基礎架構程式化(Infrastructure as code)來管理。

構建自定義的映象

Docker能自動建立映象,構建自定義的映象,有兩種方法:

1、使用docker commit 命令

關於commit命令,其實就是使用docker run -i -t XXX /bin/bash 進入容器的互動介面,進行各種操作後,再將這個容器通過提交命令提交上去來達到目的。

$docker ps -l命令獲得安裝完命令之後容器的id如698***

$docker commit 698 pika/py_ubuntu    #把這個容器儲存為映象py_ubuntu

2、使用Dockerfile

這裡介紹dockerfile方法,因為使用Dockerfile構建擁有比提交命令更高的靈活性和可維護性。

易於自動化的命令:

Dockerfile包含建立映象所需要的全部指令。基於在Dockerfile中的指令,我們可以使用Docker build命令來建立映象。通過減少映象和容器的建立過程來簡化部署。

Dockerfile支援的語法命令如下:INSTRUCTION argument。指令不區分大小寫。但是,命名約定為全部大寫。在文字檔案或Dockerfile檔案中這些命令的順序就是它們被執行的順序。

Dockerfile命令

如果一個映象存在相同的父映象和指令(除了ADD),Docker將會使用映象而不是執行該指令,即快取。為了有效地利用快取,你需要保持你的Dockerfile一致,並且儘量在末尾修改。

使用 # 作為註釋,但是lz試過,註釋很多時候必須單獨成行,否則如果接在目錄後面,會出現No such file or directory報錯。

所有Dockerfile都必須以FROM命令開始。 

FROM命令會指定映象基於哪個基礎映象建立,接下來的命令也會基於這個基礎映象(CentOS和Ubuntu有些命令可是不一樣的)。FROM命令可以多次使用,表示會建立多個映象。

具體語法如下:FROM <image name> 

或者:FROM <image>:<tag>

1. MAINTAINER用來指定維護者的姓名和聯絡方式。MAINTAINER <author name>

更改MAINTAINER指令會使Docker強制執行RUN指令來更新apt,而不是使用快取。

2. RUN:在shell或者exec的環境下執行的命令。RUN指令會在新建立的映象上新增新的層面,接下來提交的結果用在Dockerfile的下一條指令中。每條 RUN 指令將在當前映象基礎上執行指定命令,並提交為新的映象。當命令較長時可以使用 \ 來換行。也就是說RUN命令會在上面FROM指定的映象裡執行任何命令,然後提交(commit)結果,提交的映象會在後面繼續用到。

RUN命令等價於:

docker run image command
docker commit container_id

格式為 RUN <command> 或 RUN ["executable", "param1", "param2"]

前者將在shell終端中執行命令,即 /bin/sh -c ;後者則使用 exec 執行。指定使用其它終端可以通過第二種方式實現,例如 RUN ["/bin/bash", "-c", "echo hello"] 。

3. ADD:複製檔案指令。它有兩個引數<source>和<destination>。

語法如下:ADD 《src》 《destination》

<src> 是相對被構建的源目錄的相對路徑!,可以是檔案或目錄的路徑,也可以是一個遠端的檔案url。<dest> 是container中的絕對路徑

4. CMD:提供了容器預設的執行命令。 Dockerfile只允許使用一次CMD指令。多個只有最後一個指令生效。

支援三種格式
CMD ["executable","param1","param2"] 使用 exec 執行,推薦方式;
CMD command param1 param2 在 /bin/sh 中執行,提供給需要互動的應用;
CMD ["param1","param2"] 提供給 ENTRYPOINT 的預設引數;

5. EXPOSE:指定容器在執行時監聽的埠。

語法如下:EXPOSE <port> [<port>...]

比如memcached使用埠 11211,可以把這個埠暴露在外,這樣容器外可以看到這個埠並與其通訊。

Note: <port>後面不能接空格或者註釋什麼的,否則會報錯:EXPOSE 22 INFO[1063] Invalid containerPort:

Docker的核心概念是可重複和可移植。映象應該可以執行在任何主機上並且執行儘可能多的次數。

在Dockerfile中你有能力對映私有和公有埠,但是你永遠不要通過Dockerfile對映公有埠。通過對映公有埠到主機上,你將只能執行一個容器化應用程式例項。(執行多個埠不就衝突啦)
#private and public mapping
EXPOSE 80:8080
#private only
EXPOSE 80
如果映象的使用者關心容器公有映射了哪個公有埠,他們可以在執行映象時通過-p引數設定,否則,Docker會自動為容器分配埠。
切勿在Dockerfile對映公有埠。

[計算機埠]

6. ENTRYPOINT:配置給容器一個可執行的命令,這意味著在每次使用映象建立容器時一個特定的應用程式可以被設定為預設程式。同時也意味著該映象每次被呼叫時僅能執行指定的應用。類似於CMD,Docker只允許一個ENTRYPOINT,多個ENTRYPOINT會抵消之前所有的指令,只執行最後的ENTRYPOINT指令。

ENTRYPOINT 命令設定在容器啟動時執行命令,也就是配置容器啟動後執行的命令,並且不可被 docker run 提供的引數覆蓋。

# cat Dockerfile
FROM ubuntu
ENTRYPOINT echo "Welcome!"

# docker run 62fda5e450d5
Welcome!
兩種語法格式,一種就是上面的(shell方式):ENTRYPOINT cmd param1 param2 ...
第二種是 exec 格式:ENTRYPOINT ["cmd", "param1", "param2"...]

USER 命令:映象正在執行時設定一個UID。語法如下:USER <uid>
比如指定 memcached 的執行使用者,可以使用上面的 ENTRYPOINT 來實現:ENTRYPOINT ["memcached", "-u", "daemon"]
更好的方式是:
ENTRYPOINT ["memcached"]
USER daemon

ENTRYPOINT echo這個執行時一直呼叫不出bash命令,顯示過後就退出了,不知道為嘛?所以lz在dockerfile中註釋了這一句。

7. WORKDIR:指定RUNCMDENTRYPOINT命令的工作目錄。語法如下:WORKDIR /path/to/workdir

8. ENV:設定環境變數。它們使用鍵值對,增加執行程式的靈活性。

語法如下:ENV <key> <value>

設定了後,後續的RUN命令都可以使用
使用此dockerfile生成的image新建container,可以通過 docker inspect 看到這個環境變數:
[email protected]:~# docker inspect 49bfc7a9817f
也可以通過在docker run時設定或修改環境變數:
docker run -i -t --env name="pi" ubuntu:newtest /bin/bash

9. VOLUME:授權訪問從容器內到主機上的目錄。用於containers之間共享資料

語法如下:VOLUME ["/data"]

Dockerfile示例

/media/pi/files/mine/python_workspace/DockerEnv/dockerfile

#python3 development environment
FROM ubuntu:14.04
MAINTAINER pi "[email protected]"
#ENTRYPOINT echo "python3 development environment\n"


# 更新源,原生ubuntu映象中的下載源速度太慢,然而下面這個源並不是最新的,居然沒有python3-pip!!!
#RUN echo "deb http://mirrors.163.com/ubuntu precise main universe" > /etc/apt/sources.list
#RUN echo "deb http://mirrors.163.com/ubuntu/ precise main restricted universe multiverse" > /etc/apt/sources.list
RUN apt-get update


#安裝ssh server進行遠端操控
RUN apt-get install -y openssh-server
RUN mkdir /var/run/sshd
# 設定root ssh遠端登入密碼
RUN echo "root:249784435" | chpasswd
# 容器需要開放SSH 22埠,以使外部能夠訪問容器內部
EXPOSE 22


#常用安裝
#軟體衝突,要先將vim-common解除安裝,再裝vim
RUN apt-get remove -y vim-common
RUN apt-get install -y vim
RUN apt-get install -y git
RUN apt-get install -y wget


#安裝python3開發環境
RUN apt-get install -y python3
RUN apt-get install -y python3-pip
RUN ln -sf /usr/bin/python3.4 /usr/bin/python
RUN ln -sf /usr/bin/pip3 /usr/bin/pip


#apt-get安裝python3拓展包(有的包pip安裝會出錯)
RUN apt-get install -y python3-numpy
RUN apt-get install -y python3-scipy
#extra packages installed : python3-six ... + python3-numpy
RUN apt-get install -y python3-matplotlib
#extra packages installed : python3-dateutil python3-nose  python3-pil python3-pyparsing python3-tk python3-pytz  python3-tornado ... + python3-numpy
RUN apt-get install -y python3-pandas
RUN apt-get install -y mysql-server mysql-client


#pip安裝python3拓展包(有的只能pip安裝)
ADD requirements.txt /tmp/requirements.txt
RUN pip3 install -r /tmp/requirements.txt

構建自定義ubuntu映象

使用Dockerfile構建映象命令

docker build [options] PATH | URL
額外選項,如:
--rm=true表示構建成功後,移除所有中間容器
--no-cache=false表示在構建過程中不使用快取

-t   給該映象賦予一個tag,用以將來的呼叫與搜尋 

.   表示呼叫當前目錄的Dockerfile

$cd /media/pi/files/mine/python_workspace/DockerEnv

$docker build -t py-ubuntu .


之後可以通過用"docker images"命令檢視映象

最佳實踐:注意事項

當構建映象時使用可理解的標籤,以便更好地管理映象;
避免在Dockerfile中對映公有埠;
CMD與ENTRYPOINT命令請使用陣列語法。

在使用apt-get安裝軟體時,需要加上"-y"的引數,如果不指定-y引數的話,apt-get命令會進入互動模式,需要使用者輸入命令來進行確認,但在docker環境中是無法響應這種互動的。所以就會造成安裝中斷這種問題。

如果安裝了ssh,chpasswd方法給ssh新增root使用者登入密碼為123456。"chpasswd"可以批量的為ssh新增以"username:passwd"為格式的使用者與密碼。可以將username:passwd批量的寫在一個txt檔案中,然後使用xxx.txt chpasswd方法為ssh批量新增使用者。