在前面咱們講解了基於已有的鏡像容器建立和基於本地模板導入兩種方式來建立鏡像,在這裏咱們就來講說第三種建立鏡像的方式。Dockerfile是一個文本格式的配置文件,咱們能夠經過Dockerfile快速建立自定義的鏡像。html
Dockerfile是由多行命令語句組成的,而且在文件中支持以 # 開始的註釋行。咱們通常將Dockerfile文件分爲四部分:基礎鏡像信息、維護者信息、鏡像操做指令和容器啓動時執行指令。其中,第一行(不包含註釋行)必須指定基於的基礎鏡像,例如:FROM ubuntu。以後能夠是維護者信息,如:MAINTAINER gongziqi 14155830994@qq.com。再日後能夠是鏡像的操做指令,如:python
RUN echo "deb archive.ubuntu.com/ubuntu/ raring main universe" >> /etc/apt/sources.listnginx
RUN apt-get update && apt-get install -y nginxdocker
RUN echo "\ndaemon off;" >> /etc/nginx/nginx.confshell
最後能夠是容器啓動時執行指令,如:CMD /usr/sbin/nginx。數據庫
# 0. 在ubuntu鏡像的基礎上,安裝inotify-tools/nginx/apache2/openssh-server等,建立新的Nginx鏡像
# Nginx
# VERSION 1.0
FROM ubuntu
MAINTAINER gongziqi 1415583094@qq.com
RUN apt-get update && apt-get install -y inotify-tools nginx apache2 openssh-server
# 1. 在ubuntu鏡像基礎上,安裝firefox/vnc。啓動後,用戶可經過5900端口經過vnc方式使用firefox
# FireFox over VNC
# VERSION 1.0
FROM ubuntu
RUN apt-get update && apt-get install -y x11vnc xvfb firefox
RUN mkdir ./.vnc
RUN x11vnc -storepasswd 123456 ~/.vnc/passwd
RUN bash -c 'echo "firefox" >> /.bashrc'
EXPOSE 5900
CMD ["x11vnc","-forever","usepw","-create"]
複製代碼
語法爲:FROM 或 FROM
:。若在同一個Dockerfile中建立多個鏡像,可使用多個FROM即每一個鏡像一個。apache
語法:MAINTAINER ,用來指定維護者信息。ubuntu
語法:RUN 或 RUN ["executable","param1","param2"]。第一個將在shell終端中運行命令,即 /bin/bash -c;第二個則使用 exec 執行。每條RUN指令將在當前鏡像基礎上執行指定指令,並提交爲新的鏡像。若命令行太長可使用 \ 來換行書寫。vim
支持三種方式:ruby
CMD ["executable", "param1", "param2"],使用 exec執行,推薦方式。
CMD command param1 param2,在 /bin/sh 中執行,提供給須要交互的應用。
CMD ["param1","param2"],提供給 ENTRYPOINT的默認參數。
指定啓動容器時執行的命令,每一個Dockerfile只能由一條 CMD命令。若指定多條,則只有最後一條有效。若在啓動容器時,指定了運行的命令,則CMD命令將會被覆蓋。
語法:EXPOSE [ ...],如:EXPOSE 22 80 8443,即告訴Docker服務器容器暴露的端口,這些端口可供互聯使用。此時在容器啓動中,可以使用 -P 來隨機指定一個端口,也可以使用 -p 來指定具體的端口映射。
語法:ENV 。指定一個環境變量,會被後面的RUN指令使用,並在容器運行時保持。如:
ENV PG_MAJOR 9.3
ENV PG_VERSION 9.3.4
RUN curl -SL http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC /usr/src/postgress && ...
ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH
複製代碼
語法:ADD 。將複製指定的src到容器中的desc。其中,src 能夠是Dockerfile所在目錄的一個相對路徑(文件/目錄);也可爲一個URL;還可爲一個tar文件。
語法:COPY
語法:ENTRYPOINT ["executable","param1","param2"] 或 ENTRYPOINT command param1 param2(shell中執行)。配置容器啓動後執行的命令,而且不可被docker run 提供的參數覆蓋。每一個Dockerfile只能有一個ENTRYPOINT,當指定多個時,只有最後一個有效。
語法:VOLUME ["/data"]。建立一個能夠從本地主機或其餘容器掛載的掛載點,通常用來存放數據庫和須要保持的數據等。
語法:USER daemon。指定運行容器時的用戶名或UID,後續的RUN指令也會使用指定用戶。當服務不須要管理員權限時,可經過該命令指定運行用戶,而且能夠在以前建立所須要的用戶。如:RUN groupadd -r postgres && useradd -r -g postgres postgres。若此時須要臨時獲取管理員權限,則可以使用gosu,不推薦使用sudo。
語法:WORKDIR /path/to/workdir。爲後續的 RUN、CMD、ENTRYPOINT指令配置工做目錄。可以使用多個WORKDIR,若後面的WORKDIR指定的是相對路徑,則是基於前一個WORKDIR指定的路徑。如:
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
# 結果爲:/a/b/c
複製代碼
語法:ONBUILD [INSTRUCTION]。配置當所建立的鏡像做爲其餘新建立鏡像的基礎鏡像時,所執行的操做指令。如:Dockerfile使用以下的內容建立了鏡像 image-A。
[...]
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
[...]
複製代碼
若基於image-A建立新的鏡像時,新的Dockerfile中使用 FROM image-A指定基礎鏡像時,會自動執行 ONBUILD 指令內容,即等價於在 FROM指令後添加了以上的兩條指令。在使用ONBUILD指令的鏡像,咱們推薦在標籤中註明,如:ruby:1.9-onbuild。
在編寫完Dockerfile以後,能夠經過 Docker build 命令來建立鏡像。語法爲:docker build [選項] 路徑,即讀取指定路徑下的Dockerfile,並將該路徑下全部內容發送給Docker服務端,由服務端來建立鏡像。所以咱們建議放置Dockerfile的目錄爲空目錄。若爲非空目錄,但願忽略路徑下的某些目錄或文件,可經過 .dockerignore文件來配置。
# 指定Dockerfile路徑所在路徑爲 /tmp/docker_builder/,但願生成鏡像標籤爲 build_repo/first_image, # 在標籤命名時須要注意,全部字母必須爲小寫
$ sudo docker build -t build_repo/first_image /tmp/docker_builder/
複製代碼
根據以上信息,咱們來本身建立一個Nginx鏡像。
# 0. 建立Dockerfile所在目錄
$ sudo mkdir /opt/tmp_dockerbuilder
# 1. 建立Dockerfile文件並編寫內容
$ sudo vim Dockerfile
# Nginx
# VERSION 1.0
FROM ubuntu
MAINTAINER gongziqi 1415583094@qq.com
RUN apt-get update && apt-get install -y inotify-tools nginx apache2 openssh-server
# 2. 查看當前本地鏡像
$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
# 3. build Dockerfile文件,建立鏡像
$ sudo docker build -t nginx/mynginx /opt/tmp_dockerbuilder/Dockerfile
Sending build context to Docker daemon 2.048kB
Step 1/3 : FROM ubuntu
---> 4e5021d210f6
Step 2/3 : MAINTAINER gongziqi 1415583094@qq.com
---> Running in 8dc5269da475
Removing intermediate container 8dc5269da475
---> e27af3f3a447
Step 3/3 : RUN apt-get update && apt-get install -y inotify-tools nginx apache2 openssh-server
---> Running in 2ec0f5b9fc81
........
........
........
Successfully built d27de6c7896d
Successfully tagged nginx/mynginx:latest
# 4. 再次查看本地鏡像
$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx/mynginx latest d27de6c7896d 6 minutes ago 275MB
# 5. 以當前建立的鏡像運行容器
$ sudo docker run -ti d27de6c7896d /bin/bash
root@a505965d1b84:/#
# 6. 查看當前的容器中是否有咱們剛纔須要安裝的相關軟件
root@a505965d1b84:/# find / -name apache2
/etc/cron.daily/apache2
/etc/init.d/apache2
/etc/logrotate.d/apache2
/etc/apache2
/etc/ufw/applications.d/apache2
find: '/proc/1/map_files': Operation not permitted
find: '/proc/12/map_files': Operation not permitted
/usr/lib/apache2
/usr/sbin/apache2
/usr/share/bug/apache2
/usr/share/doc/apache2
/usr/share/lintian/overrides/apache2
/usr/share/apache2
/var/cache/apache2
/var/lib/apache2
/var/log/apache2
# 7. 查看ubuntu鏡像運行的容器中是否有apache2
$ sudo docker run -tid ubuntu /bin/bash
$ sudo docker exec -ti 6df8ff14f57f /bin/bash
root@6df8ff14f57f:/# find / -name apache2
find: '/proc/1/map_files': Operation not permitted
find: '/proc/10/map_files': Operation not permitted
find: '/proc/19/map_files': Operation not permitted
root@6df8ff14f57f:/#
# 說明:咱們會發現剛纔的配置的 apache2 軟件已被安裝,而基於的 ubuntu鏡像自己是沒有apache2的
複製代碼