Docker系列-(2) 鏡像製做與發佈

docker.png

上篇文章引入了Docker的基本原理和操做,本節文章主要介紹如何製做Docker鏡像和發佈。java

鏡像文件結構

Docker鏡像的本質是一系列文件的集合,這些文件依次疊加,造成了最後的鏡像文件,相似於下圖所示的結構,linux

Screen Shot 2019-11-24 at 11.42.39 AM.png

從底層往上,依次是文件系統層,操做系統層,專有鏡像層,讀寫層。nginx

  • 啓動文件層:Docker啓動時的用到的文件系統,啓動完成後會自動脫離,用戶不會與這一層直接打交道。docker

  • 操做系統層:這一層主要是操做系統相關的一些文件,根據發行版本的不一樣,可能有CentsOS、Ubuntu等等。文件包含dev,/proc,/bin,/etc 等目錄, 是一個最小化的操做系統,不少工具都沒有提供,包括vi、wget、curl等。注意這一層不包含linux內核,只是可在任何知足要求的linux內核上運行。shell

  • 專有鏡像層:通常各大軟件都會基於上面兩層製做專有的鏡像,好比nginx、tomcat等,都有專門的官方鏡像,能夠直接在docker hub上下載。ubuntu

  • 讀寫層:這是咱們製做本身的鏡像時須要操做的層,是一個動態的運行環境,在後續鏡像製做中的好比ENV, Volume,cmd等操做最終落實到此運行環境中。centos

製做鏡像的實質就是修改讀寫層。當須要修改鏡像內的某個文件時,只對處於最上方的讀寫層進行了變更,不復寫下層已有文件系統的內容,已有文件在只讀層中的原始版本仍然存在,但會被讀寫層中的新版本文件所隱藏,當 docker commit 這個修改過的容器文件系統爲一個新的鏡像時,保存的內容僅爲最上層讀寫文件系統中被更新過的文件。tomcat

能夠經過history命令查看鏡像層,bash

Screen Shot 2019-11-24 at 3.05.19 PM.png

製做鏡像

製做鏡像有兩種通用的方法,第一種是直接經過配置好的Container來生成鏡像;另一種是經過Dockerfile的方式,基於已有的鏡像來生成新的鏡像,這種方法更爲經常使用。網絡

配置Container製做鏡像

這裏以製做nginx的鏡像爲例,介紹整個製做流程。

1)下載基礎鏡像,這裏以Ubuntu做爲基礎鏡像。因爲本地沒有鏡像能夠先利用docker search獲取官方鏡像的名稱,而後docker pull將鏡像下載到本地。

Screen Shot 2019-11-24 at 3.18.12 PM.png

2)以交互方式啓動鏡像,方便在容器中安裝軟件。-it表示交互方式,/bin/bash爲指定啓動的終端。下圖能夠看到已經成功進入到容器內部了。

docker run -it ubuntu:latest /bin/bash
複製代碼

Screen Shot 2019-11-24 at 3.21.23 PM.png

3)如今按照Nginx正常的安裝流程安裝便可,因爲Ubuntu鏡像只是一個最小化的系統,可能你須要經過apt-get install來安裝一些須要的軟件。

4)退出容器,使用commit指令生成新的鏡像。

注意退出容器的時候,也有兩種方法,一般直接exit就能夠,可是這樣容器也會關閉。若是不想關閉容器,只是退出終端,可使用Ctrl+P+Q快捷鍵,此時退出後,容器依然在後臺運行。

直接運行docker commit同時指定容器id或者name,以及鏡像名就能夠了,新的鏡像製做完成了。

docker commit e0c618df0979 ubuntu-nginx
複製代碼

Screen Shot 2019-11-24 at 3.32.46 PM.png

接下來能夠經過正常的方式啓動鏡像了。

使用Dockerfile製做

上面介紹了手動進入容器內部,製做Docker鏡像的方式,通常比較繁瑣。一般咱們會使用Dockerfile的方式製做鏡像,這種方式下咱們須要編寫Dockerfile文件。

Dockerfile文件

Dockerfile是一個文本格式的配置文件,用戶可使用Dockerfile快速建立自定義鏡像。

下面是一個簡單的Dockerfile文件,先將編譯生成的jar文件複製到容器,而後聲明容器暴露的端口,最後指定在啓動容器時須要運行的指令。

FROM openjdk:8
ADD ["target/bazaar-1.0.0.jar", "bazaar.jar"]
EXPOSE 1234
ENTRYPOINT ["java", "-jar", "/bazaar.jar"]
複製代碼

Dockerfile中經常使用的指令集有:

Picture1.png

  • FROM: 第一條指令必須爲FROM指令,用於指定基礎鏡像。
  • MAINTAINER: 指定維護者信息。
  • RUN: 會在shell終端運行命令。
  • EXPOSE: 格式爲 EXPOSE [ ...],聲明容器須要暴露的端口號。鏡像啓動能夠經過 –P 或 -p 進行端口映射的綁定。
  • ENV: 指定一個環境變量,能夠被後續的RUN引用,而且在容器中記錄該環境變量。
  • ADD: 該命令將複製指定的到容器中的。其中能夠是Dockerfile所在目錄的一個相對路徑;也能夠是tar文件(自動解壓)。
  • VOLUME: 格式爲 VOLUME [path]。建立一個能夠從本地主機或其餘容器掛載點,通常用來存放須要保持的數據。
  • USER: 指定運行容器時的用戶名,後續的RUN也會指定該用戶。
  • WORKDIR: 指定工做空間,後續命令都在此目錄下執行。

