三、DockerFile 訂製屬於自己的專屬鏡像

  • 2019 年 10 月 31 日
  • 筆記

前言

上篇文章我們知道了怎麼操作鏡像和容器,到基礎都是從已經存在的鏡像開始的,那我們自己怎樣搭建一個鏡像並使用它呢?接下來就讓我們學習使用dockerfile 創建屬於自己的鏡像吧。

dockerfile

在這之前,我們需要知道dockerfile ,因為我們就是通過dockerfile 來創建鏡像的。那dockerfile 是什麼呢?
dockerfile 是一個文件,文件裡面是我們寫的一條條的指令,然後通過docker build
命令來構建一個鏡像。
現在難就難在這個指令怎麼寫,所以接下讓我們一起看看dockfile 指令吧。

dockerfile 指令

讓我們先來了解一些基本的 dockerfile 指令吧

FROM

FROM <image>  FROM <image>:<tag>  #tag是可選的,默認會使用latest版本的基礎鏡像

from 指令是依賴的基礎鏡像,所謂的訂製鏡像,是在其他的鏡像上添加一些我們自己東西,訂製成我們自己的鏡像。當然我們也可以不依賴任何鏡像,自己從頭開始搭建。那就使用
FROM scratch
scratch 其實也是一個docker 鏡像,但是這個鏡像比較難特殊,它是一個虛擬鏡像,裡面什麼都沒有,是一個空白的鏡像,所以如果想不依賴任何鏡像,可以使用from scratch

那現在又有一個問題了,dockfile 文件中可以出現多個From 么?

在docker 17.05 版本之前是不支援出現多個From 的,一個dockefile只能有一個From 指令,且必須放在文件中的第一行。因為作為基礎鏡像使用。在docker17.05 後支援多From 。表示構建的多重階段,不過最終生成的鏡像還是以最後一個From 基礎鏡像為基礎的。

RUN

run 指令 是表示在鏡像構建時運行的指令。
兩種格式:

#shell格式  run <命令>  eg: run apt-get update    #exec 格式  run ["可執行文件",「參數1」,「參數2」...]

COPY

複製文件的指令

copy 源路徑  目標路徑  #支援通配符  eg:copy hom?.txt /mydir/

ADD

add 是更高級的複製。copy 有的功能它都用,它還能訪問網路資源,源路徑可以是一個URL。源路徑文件也可以是一個壓縮文件,可以直接解壓。
所以如果想要直接複製一個壓縮包進去的話,就要使用COPY 而不能只用ADD了。
官方建議是能使用COPY 的就使用COPY ,因為COPY 命令語義比較明確就是複製文件,並且ADD 指令會使得鏡像構建快取失效,使得鏡像構建比較緩慢。

CMD

cmd 指令是表示在運行容器時執行的指令。

#shell 格式  cmd  <命令>  eg:cmd echo $HOME    #exec 格式  cmd ["可執行文件",「參數1」,「參數2」]  eg: cmd ["sh","-c","echo $HOME"]

ENTRYPOINT

entrypoint 入口點

entrypoint <命令>    entrypoint ["可執行文件","參數1","參數2"]

entryPoint 指令和 cmd 指令功能類似,不過entrypoint 可以讓鏡像變成像命令一樣使用,可以做應用運行前的準備工作。這個具體的後面講。

ENV

env 是設置環境變數的指令,

env MY_VERSION 1.0.0

ARG

arg 用於構建時傳遞的參數

arg <參數名>[=<默認值>]    eg:  arg version  arg myversion=1.0.0

VOLUME

定義匿名卷

