根據Dockerfile構建鏡像

根據Dockerfile構建出一個鏡像
Dockfile是一種被Docker程序解釋的腳本,Dockerfile由一條一條的指令組成,每條
指令對應Linux下面的一條命令。Docker程序將這些Dockerfile指令翻譯真正的Linux命
令。Dockerfile有本身書寫格式和支持的命令,Docker程序解決這些命令間的依賴關係,
相似於Makefile。Docker程序將讀取Dockerfile,根據指令生成定製的image。相比
image這種黑盒子,Dockerfile這種顯而易見的腳本更容易被使用者接受,它明確的代表
image是怎麼產生的。有了Dockerfile,當咱們須要定製本身額外的需求時,只需在
Dockerfile上添加或者修改指令,從新生成image便可,省去了敲命令的麻煩。
Dockerfile由一行行命令語句組成,而且支持以# 開頭的註釋行。
Dockerfile的指令是忽略大小寫的,建議使用大寫,每一行只支持一條指令,每條指令
能夠攜帶多個參數。
Dockerfile的指令根據做用能夠分爲兩種:構建指令和設置指令。
構建指令用於構建image,其指定的操做不會在運行image的容器上執行;
設置指令用於設置image的屬性,其指定的操做將在運行image的容器中執行。
通常的,Dockerfile分爲四部分:基礎鏡像信息、維護者信息、鏡像操做指令和容器啓動時
執行指令。
下面是一個例子:
#This dockerfile uses the ubuntu image
#VERSION 2 - EDITION 1
#Author: docker_user
#Command format: Instruction [arguments / command] ..
#Base image to use, this must be set as the first line
#第一行必須指明基於的基礎鏡像
FROM ubuntu
#Maintainer: docker_user<docker_user at email.com> (@docker_user)
#維護該鏡像的用戶信息
MAINTAINER docker_user docker_user@email.com
#Commands to update the image
#鏡像操做命令
RUN echo "deb http://archive.ubuntu.com/ubuntu/ raring main universe" >>
/etc/apt/sources.list
RUN apt-get update && apt-get install -y nginx
RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf
#開啓80端口
EXPOSE 80
#Commands when creating a new container
#啓動容器時執行的命令
CMD /usr/sbin/nginx
在編寫dockerfile時,有嚴格的格式要遵循:
其中,一開始必須使用FROM指令指明所基於的鏡像名稱,接下來使用MAINTAINER指
令說明維護者信息。後面則是鏡像操做指令,例如RUN指令,RUN 指令將對鏡像執行跟隨
的命令。每運行一條RUN 指令,都會給基礎鏡像添加新的一層並提交。最後是CMD指令,
來指定運行容器時的操做命令。
dockerfile指令
指令的通常格式爲INSTRUCTION arguments,指令包括FROM 、MAINTAINER 、RUN
等。
(1)FROM(指定基礎image)
構建指令,必須指定且須要在Dockerfile其餘指令的前面。後續的指令都依賴於該指令指定
的image。FROM指令指定的基礎image能夠是官方遠程倉庫中的,也能夠位於本地倉庫。
該指令有兩種格式:
FROM <image>
指定基礎image爲該image的最後修改的版本。
或者:
FROM <image>:<tag>
指定基礎image爲該image的一個tag版本。
(2)MAINTAINER(用來指定鏡像建立者信息)
構建指令,用於將image的製做者相關的信息寫入到image中。當咱們對該image執行
docker inspect命令時,輸出中有相應的字段記錄該信息。
格式:
MAINTAINER <name>
(3)RUN(安裝軟件用)
構建指令,RUN能夠運行任何被基礎image支持的命令。如基礎image選擇了ubuntu,那
麼軟件管理部分只能使用ubuntu的命令。
該指令有兩種格式:
RUN <command> (the command is run in a shell - /bin/sh -c)
RUN ["executable", "param1", "param2" ... ] (exec form)
前者將在 shell 終端中運行命令,即/bin/sh -c ;後者則使用exec 執行。
指定使用其它終端能夠經過第二種方式實現,例如 RUN ["/bin/bash", "-c", "echo hello"]

每條RUN指令將在當前鏡像基礎上執行指定命令,並提交爲新的鏡像。當命令較長時能夠
使用「\」來換行。
(4)CMD(設置container啓動時執行的操做)
該指令有三種格式:
設置指令,用於container啓動時指定的操做。該操做能夠是執行自定義腳本,也能夠是執
行系統命令。
CMD ["executable","param1","param2"] 使用exec 執行,推薦方式;
CMD command param1 param2 在/bin/sh中執行,提供給須要交互的應用;
當Dockerfile指定了ENTRYPOINT,那麼使用下面的格式:
CMD ["param1","param2"] 提供給ENTRYPOINT 的默認參數;
ENTRYPOINT指定的是一個可執行的腳本或者程序的路徑,該指定的腳本或者程序將會
param1和param2做爲參數執行。因此若是CMD指令使用上面的形式,那麼Dockerfile中
必需要有配套的ENTRYPOINT。
指定啓動容器時執行的命令,每一個Dockerfile只能有一條CMD 命令。若是指定了多條命
令,只有最後一條會被執行。若是用戶啓動容器時候指定了運行的命令,則會覆蓋掉CMD
指定的命令。
5)ENTRYPOINT(設置container啓動時執行的操做)
設置指令,指定容器啓動時執行的命令,能夠屢次設置,可是隻有最後一個有效。
兩種格式:
ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2 (shell中執行)。
配置容器啓動後執行的命令,而且不可被docker run提供的參數覆蓋。
每一個Dockerfile 中只能有一個ENTRYPOINT,當指定多個時,只有最後一個起效。
該指令的使用分爲兩種狀況,一種是獨自使用,另外一種和CMD指令配合使用。
當獨自使用時,若是你還使用了CMD命令且CMD是一個完整的可執行的命令,那麼CMD
指令和ENTRYPOINT會互相覆蓋只有最後一個CMD或者ENTRYPOINT有效。
例如: CMD指令將不會被執行,只有ENTRYPOINT指令被執行
CMD echo 「Hello, World!」
ENTRYPOINT ls -l
另外一種用法和CMD指令配合使用來指定ENTRYPOINT的默認參數,這時CMD指令不是一
個完整的可執行命令,僅僅是參數部分;ENTRYPOINT指令只能使用JSON方式指定執行命
令,而不能指定參數。
例如:
FROM ubuntu
CMD ["-l"]
ENTRYPOINT ["/usr/bin/ls"]
(6)USER(設置container容器的用戶,默認是root用戶)
格式爲:
USER daemon
指定運行容器時的用戶名或UID,後續的RUN 也會使用指定用戶。
當服務不須要管理員權限時,能夠經過該命令指定運行用戶。而且能夠在以前建立所須要的
用戶,例
如: RUN groupadd -r postgres&&useradd -r -g postgres postgres
例如: 指定memcached的運行用戶
ENTRYPOINT ["memcached"]
USER daemon
或 EN
TRYPOINT ["memcached", "-u", "daemon"]
(7)EXPOSE(指定容器須要映射到宿主機器的端口)
格式爲:
EXPOSE <port> [<port>...]
設置指令,該指令會將容器中的端口映射成宿主機器中的某個端口。當你須要訪問容器的時
候,能夠不是用容器的IP地址而是使用宿主機器的IP地址和映射後的端口。
要完成整個操做須要兩個步驟,首先在Dockerfile使用EXPOSE設置須要映射的容器端口,
而後在運行容器的時候指定-p選項加上EXPOSE設置的端口,這樣EXPOSE設置的端口號會
被隨機映射成宿主機器中的一個端口號。也能夠指定須要映射到宿主機器的哪一個端口,這時
要確保宿主機器上的端口號沒有被使用。EXPOSE指令能夠一次設置多個端口號,相應的運
行容器的時候,能夠配套的屢次使用-p選項。
例如: 映射一個端口
EXPOSE port1
#相應的運行容器使用的命令
docker run -p port1 image
例如: 映射多個端口
EXPOSE port1 port2 port3
#相應的運行容器使用的命令
docker run -p port1 -p port2 -p port3 image
#根據Dockerfile構建鏡像還能夠指定須要映射到宿主機器上的某個端口號
docker run -p host_port1:port1 -p host_port2:port2 -p host_port3:port3 image
端口映射是docker比較重要的一個功能,緣由在於咱們每次運行容器的時候容器的IP地址
不能指定而是在橋接網卡的地址範圍內隨機生成的。宿主機器的IP地址是固定的,咱們能夠
將容器的端口的映射到宿主機器上的一個端口,免去每次訪問容器中的某個服務時都要查看
容器的IP的地址。對於一個運行的容器,可使用docker port加上容器中須要映射的端口
和容器的ID來查看該端口號在宿主機器上的映射端口。
(8)ENV(用於設置環境變量)
構建指令,指定一個環境變量,會被後續RUN指令使用,並在容器運行時保持。
格式:
ENV <key> <value>
設置了後,後續的RUN命令均可以使用,container啓動後,能夠經過docker inspect查看
這個環境變量,也能夠經過在docker run --env key=value時設置或修改環境變量。
假如你安裝了JAVA程序,須要設置JAVA_HOME,那麼能夠在Dockerfile中這樣寫:
ENV JAVA_HOME /path/to/java/dirent
再例如:
ENV PG_MAJOR 9.3
ENV PG_VERSION 9.3.4
RUN curl http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC
/usr/src/postgress
ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH
(9)ADD(將源文件複製到container的目標文件)
構建指令,全部拷貝到container中的文件和文件夾權限爲0755,uid和gid爲0;
源文件要與Dockerfile位於相同目錄中;
一、若是源路徑是個文件,且目標路徑是以 / 結尾, 則docker會把目標路徑看成一個目
錄,會把源文件拷貝到該目錄下。若是目標路徑不存在,則會自動建立目標路徑。
二、若是源路徑是個文件,且目標路徑是否是以 / 結尾,則docker會把目標路徑看成一個文
件。
若是目標路徑不存在,會以目標路徑爲名建立一個文件,內容同源文件;
若是目標文件是個存在的文件,會用源文件覆蓋它,固然只是內容覆蓋,文件名仍是目標文
件名。
若是目標文件實際是個存在的目錄,則會源文件拷貝到該目錄下。 注意,這種狀況下,最
好顯示的以 / 結尾,以免混淆。
三、若是源路徑是個目錄,且目標路徑不存在,則docker會自動以目標路徑建立一個目錄,
把源路徑目錄下的文件拷貝進來。若是目標路徑是個已經存在的目錄,則docker會把源路
徑目錄下的文件拷貝到該目錄下。
四、若是源文件是個歸檔文件(壓縮文件),則docker會自動幫解壓。
格式:
ADD <src> <dest>
該命令將複製指定的<src>到容器中的<dest>。
其中<src>能夠是Dockerfile所在目錄的一個相對路徑;也能夠是一個 URL;還能夠是一個
tar 文件(自動解壓爲目錄)
<dest>是container中的絕對路徑
例如:
#test
FROM ubuntu
MAINTAINER hello
ADD test1.txt test1.txt
ADD test1.txt test1.txt.bak
ADD test1.txt /mydir/
ADD data1 data1
ADD data2 data2
ADD zip.tar /myzip
(10)COPY
格式爲 COPY <src><dest>
複製本地主機的<src>(爲Dockerfile所在目錄的相對路徑)到容器中的<dest>。
源文件/目錄要與Dockerfile在相同的目錄中
COPY指令和ADD指令功能和使用方式相似。只是COPY指令不會作自動解壓工做。
(11)VOLUME(指定掛載點)
設置指令,使容器中的一個目錄具備持久化存儲數據的功能,該目錄能夠被容器自己使用,
也能夠共享給其餘容器使用。咱們知道容器使用的是AUFS,這種文件系統不能持久化數
據,當容器關閉後,全部的更改都會丟失。當容器中的應用有持久化數據的需求時能夠在
Dockerfile中使用該指令。
格式:
VOLUME ["<mountpoint>"]
例如:FROM base
VOLUME ["/tmp/data"]
運行經過該Dockerfile生成image的容器,/tmp/data目錄中的數據在容器關閉後,裏面的
數據還存在。例如另外一個容器也有持久化數據的需求,且想使用上面容器共享的/tmp/data
目錄,那麼能夠運行下面的命令啓動一個容器:
docker run -t -i -rm -volumes-from container1 image2 bash
container1爲第一個容器的ID,image2爲第二個容器運行image的名字。
(12)WORKDIR(切換目錄)
設置指令,能夠屢次切換(至關於cd命令),對RUN,CMD,ENTRYPOINT生效。爲後續的
RUN、CMD、ENTRYPOINT 指令配置工做目錄。
格式:
WORKDIR /path/to/workdir
例如: 在 /p1/p2 下執行 vim a.txt
WORKDIR /p1
WORKDIR p2
RUN vim a.txt
可使用多個WORKDIR指令,後續命令若是參數是相對路徑,則會基於以前命令指定的路
徑。
例如
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
則最終路徑爲/a/b/c。
(13)ONBUILD(在子鏡像中執行)
ONBUILD <Dockerfile關鍵字>
ONBUILD 指定的命令在構建鏡像時並不執行,而是在它的子鏡像中執行。
格式爲:
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 image-A
#Automatically run the following
ADD . /app/src
RUN /usr/local/bin/python-build --dir /app/src
使用ONBUILD指令的鏡像,推薦在標籤中註明,例如ruby:1.9-onbuild。
編寫完成Dockerfile以後,能夠經過docker build 命令來建立鏡像。
基本的格式爲docker build [選項] 路徑,該命令將讀取指定路徑下的Dockerfile,並將該
路徑下全部內容發送給Docker 服務端,由服務端來建立鏡像。所以通常建議放置
Dockerfile的目錄爲空目錄。
要指定鏡像的標籤信息,能夠經過-t選項,例如
$ sudo docker build –t myrepo /myapp/tmp/test1/
docker應用案例:使用dockerfile建立sshd鏡像模板並提供http訪問應用
1) 建立一個sshd_dockerfile工做目錄
根據Dockerfile構建鏡像
編輯run.sh腳本
[root@docker01 sshd_dockerfile]# cat run.sh
#!/bin/sh
/usr/sbin/httpd -D DFOREGROUND
/usr/sbin/sshd -D
在主機上生成ssh祕鑰對,並建立authorized_keys文件
根據Dockerfile構建鏡像
[root@docker01 sshd_dockerfile]# cat /root/.ssh/id_rsa.pub >
/root/sshd_dockerfile/authorized_keys
[root@docker01 sshd_dockerfile]# ls
authorized_keys Dockerfile run.sh
二、編寫Dockerfile文件,內容以下:
[root@docker01 sshd_dockerfile]# cat /root/sshd_dockerfile/Dockerfile
FROM centos:latest
MAINTAINER from ly@aliyun.com
RUN yum install -y -q httpd openssh-server sudo net-tools
RUN useradd admin
RUN echo "admin:admin" | chpasswd
RUN echo "admin ALL=(ALL) ALL" >> /etc/sudoers
RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
RUN ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key
RUN ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key
RUN mkdir -p /var/run/sshd
RUN mkdir -p /home/admin/.ssh
RUN sed -ri 's/#ServerName www.example.com:80/ServerName www.cloud.com/g'
/etc/httpd/conf/httpd.conf
ADD authorized_keys /home/admin/.ssh/authorized_keys
ADD run.sh /run.sh
RUN chmod 775 /run.sh
EXPOSE 22 80
CMD ["/run.sh"]
以上選項的含義解釋:
FROM centos:latest 選擇一個已有的os鏡像做爲基礎
MAINTAINER 鏡像的做者
RUN yum install -y -q httpd openssh-server sudo 安裝httpd、openssh-server、java

sudo和net-tools軟件包
添加測試用戶admin,密碼admin,而且將此用戶添加到sudoers裏
RUN useradd admin
RUN echo "admin:admin" | chpasswd
RUN echo "admin ALL=(ALL) ALL" >> /etc/sudoers
下面這兩句比較特殊,在centos6上必需要有,不然建立出來的容器sshd不能登陸
RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
注意:centos7上下面4句必需要有,不然建立出來的容器sshd不能登陸
RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
RUN ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key
RUN ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key
將公鑰信息上傳到遠程鏈接用戶的宿主目錄的.ssh下
ADD authorized_keys /home/admin/.ssh/authorized_keys
啓動sshd服務而且暴露22端口
RUN mkdir /var/run/sshd
EXPOSE 22 80
CMD ["/run.sh"] 運行腳本, 也能夠寫成這種方式CMD ["/usr/sbin/sshd", "-D"]
三、在sshd_dockerfile目錄下,使用docker build命令來建立鏡像,注意:在最後還有一
個」.」,表示使用當前目錄中的dockerfile
[root@docker01 sshd_dockerfile]# docker build --no-cache -t "centos:httpv1" .
Sending build context to Docker daemon 4.608kB
Step 1/18 : FROM centos:latest
---> 3fa822599e10
Step 2/18 : MAINTAINER from ly@aliyun.com
---> 0d8eeedbef89
Removing intermediate container 661854eafd44
Step 14/18 : ADD authorized_keys /home/admin/.ssh/authorized_keys
....................
四、能夠查看到生成的鏡像文件:
根據Dockerfile構建鏡像
啓動容器,並作映射端口
根據Dockerfile構建鏡像
使用admin用戶登陸
根據Dockerfile構建鏡像
訪問容器的網站服務:
根據Dockerfile構建鏡像python

相關文章
相關標籤/搜索