What: 什麼是構建docker鏡像?java
構建docker鏡像在現有鏡像的基礎上,修改或添加我的的功能後,從新打包成新鏡像的過程git
Why: 爲何要構建docker鏡像?github
docker鏡像方便部署及分享他人docker
mkdir demo01-helloworld cd demo01-helloworld
Docker以文件Dockerfile
做爲配置文件,內容以下shell
Dockerfileapache
FROM ubuntu:latest CMD ["/bin/echo", "Hello world!"]
以上內容很是簡單ubuntu
FROM
用來配置基礎鏡像,這裏以ubuntu的最新版本的鏡像做爲基礎鏡像CMD
表示鏡像中執行的命令,這裏等同於執行命令/bin/echo "Hello World!"
命令數組
docker image build . -t demo01-helloworld:0.0.1
.
表示當前文件夾裏的全部文件eclipse
-t
等同於--tag
,做用是給鏡像打標籤,這裏的標籤名爲demo01-helloworld
maven
:
後是鏡像的版本號,若是省略則默認爲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啓動時先判斷有沒有該容器,若是不存在則經過鏡像建立相應的容器,而後執行容器
須要說明的是CMD
能夠在構造鏡像的時候不指定,啓動容器的時候執行。若是啓動時指定了命令,則CMD
中指定的命令將不會執行,即被覆蓋,現象以下。你看懂了嗎?
$ docker container run demo01-helloworld:0.0.1 /bin/echo "Hello world! v2" Hello world! v2
mkdir demo02-hellojava cd demo02-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
在打包以前先肯定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!
如前文所述構建鏡像須要一個基礎鏡像,基礎鏡像也能夠不提早拉取,構建的時候若是不存在也會自動拉取
該例子中要想啓動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,即僞終端建立配置文件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!
命令 | 功能 |
---|---|
FROM | 指定基礎鏡像 |
COPY | 複製文件或文件夾 |
ENV | 設置環境變量 |
RUN | 執行一個命令,能夠寫多個,一般用於安裝軟件包 |
CMD | 執行一個命令,只有一個被執行,可被docker run後面的命令所覆蓋,即若是命令行中有該命令,CMD中的將不會執行 |
ENTRYPOINT | 配置容器啓動時的命令,必定會執行 |
EXPOSE | 暴露的端口號 |