一、 根據 Dockerfile 構建出一個容器
1、FROM(指定基礎 image)
該指令有兩種格式:
FROM <image> 制定images號也可以
指定基礎 image 爲該 image 的最後修改的版本。
或者:
FROM <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)
舉例:RUN ["touch","a.txt"]
前者將在 shell 終端中運行命令,即 /bin/sh -c ;後者則使用 exec 執行。指定使用其它終端可以通過第二種方式實現,例如 RUN ["/bin/bash", "-c", "echo hello"] 。每條 RUN 指令將在當前鏡像基礎上執行指定命令,並提交爲新的鏡像。當命令較長時可以使用 \ 來換行
4、CMD(設置 container 啓動時執行的操作)
該指令有三種格式:
設置指令,用於 container 啓動時指定的操作。該操作可以是執行自定義腳本,也可以是執行系統命令。
CMD ["executable","param1","param2"] 使用 exec 執行,推薦方式;
當 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 postgrespostgres
*指定 memcached 的運行用戶
ENTRYPOINT ["memcached"]
USER daemon
或
ENTRYPOINT ["memcached", "-u", "daemon"]
7、EXPOSE(指定容器需要映射到宿主機器的端口)
格式爲 EXPOSE <port> [<port>...]
EXPOSE 22 80
設置指令,該指令會將容器中的端口映射成宿主機器中的某個端口。當你需要訪問容器的時候,可以不是用容器的 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
還可以指定需要映射到宿主機器上的某個端口號
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(從 src 複製文件到 container 的 dest 路徑)
構建指令,所有拷貝到 container 中的文件和文件夾權限爲 0755, uid 和 gid 爲 0;
如果是一個目錄,那麼會將該目錄下的所有文件添加到 container 中,不包括目錄;
如果文件是可識別的壓縮格式,則 docker 會幫忙解壓縮(注意壓縮格式);
如果<src>是文件且<dest>中不使用斜槓結束,則會將<dest>視爲文件, <src>的內容會寫入
<dest>;
如果<src>是文件且<dest>中使用斜槓結束,則會<src>文件拷貝到<dest>目錄下。
格式:
ADD <src> <dest>
該命令將複製指定的<src>到容器中的<dest>。
其中<src>可以是 Dockerfile 所在目錄的一個相對路徑;也可以是一個 URL;還可以是一個 tar 文件(自動解壓爲目錄)
<dest>是 container 中的絕對路徑
可以複製網址他就會自動幫你下載
ADD 隨便寫一個網址
這個命令的意思就是把Dockerfile目錄裏的文件幫你拷到容器中
10、COPY
格式爲 COPY <src><dest>
複製本地主機的<src>(爲 Dockerfile 所在目錄的相對路徑)到容器中的<dest>。
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 選項,例如
$ sudodocker build –tmyrepo/myapp/tmp/test1/
docker 應用案例:使用 dockerfile 創建 sshd 鏡像模板並提供 http 訪問應用
1、建一個 sshd_dockerfile 工作目錄
編輯 run.sh 文件
在主機上生成 ssh 祕鑰對,並創建 authorized_keys 文件
2、寫 Dockerfile
以上選項的含義解釋:
FROM centos:centos6 選擇一個已有的 os 鏡像作爲基礎
MAINTAINER 鏡像的作者
RUN yum install -y openssh-server sudo 安裝 openssh-server 和 sudo 軟件包
添加測試用戶 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 上必須要有,否則創建出來的容器 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
執行 docker images 查看新生成的鏡像
使用剛纔建好的鏡像運行一個容器,將容器的端口映射到主機的 10122
在宿主主機打開一個終端,連接剛纔新建的容器
注: admin 用戶是容器中的用戶, 192.168.1.102 地址是宿主機的地址。
測試 sudo 執行授權命令: