八、【Docker筆記】使用Dockerfile創建鏡像
摘要:# 0. 創建Dockerfile所在目錄 $ sudo mkdir /opt/tmp_dockerbuilder # 1. 創建Dockerfile文件並編寫內容 $ sudo vim Dockerfile # Nginx # VERSION 1.0 FROM ubuntu MAINTAINER gongziqi [email protected] 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 [email protected] ---> 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的。若基於image-A創建新的鏡像時,新的Dockerfile中使用 FROM image-A指定基礎鏡像時,會自動執行 ONBUILD 指令內容,即等價於在 FROM指令後添加了以上的兩條指令。
在前面我們講解了基於已有的 鏡像容器創建和基於本地模板導入 兩種方式來創建鏡像,在這裏我們就來說說第三種創建鏡像的方式。Dockerfile是一個文本格式的配置文件,我們可以通過Dockerfile快速創建自定義的鏡像。
一、基本結構
Dockerfile是由多行命令語句組成的,並且在文件中支持以 # 開始的註釋行。我們一般將Dockerfile文件分爲四部分:基礎鏡像信息、維護者信息、鏡像操作指令和容器啓動時執行指令。其中,第一行(不包含註釋行)必須指定基於的基礎鏡像,例如:FROM ubuntu。之後可以是維護者信息,如:MAINTAINER gongziqi [email protected]。再往後可以是鏡像的操作指令,如:
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
最後可以是容器啓動時執行指令,如:CMD /usr/sbin/nginx。
# 0. 在ubuntu鏡像的基礎上,安裝inotify-tools/nginx/apache2/openssh-server等,創建新的Nginx鏡像 # Nginx # VERSION 1.0 FROM ubuntu MAINTAINER gongziqi [email protected] 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"]
二、指令
1、FROM
語法爲:FROM
2、MAINTAINER
語法:MAINTAINER
3、RUN
語法:RUN
4、CMD
支持三種方式:
-
CMD ["executable", "param1", "param2"],使用 exec執行,推薦方式。
-
CMD command param1 param2,在 /bin/sh 中執行,提供給需要交互的應用。
-
CMD ["param1","param2"],提供給 ENTRYPOINT的默認參數。
指定啓動容器時執行的命令,每個Dockerfile只能由一條 CMD命令。若指定多條,則只有最後一條有效。若在啓動容器時,指定了運行的命令,則CMD命令將會被覆蓋。
5、EXPOSE
語法:EXPOSE
6、ENV
語法:ENV
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
7、ADD
語法:ADD
8、COPY
語法:COPY
9、ENTRYPOINT
語法:ENTRYPOINT ["executable","param1","param2"] 或 ENTRYPOINT command param1 param2(shell中執行)。配置容器啓動後執行的命令,並且不可被docker run 提供的參數覆蓋。每個Dockerfile只能有一個ENTRYPOINT,當指定多個時,只有最後一個有效。
10、VOLUME
語法:VOLUME ["/data"]。創建一個可以從本地主機或其他容器掛載的掛載點,一般用來存放數據庫和需要保持的數據等。
11、USER
語法:USER daemon。指定運行容器時的用戶名或UID,後續的RUN指令也會使用指定用戶。當服務不需要管理員權限時,可通過該命令指定運行用戶,並且可以在之前創建所需要的用戶。如:RUN groupadd -r postgres && useradd -r -g postgres postgres。若此時需要臨時獲取管理員權限,則可使用gosu,不推薦使用sudo。
12、WORKDIR
語法:WORKDIR /path/to/workdir。爲後續的 RUN、CMD、ENTRYPOINT指令配置工作目錄。可使用多個WORKDIR,若後面的WORKDIR指定的是相對路徑,則是基於前一個WORKDIR指定的路徑。如:
WORKDIR /a WORKDIR b WORKDIR c RUN pwd # 結果爲:/a/b/c
13、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指令後添加了以上的兩條指令。在使用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 [email protected] 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 [email protected] ---> 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的