四十三、Docker-鏡像製作

1、Docker commit | export 鏡像製作

1.1 基於Docker Commit製作鏡像

# 將運行的容器提交爲新鏡像
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE                               COMMAND                  CREATED             STATUS              PORTS                  NAMES
06af4d90b48a        docker.io/ansible/centos7-ansible   "/bin/bash"              28 minutes ago      Up 10 minutes       0.0.0.0:6022->22/tcp   confident_ptolemy
05aa29d3caac        nginx                               "nginx -g 'daemon ..."   3 hours ago         Up About an hour    0.0.0.0:81->80/tcp     zealous_booth
ccdfec8b3752        nginx                               "nginx -g 'daemon ..."   3 hours ago         Up 3 hours          0.0.0.0:80->80/tcp     goofy_kowalevski

# 鏡像製作
[root@localhost ~]# docker commit 06af4d90b48a centos7-ssh
sha256:859860b8c6f796a8281ba68fa4cb134e9478a3cc2c9d25e3fa3f7aa4a2b499f4
[root@localhost ~]# docker images
REPOSITORY                          TAG                 IMAGE ID            CREATED             SIZE
centos7-ssh                         latest              859860b8c6f7        13 seconds ago      447 MB
nginx                               latest              5a3221f0137b        7 months ago        126 MB
docker.io/ansible/centos7-ansible   latest              688353a31fde        3 years ago         447 MB

#基於新鏡像啓動新的容器
[root@localhost ~]# docker run -itd --privileged -p 6023:22 -p 82:80 centos7-ssh
8d72d4b21cd4fe56e2a3095a7254ed6936b8b157eeba62413fb72fb187f3b024

將已提交的鏡像導出爲tar包(鏡像列表),發送給其他Docker宿主機即可使用

[root@localhost ~]# docker images
REPOSITORY                          TAG                 IMAGE ID            CREATED             SIZE
centos7-ssh                         latest              859860b8c6f7        14 minutes ago      447 MB
nginx                               latest              5a3221f0137b        7 months ago        126 MB
docker.io/ansible/centos7-ansible   latest              688353a31fde        3 years ago         447 MB
[root@localhost ~]# docker save 859860b8c6f7 > centos7-ssh.tar

其他Docker宿主機導入

[root@localhost ~]# docker load < centos7-ssh.tar

1.2 基於Docker export製作鏡像

[root@localhost ~]# docker ps
CONTAINER ID        IMAGE                               COMMAND                  CREATED             STATUS              PORTS                                      NAMES
8d72d4b21cd4        centos7-ssh                         "/bin/bash"              10 minutes ago      Up 10 minutes       0.0.0.0:6023->22/tcp, 0.0.0.0:82->80/tcp   eager_ramanujan
06af4d90b48a        docker.io/ansible/centos7-ansible   "/bin/bash"              48 minutes ago      Up 30 minutes       0.0.0.0:6022->22/tcp                       confident_ptolemy
05aa29d3caac        nginx                               "nginx -g 'daemon ..."   3 hours ago         Up About an hour    0.0.0.0:81->80/tcp                         zealous_booth
ccdfec8b3752        nginx                               "nginx -g 'daemon ..."   3 hours ago         Up 3 hours          0.0.0.0:80->80/tcp                         goofy_kowalevski

#將一個容器導出成爲一個tar包鏡像(會丟失容器內存中的指令)
[root@localhost ~]# docker export 8d72d4b21cd4 > centos7-ssh.tar
#將centos7-ssh.tar導入到Docker鏡像列表
[root@localhost ~]# cat centos7-ssh.tar|docker import - centos7-ssh-v1
sha256:86ac2787cfb2a21d302bc06b361812025b097e56567511dadbbc8f6adb24176d
[root@localhost ~]# docker images
REPOSITORY                          TAG                 IMAGE ID            CREATED             SIZE
centos7-ssh-v1                      latest              86ac2787cfb2        12 seconds ago      428 MB
centos7-ssh                         latest              859860b8c6f7        22 minutes ago      447 MB
nginx                               latest              5a3221f0137b        7 months ago        126 MB
docker.io/ansible/centos7-ansible   latest              688353a31fde        3 years ago         447 MB

啓動

#基於導入的centos7-ssh-v1創建新的虛擬機,無法啓動
[root@localhost ~]# docker run -itd --privileged -p 6026:22 -p 83:80 centos7-ssh-v1
/usr/bin/docker-current: Error response from daemon: No command specified.
See '/usr/bin/docker-current run --help'.

#讓啓動的CentOS虛擬機,能夠在前臺一直運行(永不退出)
[root@localhost ~]# docker run -itd --privileged -p 6024:22 -p 83:80 centos7-ssh-v1 /bin/bash
3028916479c5456cd42c4dadfa57f94f8f13a01f587a8440856ff8e1232b9262
[root@localhost ~]# docker run -itd --privileged -p 6025:22 -p 84:80 centos7-ssh-v1 sleep 9999d
1c807954af04d0353a895b4c9855816a574490d638376404348c5338352e5674
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE                               COMMAND                  CREATED             STATUS              PORTS                                      NAMES
1c807954af04        centos7-ssh-v1                      "sleep 9999d"            6 seconds ago       Up 5 seconds        0.0.0.0:6025->22/tcp, 0.0.0.0:84->80/tcp   clever_clarke
3028916479c5        centos7-ssh-v1                      "/bin/bash"              16 seconds ago      Up 15 seconds       0.0.0.0:6024->22/tcp, 0.0.0.0:83->80/tcp   hopeful_fermat
8d72d4b21cd4        centos7-ssh                         "/bin/bash"              17 minutes ago      Up 17 minutes       0.0.0.0:6023->22/tcp, 0.0.0.0:82->80/tcp   eager_ramanujan
06af4d90b48a        docker.io/ansible/centos7-ansible   "/bin/bash"              55 minutes ago      Up 37 minutes       0.0.0.0:6022->22/tcp                       confident_ptolemy
05aa29d3caac        nginx                               "nginx -g 'daemon ..."   3 hours ago         Up About an hour    0.0.0.0:81->80/tcp                         zealous_booth
ccdfec8b3752        nginx                               "nginx -g 'daemon ..."   3 hours ago         Up 3 hours          0.0.0.0:80->80/tcp                         goofy_kowalevski
[root@localhost ~]# 

推薦使用方案一。

2、Dockerfile 鏡像製作

企業生產環境推薦使用Dockerfile製作鏡像,Dockerfile製作原理:將基於一個基礎鏡像,通過編寫Dockerfile方式,將各個功能進行疊加,最終形成新的Docker鏡像,是目前互聯網企業中打包鏡像最爲推薦的方式。
Dockerfile是一個鏡像的表示,也是一個鏡像的原材料,可以通過Dockerfile來描述構建鏡像,並自動構建一個容器。

DockerFile製作鏡像必備指令:

FROM	 指定所創建鏡像的基礎鏡像;
MAINTAINER	指定維護者信息;
RUN	運行命令;
CMD	指定啓動容器時默認執行的命令;
LABEL	指定生成鏡像的元數據標籤信息;
EXPOSE	聲明鏡像內服務所監聽的端口;
ENV	指定環境變量;
ADD	賦值指定的<src>路徑下的內容到容器中的<dest>路徑下,<src>可以爲URL;如果爲tar文件,會自動解壓到<dest>路徑下
COPY	賦值本地主機的<scr>路徑下的內容到容器中的<dest>路徑下;一般情況下推薦使用COPY而不是ADD;
ENTRYPOINT	指定鏡像的默認入口;
VOLUME	創建數據掛載點;
USER	指定運行容器時的用戶名或UID;
WORKDIR	配置工作目錄;
ARG	指定鏡像內使用的參數(例如版本號信息等);
ONBUILD	配置當前所創建的鏡像作爲其他鏡像的基礎鏡像時,所執行的創建操作的命令;
STOPSIGNAL	容器退出的信號;
HEALTHCHECK	 如何進行健康檢查;
SHELL	指定使用SHELL時的默認SHELL類型;

Dockerfile語法命令詳解:

FROM指定所創建的鏡像的基礎鏡像,如果本地不存在,則默認會去Docker Hub下載指定鏡像。
格式爲:FROM<image>,或FROM<image>:<tag>,或FROM<image>@<digest>。任何Dockerfile中的第一條指令必須爲FROM指令。並且,如果在同一個Dockerfile文件中創建多個鏡像,可以使用多個FROM指令(每個鏡像一次)。
MAINTAINER指定維護者信息,格式爲MAINTAINER<name>。例如:
MAINTAINER [email protected]
該信息將會寫入生成鏡像的Author屬性域中。
RUN運行指定命令。
格式爲:RUN<command>或RUN ["executable","param1","param2"]。
注意:後一個指令會被解析爲json數組,所以必須使用雙引號。
前者默認將在shell終端中運行命令,即/bin/sh -c;後者則使用exec執行,不會啓動shell環境。
指定使用其他終端類型可以通過第二種方式實現,例如:
RUN ["/bin/bash","-c","echo hello"]
每條RUN指令將在當前鏡像的基礎上執行指定命令,並提交爲新的鏡像。當命令較長時可以使用\換行。例如:
RUN apt-get update \
&& apt-get install -y libsnappy-dev zliblg-dev libbz2-dev \
&& rm -rf /var/cache/apt
CMD用來指定啓動容器時默認執行的命令。它支持三種格式:
CMD ["executable","param1","param2"] 使用exec執行,是推薦使用的方式;
CMD param1 param2 在/bin/sh中執行,提供給需要交互的應用;
CMD ["param1","param2"] 提供給ENTRYPOINT的默認參數。
每個Dockerfile只能有一條CMD命令。如果指定了多條命令,只有最後一條會被執行。入股用戶啓動容器時指定了運行的命令(作爲run的參數),則會覆蓋掉CMD指定的命令。
LABEL指令用來生成用於生成鏡像的元數據的標籤信息。
格式爲:LABEL <key>=<value> <key>=<value> <key>=<value> ...。
例如:
LABEL version="1.0"
LABEL description="This text illustrates \ that label-values can span multiple lines."
EXPOSE聲明鏡像內服務所監聽的端口。
格式爲:EXPOSE <port> [<port>...]
例如:
EXPOSE 22 80 443 3306
注意:該命令只是起到聲明作用,並不會自動完成端口映射。在容器啓動時需要使用-P(大寫P),Docker主機會自動分配一個宿主機未被使用的臨時端口轉發到指定的端口;使用-p(小寫p),則可以具體指定哪個宿主機的本地端口映射過來。
ENV指定環境變量,在鏡像生成過程中會被後續RUN指令使用,在鏡像啓動的容器中也會存在。
格式爲:ENV <key><value>或ENV<key>=<value>...。
例如:
ENV GOLANG_VERSION 1.6.3
ENV GOLANG_DOWNLOAD_RUL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz
ENV GOLANG_DOWNLOAD_SHA256 cdd5e08530c0579255d6153b08fdb3b8e47caabbe717bc7bcd7561275a87aeb
RUN curl -fssL "$GOLANG_DOWNLOAD_RUL" -o golang.tar.gz && echo "$GOLANG_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - && tar -C /usr/local -xzf golang.tar.gz && rm golang.tar.gz
ENV GOPATH $GOPATH/bin:/usr/local/go/bin:$PATH
RUN mkdir -p "$GOPATH/bin" && chmod -R 777 "$GOPATH"
指令指定的環境變量在運行時可以被覆蓋掉,如docker run --env <key>=<value> built_image。
ADD該指令將複製指定的<src>路徑下的內容到容器中的<dest>路徑下。
格式爲:ADD<src> <dest>
其中<src>可以使Dockerfile所在目錄的一個相對路徑(文件或目錄),也可以是一個URL,還可以是一個tar文件(如果是tar文件,會自動解壓到<dest>路徑下)。<dest>可以使鏡像內的絕對路徑,或者相當於工作目錄(WORKDIR)的相對路徑。路徑支持正則表達式,例如:
ADD *.c /code/
COPY複製本地主機的<src>(爲Dockerfile所在目錄的一個相對路徑、文件或目錄)下的內容到鏡像中的<dest>下。目標路徑不存在時,會自動創建。路徑同樣支持正則。格式爲:COPY <src> <dest>當使用本地目錄爲源目錄時,推薦使用COPY。
ENTRYPOINT指定鏡像的默認入口命令,該入口命令會在啓動容器時作爲根命令執行,所有傳入值作爲該命令的參數。
支持兩種格式:
ENTRYPOINT ["executable","param1","param2"] (exec調用執行);
ENTRYPOINT command param1 param2(shell中執行)。
此時,CMD指令指定值將作爲根命令的參數。
每個Dockerfile中只能有一個ENTRYPOINT,當指定多個時,只有最後一個有效。
在運行時可以被--entrypoint參數覆蓋掉,如docker run --entrypoint。
VOLUME
創建一個數據卷掛載點。
格式爲:VOLUME ["/data"]
可以從本地主機或者其他容器掛載數據卷,一般用來存放數據庫和需要保存的數據等。
USER
指定運行容器時的用戶名或UID,後續的RUN等指令也會使用特定的用戶身份。格式爲:USER daemon
當服務不需要管理員權限時,可以通過該指令指定運行用戶,並且可以在之前創建所需要的用戶。例如:
RUN groupadd -r nginx && useradd -r -g nginx nginx要臨時獲取管理員權限可以用gosu或者sudo。
WORKDIR爲後續的RUN、CMD和ENTRYPOINT指令配置工作目錄。
格式爲:WORKDIR /path/to/workdir。
可以使用多個WORKDIR指令,後續命令如果參數是相對的,則會基於之前命令指定的路徑。例如:
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
則最終路徑爲/a/b/c
ARG指定一些鏡像內使用的參數(例如版本號信息等),這些參數在執行docker build命令時才以--build-arg<varname>=<value>格式傳入。格式爲:ARG<name>[=<default value>]。
則可以用docker build --build-arg<name>=<value>來指定參數值。
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
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
使用ONBUILD指令的鏡像,推薦在標籤中註明,例如:ruby:1.9-onbuild。
STOPSIGNAL
指定所創建鏡像啓動的容器接收退出的信號值。例如:
STOPSIGNAL singnal
HEALTHCHECK配置所啓動容器如何進行健康檢查(如何判斷是否健康),自Docker 1.12開始支持。格式有兩種:
HEALTHCHECK [OPTIONS] CMD command    :根據所執行命令返回值是否爲0判斷;HEALTHCHECK NONE:禁止基礎鏡像中的健康檢查。
 [OPTION]支持:
--inerval=DURATION  (默認爲:30s):多久檢查一次;
--timeout=DURATION  (默認爲:30s):每次檢查等待結果的超時時間;
--retries=N        (默認爲:3):如果失敗了,重試幾次才最終確定失敗。
SHELL指定其他命令使用shell時的默認shell類型。
格式爲: SHELL ["executable","parameters"]默認值爲 ["bin/sh","-c"]。
注意:對於Windows系統,建議在Dockerfile開頭添加# escape=`來指定轉移信息。
創建鏡像
編寫Dockerfile之後,可以通過docker build命令來創建鏡像。
基本的docker build [選項] 內容路徑,該命令將讀取指定路徑下(包括子目錄)的Dockerfile,並將該路徑下的所有內容發送給Docker服務端,由服務端來創建鏡像。因此除非生成鏡像需要,否則一般建議放置Dockerfile的目錄爲空目錄。
如果使用非內容路徑下的Dockerfile,可以通過-f選項來指定其路徑;
要指定生成鏡像的標籤信息,可以使用-t選項。
例如:指定Dockerfile所在路徑爲 /tmp/docker_builder/,並且希望生成鏡像標籤爲build_repo/first_image,可以使用下面的命令:
docker build -t build_repo/first_image /tmp/docker_builder
使用.dockerignore文件
可以通過.dockeringore文件(每一行添加一條匹配模式)來讓Docker忽略匹配模式路徑下的目錄和文件。例如:
# comment
*/tmp*
*/*/tmp*
tmp?
~*

Dockerfile製作規範及技巧:

精簡鏡像用途:儘量讓每個鏡像的用途都比較集中、單一,避免構造大而複雜、多功能的鏡像;
選用合適的基礎鏡像:過大的基礎鏡像會造成構建出臃腫的鏡像,一般推薦比較小巧的鏡像作爲基礎鏡像;
提供詳細的註釋和維護者信息: Dockerfile也是一種代碼,需要考慮方便後續擴展和他人使用;
正確使用版本號:使用明確的具體數字信息的版本號信息,而非latest,可以避免無法確認具體版本號,統一環境;
減少鏡像層數:減少鏡像層數建議儘量合併RUN指令,可以將多條RUN指令的內容通過&&連接;
及時刪除臨時和緩存文件:這樣可以避免構造的鏡像過於臃腫,並且這些緩存文件並沒有實際用途;
提高生產速度:合理使用緩存、減少目錄下的使用文件,使用.dockeringore文件等;
調整合理的指令順序:在開啓緩存的情況下,內容不變的指令儘量放在前面,這樣可以提高指令的複用性;
減少外部源的干擾:如果確實要從外部引入數據,需要制定持久的地址,並帶有版本信息,讓他人可以重複使用而不出錯。

實例:製作centos 鏡像

# 創建 Dockerfile
[root@localhost ~]# mkdir docker-image
[root@localhost ~]# cd docker-image/
[root@localhost docker-image]# touch Dockerfile

# 查看源
[root@localhost docker-image]# docker images
REPOSITORY                          TAG                 IMAGE ID            CREATED             SIZE
nginx                               latest              5a3221f0137b        7 months ago        126 MB
docker.io/ansible/centos7-ansible   latest              688353a31fde        3 years ago         447 MB

# 編輯製作文件
[root@localhost docker-image]# vim Dockerfile 

FROM docker.io/ansible/centos7-ansible
RUN rm -rf /etc/yum.repos.d/epel*
MAINTAINER cluo 20200323
RUN echo 123456|passwd --stdin root
RUN yum install -y net-tools
RUN yum install -y openssh-server
COPY ssh_host_rsa_key /etc/ssh/
COPY ssh_host_ed25519_key /etc/ssh/
COPY ssh_host_ecdsa_key /etc/ssh/
RUN chown root:ssh_keys /etc/ssh/ssh_host_ecdsa_key /etc/ssh/ssh_host_ed25519_key /etc/ssh/ssh_host_rsa_key
EXPOSE 22 80
CMD /usr/sbin/sshd;/bin/bash

# 拷貝ssh文件到當前目錄
[root@localhost docker-image]# ls /etc/ssh/
moduli      sshd_config         ssh_host_ecdsa_key.pub  ssh_host_ed25519_key.pub  ssh_host_rsa_key.pub
ssh_config  ssh_host_ecdsa_key  ssh_host_ed25519_key    ssh_host_rsa_key
[root@localhost docker-image]# cp /etc/ssh/ssh_host_ecdsa_key .
[root@localhost docker-image]# cp /etc/ssh/ssh_host_rsa_key .
[root@localhost docker-image]# cp /etc/ssh/ssh_host_ed25519_key .

# 製作
[root@localhost docker-image]# docker build -t centos7-ssh .

...
Successfully built 45ef6218ff65

# 完成鏡像 centos7-ssh 製作
[root@localhost docker-image]# docker images
REPOSITORY                          TAG                 IMAGE ID            CREATED              SIZE
centos7-ssh                         latest              45ef6218ff65        About a minute ago   672 MB
nginx                               latest              5a3221f0137b        7 months ago         126 MB
docker.io/ansible/centos7-ansible   latest              688353a31fde        3 years ago          447 MB

# 補充:鏡像刪除命令
[root@localhost docker-image]# docker rmi -f 45ef6218ff65 

啓動 centos7-ssh

[root@localhost docker-image]# docker run -itd --privileged -p 6022:22 centos7-ssh
051bbeaf0dad1d1a318b286e91fb03310efbd35bf15fab3e15e3515f6e45116a
[root@localhost docker-image]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                          NAMES
051bbeaf0dad        centos7-ssh         "/bin/sh -c /usr/s..."   4 minutes ago       Up 4 minutes        80/tcp, 0.0.0.0:6022->22/tcp   epic_goldstine

連接
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章