比較複雜的是CMD與ENTRYPOINT的對比,二者均可以運行指令,可是稍有不一樣。

  • CMD給出的是一個容器的默認的可執行體,能夠被覆蓋。
  • ENTRYPOINT纔是正統地用於定義容器啓動之後的執行體,這個執行體必定會被執行。

(1) CMD單獨使用

FROM debian:wheezy
CMD ["/bin/ping", "localhost"]
複製代碼

啓動後不指定任何參數,將會ping localhost,

$ docker run -it test
PING localhost (127.0.0.1): 48 data bytes
56 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.076 ms
56 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.087 ms
56 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.090 ms
^C--- localhost ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.076/0.084/0.090/0.000 ms
複製代碼

可是若是啓動容器的同時帶有新的指令,則原有的CMD會被新的指令覆蓋

docker run -it test bash
root@e8bb7249b843:/#
複製代碼

(2)CMD和ENTRYPOINT同時使用

CMD一般用做傳遞參數給ENTRYPOINT,以下例子所示:

FROM debian:wheezy
ENTRYPOINT ["/bin/ping"]
CMD ["localhost"]
複製代碼

直接運行鏡像並不指定任何參數,將會一直ping localhost

$ docker run -it test
PING localhost (127.0.0.1): 48 data bytes
56 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.096 ms
56 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.088 ms
56 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.088 ms
^C--- localhost ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.088/0.091/0.096/0.000 ms
複製代碼

若是直接運行的同時,指定一個參數,將會ping對應的參數,此時CMD被覆蓋。

$ docker run -it test google.com
PING google.com (173.194.45.70): 48 data bytes
56 bytes from 173.194.45.70: icmp_seq=0 ttl=55 time=32.583 ms
56 bytes from 173.194.45.70: icmp_seq=2 ttl=55 time=30.327 ms
56 bytes from 173.194.45.70: icmp_seq=4 ttl=55 time=46.379 ms
^C--- google.com ping statistics ---
5 packets transmitted, 3 packets received, 40% packet loss
round-trip min/avg/max/stddev = 30.327/36.430/46.379/7.095 ms
複製代碼

若是你想要製做的容器更加通用一些,能夠在Dockerfile中使用CMD ["/path/dedicated_command"],這樣你能夠在運行容器的同時,根據需求來覆蓋已有的指令。

利用Dockerfile製做容器

上面介紹了Dockerfile中經常使用的指令,通常咱們寫好Dockerfile以後,直接進入到Dockerfile所在的目錄,運行docker build便可,Docker會根據Dockerfile中指定的步驟來生成咱們的鏡像。

$ docker build -t your_image_name .
複製代碼

以上就是製做鏡像的全部流程,接下來介紹鏡像的發佈。

鏡像發佈

鏡像發佈有兩種選擇,能夠直接push到官方的docker hub,你只須要註冊一個docker帳號便可;也能夠本身在本地建立私有倉庫,將鏡像push這裏。

Docker Hub

打開 hub.docker.com/ 註冊好帳戶後,記住好本身的帳戶名,待會須要將本地的鏡像打tag帶上用戶名,而後進行push。

首先使用以下的指令就給本地鏡像打tag,

docker tag myImage:v1 your_user_name/myImage:v1
複製代碼

接下來直接push就行,會自動push到官方倉庫,注意可能會須要docker login一下,這裏直接輸入用戶名密碼便可。

docker push your_user_name/myImage:v1
複製代碼

這樣官方倉庫就有你的Image了, 之後直接docker pull就好了。

本地私有倉庫

(1) 首先下載registry鏡像:docker pull registry.

(2) 接着在5000端口啓動,docker run -d --name reg -p 5000:5000 registry.

(3) 配置http傳輸,私服默認只能使用https,須要配置開放http.

以centos上的配置爲例,

Picture1.png

注意圖中的ip根據實際registry的ip來進行設置,能夠經過docker inspect reg來找到。

配置完畢重啓下docker服務

systemctl daemon-reload 
systemctl restart docker
複製代碼

以上就完成了私有倉庫的建立。

接下來直接push Image到倉庫便可,流程和push到官方倉庫相似,只是打tag的用戶名改爲私有倉庫的地址。

(1)打tag

docker tag hello-world http://192.168.244.7:5000/hello-world 
複製代碼

(2)push鏡像

docker push 192.168.244.7:5000/hello-world
複製代碼

(3)查詢鏡像:

Picture1.png

(4)查詢鏡像版本:

Picture1.png

以上就是鏡像製做和發佈的所有內容,下節會介紹實際部署中,docker-compose的使用以及docker的網絡通訊。

參考連接:

相關文章
相關標籤/搜索