前面的章節學習之后(系列學習傳送門:Docker 系列學習 - Circle_Wang - 博客園),其實我們基本可以正常使用他人已經編寫好的docker鏡像來進行容器步署操作或者更改了鏡像了。這一章節我們將來學習如何通過DockerFile自行構建一個docker鏡像(換句話說就是如何自己構建出一個容器模板)。當我們寫好了一個DockerFile之后,可以使用以下命令來創建出按照DockerFile生成的一個鏡像。
docker build -f Dockerfile的文件路徑 -t 鏡像名:TAG(TAG可以省略) .
通過這個命令,docker就會根據指定的dockerfile開始生成一個指定鏡像名:TAG的鏡像(如果TAG被省略會默認生成latest),這里一定要注意最后有一個".",這個"."表示當前目錄下
1、DockerFile文件命令
首先我們需要來熟悉一下編寫一個基本的DockerFile文件需要遵守的規則,全部命令參見參考網頁1。
下面,我們將采用FROM,MAINTAINER,CMD,WORKDIR,RUN這幾個命令來簡單熟悉下怎么創建一個鏡像。我的dockerfile文件如下:
# 從哪個基礎鏡像啟動 FROM ubuntu # 設置該鏡像編寫者信息 MAINTAINER CircleWang # 設定從該鏡像啟動容器時默認進入的路徑 WORKDIR /home # 在構建鏡像時執行兩個命令 RUN apt-get update RUN apt-get install vim -y # 在啟動容器時容器執行的命令 CMD echo '---我被執行了---'
文件中已經有了基本的注釋了,總結一下這整個dockerfile文件干了一個什么事情呢?第一行首先獲取了一個基礎鏡像叫ubuntu,並且備注了一下編寫這個鏡像的作者(第二行命令),第三行命令是指當生成容器的時候(進入容器的時候)默認是在/home目錄下的(大家可以回憶一下之前我們進入官方的ubuntu鏡像制造的容器時都是在根目錄下的吧)。接下來的兩行命令(RUN),就是指在生成鏡像時會執行apt-get update以及apt-get install vim -y兩個命令,這兩個命令其實就是在安裝下載VIM(回憶咱們的這篇文章中:Docker系列學習(二)——查看,啟動,退出,保存鏡像的方法的第8點,官方的ubuntu鏡像是沒有安裝vim的),以后只要是從我這個鏡像(dockerfile文件創建的鏡像)生成的容器,那么就是自帶有vim的了。最后一行命令(CMD)其實是指當從鏡像生成容器的時候,容器中會執行這個命令(這個命令的意思是打印一句話”---我被執行了---“)。
這里要注意RUN和CMD這兩個命令雖然都是執行,但是意義不同。RUN是指在構建鏡像的時候(可以認為是定義類)會在這個類中執行(這里就是安裝vim),但是在構建類的時候是不執行CMD的,換句話說當你在docker build的時候是不會打印”---我被執行了---“這句話的,只要當你從這個鏡像中生成容器時,在容器內部會執行CMD命令。
下面我們來看看你生成鏡像,以及從這個鏡像生成類的情況。
docker build -f my_dockerfile01 -t my_ubuntu .
可以看到我已經生成了一個名叫my_ubuntu的鏡像TAG為latset。下面我們再根據這個鏡像(my_ubuntu)啟動一個容器看看。
docker run -it my_ubuntu
已經打印除了我們CMD的信息了。這里有個問題出現了,為什么我是用的時-it(交互運行容器)為什么沒有進入到容器內呢?我們使用docker ps -a卻是可以看到一個停止的容器的,為什么容器會直接停止呢。回憶一下我們之前啟動官方的ubuntu系統時,啟動完成了就會直接進入到容器內部的啊。並且還有一個非常奇怪的現象是我是用docker ps -a可以看到這個容器的id但是無法使用docker start 容器id的方式啟動這個容器(其實查看細節應該是啟動了又馬上關閉了)。這個問題我查看了很多地方都沒有說得很清楚的解釋以后再補充吧,直接說解決方法。
方法一:直接在從鏡像中啟動容器時采用docker run -it my_ubuntu /bin/bash命令,最后添加的/bin/bsah指啟動一個命令窗口,並以交互的形式,這樣就可以直接進入容器了,並且關閉容器之后還能再次啟動容器。
方法二:在dockerfile文件中最后一個命令CMD,更改為
CMD echo '---我被執行了---' && /bin/bash
這個意思就是不僅要打印”---我被執行了---“,還要進入/bin/bash,此時在使用docker run -it my_ubuntu命令進入就沒有問題了。(注意更改了Dockerfile文件要重新build鏡像喲)
2、CMD和ENTRYPOINT的區別
前一節我們已經講過了CMD的用法,也就是在從鏡像生成容器時,在容器內部會執行的命令。但是這里要注意到CMD在dockerfile中只有最后一個會被執行,如果你的dockerfile中有多個CMD命令,只有最后一個CMD命令會被執行(這也就是前一節我是使用&&符號來鏈接命令而不使用兩個CMD命令)。並且如果在使用docker run -it my_ubuntu 命令來啟動容器的時候,此時后面如果加了/bin/bush(這種類似的命令行命令)此時就會忽略掉鏡像中的CMD命令。(換句話說,如果采用docker run -it my_ubuntu /bin/bash啟動容器,那么將不會打印出”---我被執行了---“這句話的)
ENTRYPOINT的使用跟CMD一樣,雖然依然是只有最后一個ENTRYPOINT才會被容器內命令行執行,但是卻可以在末尾增加命令,也會在啟動容器的時候執行的。