Docker探索系列2之鏡像打包與DockerFile


preface

docker基本入門以后,可以試試打包docker鏡像與dockerfile了

docker鏡像

docker hub倉庫有2類倉庫,用戶倉庫和頂層倉庫,用戶倉庫由docker用戶創建的,頂層倉庫由docker內部的人來管理的。倉庫里存放的是鏡像文件,那么問題來了 ,怎么去創建鏡像呢?

how to create image

構建docker鏡像的有2種方法:

  1. 使用docker commit命令。
  2. 使用docker build 命令和Dockerfile文件。
    在這里並不推薦使用docker commit命令,而應該使用更靈活,更強大的Dockerfile來構建鏡像
    但是還得介紹下如何使用docker commit。。

notice:
you should remeber , we are not create new image from 0。而是基於一個已有的基礎鏡像,如CentOs來構建新鏡像而已。如果真的想從0構建一個全新的鏡像,可以參考: https://docs.docker.com/engine/userguide/eng-image/baseimages/

使用commit來創建一個新的鏡像

我們先啟動一個container,然后安裝個python3。

我們先啟動一個container,然后安裝個python3,
[root@salt docker]# docker run --name python3 -i -t centos /bin/bash
#省去安裝py3步驟。。。。。。
[root@cb6903f738e1 python3.5.2]# exit   #安裝好后退出
[root@salt docker_pratice]# docker commit -m="install python3" --author='Leo'  python3 1403208717:test

參數解釋:

  • -m: 用來指定新創建的鏡像的提交信息
  • --author選項用來列出鏡像的作者信息
  • 標簽: 我們在1403208717追加了一個test,表示冒號后面的是標簽。
查看有剛才commit的信息
[root@salt docker]# docker  images
REPOSITORY              TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
1403208717              latest              001d2ee1399c        12 minutes ago      840.4 MB

導入鏡像

docker通過load放來導入其他的鏡像文件。

[root@linux-node2 ~]# docker load < docker_httpd.iso  # docker_http.iso是一個標准的docker鏡像文件
[root@linux-node2 ~]# docker images   # 導入成功
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
httpd               latest              4f1d18bcf20b        7 weeks ago         531.5 MB

使用dockerfile構建鏡像(基於DSL語法指令創建一個docker鏡像)

我們首先創建一個目錄用來存放dockerfile,這個目錄成為構建環境(base environment),docker稱為這個為上下文或者構建上下文(build context)。docker會在構建鏡像時將構建上下文和該上下文的文件和目錄上傳到Docker守護進程。這樣docker守護進程就能直接訪問你想在鏡像中存儲的任何代碼,文件或者其他數據。
下面看看DockerFIle的樣例:

[root@salt docker_pratice]# mkdir /docker_pratice/
[root@salt ~]# cat /docker_pratice/Dockerfile 
# this is a comment              # 注釋
FROM 1403208717                #從哪個基礎鏡像開始
MAINTAINER Docker Newbee <newbee@docker.com>     #表明作者信息
RUN yum -y update                # 需要運行命令,運行成功后提交該鏡像
RUN yum -y insall httpd           # 需要運行命令,運行成功后提交該鏡像
RUN echo "Hi, i am in your container" >/var/www/html/index.html   #同上
EXPOSE 80

流程講解:
每條指令都會創建一個新的鏡像層並對鏡像進行提交。docker大體上按照如下流程執行DockerFile中的指令。

  • Docker從基礎鏡像運行一個容器。
  • 執行一條指令,對容器修改。
  • 執行類似與docker commit的操作,提交一個新的鏡像層。
  • Docker再基於剛剛提交的鏡像運行一個新的容器。
  • 執行Dockerfile中的下一條指令,直到所有的指令執行完畢。

確認無誤后,我們開始執行dockerfile文件:

 [root@salt docker_pratice]# docker build -t="test/run_httpd" .   --no-cache
  • -t 是指明到哪個repository下的哪個tag
  • . 表示當前目錄下的dockerfile
  • --no-cache: 表示不使用緩存功能,在沒有結束提交之前的鏡像層,都看作緩存層,比如我們yum update后,再次執行dockefile是不會在yum update了,所以使用--no-cache后才會執行yum update。

基於構建緩存的DockerFile模版

構建緩存帶來的好處就是,我們可以實現簡單的Dockerfile模版(比如在Dockerfile文件頂部增加包倉庫或者更新包,從而盡可能確保緩存命中)。我們一般都會在自己的Dockerfile文件頂部使用相同的指令集模版,比如對Ubuntu,可以使用下面的代碼:

FROM ubuntu:14.04,
MAINTAINER James Turnbull "liaojiafa@qq.com"
ENV REFRESHED_AT 2016-12-05
RUN apt-get -qq update

讓我們一步步來分析一下這個新的Dockerfile。首先,我通過FROM指令為新鏡像設置了一個基礎鏡像ubuntu:14.04。接着,我又使用MAINTANINER指令添加了自己的詳細信息聯系信息,之后我又使用了一個名為REFERSHED_AT的環境變量,這個環境變量用來表明該鏡像模版最后的更新時間。最后,我使用run指令來運行apt-get -qq update。

有了這個模版,如果想刷新一個構建,只需要修改ENV指令中的日期。這使DOcker在命令中ENV指令時開始重置這個緩存,並運行后續指令而無需依賴該緩存。也就是說,RUN apt-get update這條指令就會被再次執行,包緩存也會被刷新為最新內容。可以擴展此模版,比如適配到不同的平台或者添加額外的需求。比如像下面的的一樣:

FROM centos
MAINTAINER Leo liaojiafa@exmpale.com
ENV REFRESHED_AT 2016-12-09
RUN yum -y -q update

dockerfile常用命令:

  • workdir: 指令在從鏡像創建一個新容器時,在容器內部設置一個工作目錄,entrypoint 和 cmd指定的程序會在這個目錄下執行。 如 WORKDIR /tmp
  • env : 在鏡像構建過程中設置環境變量 。 ENV TEST /HOME/RMV
  • user: 指定該鏡像用什么用戶身份去運行 。 USER roo
  • volume: 指令用來向基於鏡像創建的容器添加卷。一個卷是可以存在一個或者多個容器內的特訂目錄,這個目錄可以繞過聯合文件系統,並提供以下功能 :
  1. 卷可以在容器間共享和重用。
  2. 一個容器可以不是必須和其他容器共享卷。
  3. 對卷的修改必須是修改不會對更新鏡像產生影響。
  4. 卷會一直存在直到沒有任何容器再使用它。
  • add: 用來構建環境下的文件和目錄復制到鏡像中。如安裝一個應用程序的時候,add指令需要源文件位置和目的文件位置兩個參數。

端口映射

[root@salt var]# docker run -tdi -p 80:80 --name apache_web basic_sys
       -p : hostip :  host_port : docker_container's port
  • -p 從左往右的可以依次寫成宿主機IP,宿主機端口,容器的端口。
    經過上面的配置以后,此時訪問宿主機的80端口就等於訪問容器的80端口。

刪除鏡像:

rmi緊接着后面鏡像ID。

[root@salt var]# docker rmi 1403208717

本地部署repository

服務器端架器repository:
[root@salt ~]#docker run -p 5000:5000 registry
查看本地鏡像信息
[root@salt ~]#docker images test/run_httpd 

給需要上傳的鏡像打上tag

[root@salt nginx]# docker tag 9d16dcc5a7a3  127.0.0.1:5000/test/run_httpd 

上傳:

[root@salt nginx]# docker push 127.0.0.1:5000/test/run_httpd

docker內部容器互聯

首先創建一個redis容器

[root@salt nginx]#docker -ti --name redis xxxx

創建一個web容器,和redis容器互聯。

[root@salt ~]# docker run -ti -p 0.0.0.0:80:80 --name httpweb --link redis:db -v /var/www/html/:/var/www/html/:ro test/run_httpd
[root@d71914aabd87 redis-3.2.3]# redis-cli -h db -p 5555
db:5555> keys *
(empty list or set)

我們可以查看/etc/hosts文件里面,可以看到和子容器對應的信息的。
此時能夠訪問http,也能夠連接redis了。容器與容器,宿主機和容器的/var/www/html也是共享的。

參數解釋:
  • -p 0.0.0.0:80:80 從左往右,表示把宿主機的80端口和 容器的80端口綁定到一塊。
  • --link redis:db 表示連接到容器名為redis的這個容器,db是為這個子容器取個別名。
  • -v /var/www/html/:/var/www/html/:ro 表示把本地宿主機的/var/www/html映射到容器的/var/www/html,ro表示為Only read,也可以為rw權限。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM