docker構建映象

zhouweixin發表於2020-09-28

1 What & Why

What: 什麼是構建docker映象?

構建docker映象在現有映象的基礎上,修改或新增個人的功能後,重新打包成新映象的過程

Why: 為什麼要構建docker映象?

docker映象方便部署及分享他人

2 Hello World

2.1 目標

  1. 利用現有映象ubuntu構建新映象
  2. 映象的功能是利用ubuntu的echo命令列印Hello world

2.2 建立資料夾

mkdir demo01-helloworld
cd demo01-helloworld

2.3 建立配置檔案

Docker以檔案Dockerfile作為配置檔案,內容如下

Dockerfile

FROM ubuntu:latest

CMD ["/bin/echo", "Hello world!"]

以上內容非常簡單

  • FROM用來配置基礎映象,這裡以ubuntu的最新版本的映象作為基礎映象
  • CMD表示映象中執行的命令,這裡等同於執行命令/bin/echo "Hello World!"
    • 當前的格式為Exec格式
    • 後面會介紹shell格式

2.4 構建映象

命令

docker image build . -t demo01-helloworld:0.0.1
  • .表示當前資料夾裡的所有檔案

  • -t等同於--tag,作用是給映象打標籤,這裡的標籤名為demo01-helloworld

  • :後是映象的版本號,如果省略則預設為latest

構建過程如下,當列印Successfully tagged demo01-helloworld:0.0.1表明映象構建成功

$ docker image build . -t demo01-helloworld
Sending build context to Docker daemon  2.048kB
Step 1/2 : FROM ubuntu:latest
 ---> 4e2eef94cd6b
Step 2/2 : CMD ["/bin/echo", "Hello world!"]
 ---> Running in 581995f3af46
Removing intermediate container 581995f3af46
 ---> afa0f6e8fc94
Successfully built afa0f6e8fc94
Successfully tagged demo01-helloworld:0.0.1

可以用命令docker image ls查詢所有映象,再次確認已經構建完成

$ docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
demo01-helloworld   0.0.1               afa0f6e8fc94        19 seconds ago      73.9MB

執行映象,先生成容器,再啟動容器

$ docker container run demo01-helloworld:0.0.1
Hello world!

docker啟動時先判斷有沒有該容器,如果不存在則通過映象建立相應的容器,然後執行容器

2.5 注意

需要說明的是CMD可以在構造映象的時候不指定,啟動容器的時候執行。如果啟動時指定了命令,則CMD中指定的命令將不會執行,即被覆蓋,現象如下。你看懂了嗎?

$ docker container run demo01-helloworld:0.0.1 /bin/echo "Hello world! v2"
Hello world! v2

3 java應用

3.1 目標

  1. 利用現有映象openjdk構建新映象
  2. 映象的功能是執行java程式列印Hello java

3.2 建立資料夾

mkdir demo02-hellojava
cd demo02-java

3.3 建立java工程

選擇你喜歡的方式建立一個maven工程,可以從通過網頁下載模板,可以利用eclipse和idea等等

這裡採用mvn命令的方式建立

mvn archetype:generate -DgroupId=org.zwx.hellojava -DartifactId=demo02-hellojava -DinteractiveMode=false

結果如下

$ mvn archetype:generate -DgroupId=org.zwx.hellojava -DartifactId=demo02-hellojava -DinteractiveMode=false
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------< org.apache.maven:standalone-pom >-------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] --------------------------------[ pom ]---------------------------------
[INFO] ...省略一些內容
[INFO] Parameter: basedir, Value: /Users/zhouweixin/docker-demos
[INFO] Parameter: package, Value: org.zwx.hellojava
[INFO] Parameter: groupId, Value: org.zwx.hellojava
[INFO] Parameter: artifactId, Value: demo02-hellojava
[INFO] Parameter: packageName, Value: org.zwx.hellojava
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] project created from Old (1.x) Archetype in dir: /Users/zhouweixin/docker-demos/demo02-hellojava
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  16.557 s
[INFO] Finished at: 2020-09-28T17:55:09+08:00
[INFO] ------------------------------------------------------------------------

檔案目錄

.
├── pom.xml
└── src
    ├── main
    │   └── java
    │       └── org
    │           └── zwx
    │               └── hellojava
    │                   └── App.java
    └── test
        └── java
            └── org
                └── zwx
                    └── hellojava
                        └── AppTest.java

3.4 編譯執行

在打包之前先確定java應用可以正常執行

首先,修改檔案src/main/java/org/zwx/hellojava/App.java

package org.zwx.hellojava;

/**
 * Hello world!
 *
 */
public class App
{
    public static void main( String[] args )
    {
        System.out.println( "Hello java!" );
    }
}

然後,用mvn命令編譯打包

$ mvn package
[INFO] Scanning for projects...
[INFO]
[INFO] -----------------< org.zwx.hellojava:demo02-hellojava >-----------------
[INFO] Building demo02-hellojava 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] ...省略一些內容
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ demo02-hellojava ---
[INFO] Building jar: /Users/zhouweixin/docker-demos/demo02-hellojava/target/demo02-hellojava-1.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  1.531 s
[INFO] Finished at: 2020-09-28T17:59:40+08:00
[INFO] ------------------------------------------------------------------------

檔案目錄

.
├── pom.xml
├── src
│   └── ...省略一些內容
└── target
    ├── demo02-hellojava-1.0-SNAPSHOT.jar
    └── ...省略一些內容

當你執行完命令mvn package後,首先會編譯生成一些class檔案,然後打包成demo02-hellojava-1.0-SNAPSHOT.jar,生成的檔案都在目錄target下

該jar檔案是執行檔案,具體執行命令如下

$ java -cp target/demo02-hellojava-1.0-SNAPSHOT.jar org.zwx.hellojava.App
Hello java!

3.5 拉取基礎映象

如前文所述構建映象需要一個基礎映象,基礎映象也可以不提前拉取,構建的時候如果不存在也會自動拉取

該例子中要想啟動java應用,你知道需要哪個環境嗎?

你應該是猜對了,僅僅需要java的執行時環境(jre)

首先到hub.docker.com上檢索jre的相關tag,這裡我們選擇的是8u265-jre

二話不說,先拉取映象(也可以不提前拉取)

$ docker pull openjdk:8u265-jre
8u265-jre: Pulling from library/openjdk
57df1a1f1ad8: Pull complete
71e126169501: Pull complete
1af28a55c3f3: Pull complete
a9777c2d5c29: Pull complete
9248106993db: Pull complete
1f74ab5b5b3e: Pull complete
Digest: sha256:e98dece4606dc1ec47c0c9ab6aa43931577232a5b7d6fd46f3ead7377727b412
Status: Downloaded newer image for openjdk:8u265-jre
docker.io/library/openjdk:8u265-jre

用互動的方式執行該映象並確定java的版本

$ docker container run -it openjdk:8u265-jre
root@0687c67dccd0:/# java -version
openjdk version "1.8.0_265"
OpenJDK Runtime Environment (build 1.8.0_265-b01)
OpenJDK 64-Bit Server VM (build 25.265-b01, mixed mode)

引數說明

  • -it-i-t的縮寫
  • -i全稱是--interactive,即互動模式,可以正常的輸入輸出
  • -t是一個偽TTY,即偽終端

3.6 構建映象

建立配置檔案Dockerfile

FROM openjdk:8u265-jre

COPY target/demo02-hellojava-1.0-SNAPSHOT.jar /usr/src/demo02-hellojava-1.0-SNAPSHOT.jar

CMD java -cp /usr/src/demo02-hellojava-1.0-SNAPSHOT.jar org.zwx.hellojava.App

引數說明

  • COPY命令用於將本地檔案拷貝到基礎映象中,並且這個基礎映象中有java執行時環境,兩者結合滿足正常執行程式
    • 第一個引數為本地檔案目錄
    • 第二個引數為基礎映象中的目錄
  • CMD命令表示在基礎映象中執行的命令(可以不寫陣列的形式)

執行映象構建命令

$ docker image build . -t demo02-hellojava:0.0.1
Sending build context to Docker daemon  38.91kB
Step 1/3 : FROM openjdk:8u265-jre
 ---> d9d1d3243082
Step 2/3 : COPY target/demo02-hellojava-1.0-SNAPSHOT.jar /usr/src/demo02-hellojava-1.0-SNAPSHOT.jar
 ---> Using cache
 ---> 6c34d345bb51
Step 3/3 : CMD java -cp /usr/src/demo02-hellojava-1.0-SNAPSHOT.jar org.zwx.hellojava.App
 ---> Running in 0d9a33ea0ae1
Removing intermediate container 0d9a33ea0ae1
 ---> fc3cd9ee5218
Successfully built fc3cd9ee5218
Successfully tagged demo02-hellojava:0.0.1

啟動

$ docker container run demo02-hellojava:0.0.1
Hello java!

4 Dockfile中的命令

命令 功能
FROM 指定基礎映象
COPY 複製檔案或資料夾
ENV 設定環境變數
RUN 執行一個命令,可以寫多個,通常用於安裝軟體包
CMD 執行一個命令,只有一個被執行,可被docker run後面的命令所覆蓋,即如果命令列中有該命令,CMD中的將不會執行
ENTRYPOINT 配置容器啟動時的命令,一定會執行
EXPOSE 暴露的埠號

參考

相關文章