volume <路徑>  volume ["<路徑1>",["<路徑2>"...]    eg: volume  /etc/docker/log

EXPOSE

申明埠

expose <埠1>  [<埠2>...]

這裡需要注意的是,expose 是申明容器應用埠,但是容器運行是並不一定就是開啟這個埠提供服務。在dockerfile 中寫入埠申明有兩個好處,一是當做鏡像服務的守護埠,方便映射,二是在運行時使用隨機埠映射時,就會映射的expose設置的埠上。

好了,指令當然不止這些,更多的想了解的查看:

https://docs.docker.com/engine/reference/builder/

簡單測試

之前這篇文章寫到一半放下了,因為中間docker出了一點問題,下載鏡像一直提示超時,然後設置了中國加速,才弄好。
上面我們了解了Dockerfile 指令,接下來就讓我們先做一個簡單的測試吧。
我們穿件一個springboot項目。創建一個HelloController 類。

@RestController  public class HelloController {      @RequestMapping("/")      public String hello(){          return "hello docke 我的簡單測試 ";      }  }

然後打成jar 包。放到我們伺服器的文件夾下。
並且在文件下創建Dockerfile文件

vim Dcokerfile    #文件內容  FROM java:8  VOLUME /tmp  ADD hello-1.0.0.jar hello-1.0.0.jar  ENTRYPOINT ["java","-jar","/hello-1.0.0.jar"]

可以看到用到的命令都是我們上面介紹的。java8作為基礎鏡像,/tmp作為數據卷, add 將本地jar包添加到鏡像中,entrypoint 運行我們的jar包。

file

在該目錄下構建鏡像現在,最後面的點別忘記了。

docker build -t helle:v1 .

file
可以看到我們的鏡像分4不構建,也就是構建四個鏡像,因為我們Dockerfile 中有四條指令。前面說了後一條指令是在前一條指令的基礎上構建鏡像的。所以這四個鏡像中前面三個就是中間鏡像了。

我們現在看看我們創建的鏡像。
file

我們接下來啟動鏡像

docker run -d -p 8090:8080 hello:v1 

file
其中 -d 是後台啟動,-p 是映射埠,前面的是我們設置的埠,後面是項目運行的埠。
啟動後我們在瀏覽器上訪問下。

http://192.168.252.53:8090

file

這樣我們通過docker 構建我們springboot 的項目,創建屬於我們自己的鏡像就完成了。

配置docker遠程訪問

我們現在要做的是,直接通過idea打包生成docker鏡像。所以,第一步開啟docker的遠程訪問,我的docker 是安裝到伺服器上的。我先在本地檢測一下,伺服器上的docker 是否開啟的遠程訪問。

docker -H 192.168.252.53 info

file
說明是沒有開啟docker的遠程服務的。所以進入伺服器。
執行如下操作,在docker.service. 文件夾下創建一個http-proxy.conf文件.

sudo mkdir /etc/systemd/system/docker.service.d  sudo vim /etc/systemd/system/docker.service.d/http-proxy.conf

文件內容

[Service]  ExecStart=  ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock

然後重啟daemon和docker

sudo systemctl daemon-reload  sudo systemctl restart docker

然後我們再 在本地測試一下。說明docker 的遠程訪問已經配置好了。
file

idea配置

我們打開我們的hello 項目,在pom.xml 中增加配置

<properties>          <java.version>1.8</java.version>          <docker.image.prefix>quellanan</docker.image.prefix>  </properties>

在build 中增加。

<!-- Docker -->              <plugin>                  <groupId>com.spotify</groupId>                  <artifactId>docker-maven-plugin</artifactId>                  <version>1.0.0</version>                  <!-- 將插件綁定在某個phase執行 -->                  <executions>                      <execution>                          <id>build-image</id>                          <!-- 用戶只需執行mvn package ,就會自動執行mvn docker:build -->                          <phase>package</phase>                          <goals>                              <goal>build</goal>                          </goals>                      </execution>                  </executions>                  <configuration>                      <!-- 指定生成的鏡像名 -->                      <imageName>${docker.image.prefix}/${project.artifactId}</imageName>                      <!-- 指定標籤 -->                      <imageTags>                          <imageTag>${project.version}</imageTag>                      </imageTags>                      <!-- 指定 Dockerfile 路徑 -->                      <dockerDirectory>src/main/docker</dockerDirectory>                      <!-- 指定遠程 docker api地址 -->                      <dockerHost>http://192.168.252.53:2375</dockerHost>                      <resources>                          <resource>                              <targetPath>/</targetPath>                              <!-- jar包所在的路徑此處配置的對應target目錄 -->                              <directory>${project.build.directory}</directory>                              <!-- 需要包含的jar包,這裡對應的是Dockerfile中添加的文件名 -->                              <include>${project.build.finalName}.jar</include>                          </resource>                      </resources>                  </configuration>              </plugin>  

在src/main/docker 中創建Dockerfile 文件,文件內容上面Dockerfile 內容一樣

FROM java:8  VOLUME /tmp  ADD hello-1.0.0.jar hello-1.0.0.jar  ENTRYPOINT ["java","-jar","/hello-1.0.0.jar"]

file

mvn package

因為我們配置在構建的時候就會進行docker 打包。所以我們知己運行mvn package

file
控制台查看是打包成功的。
我們去伺服器上看下,有沒有
file
可以看到已經成功了。

番外

這篇總算寫完啦算是,中間自己親自試驗,踩了一路坑,也算是初步弄好了。以後我們項目不用將jar 包放到伺服器上再來創建鏡像了,可以直接在我們項目中打包構建鏡像就想構建jar 包一樣簡單。還是可以的吧。

好了,就說這麼多啦

後續加油♡

歡迎大家關注個人公眾號 "程式設計師愛酸奶"

分享各種學習資料,包含java,linux,大數據等。資料包含影片文檔以及源碼,同時分享本人及投遞的優質技術博文。

如果大家喜歡記得關注和分享喲❤

file