Docker for Java Developers

1.  基本概念java

1.1.  主要組件git

Docker有三個主要組件:github

  • 鏡像是Docker的構建組件,並且是定義應用程序操做系統的只讀模板
  • 容器是Docker的運行組件,它是從鏡像建立的。容器能夠運行、啓動、中止、移動和刪除
  • 鏡像在註冊中心中存儲、共享和管理,而且是Docker的分發組件。Docker Store 是一個公開可用的註冊中心。https://hub.docker.com/

爲了上這三個組件協同工做,Docker守護進程(或者叫Docker容器)運行在一個主機上,並負責構建、運行和分發Docker容器。此外,客戶端是一個Docker二進制文件,它接受來自用戶的命令並與引擎來回通訊。web

1.2.  Docker Image正則表達式

Docker鏡像是一個能夠從其中啓動Docker容器的只讀模板。每一個鏡像又一系列的層組成。(PS:如今發現,把「Image」翻譯成專業術語「鏡像」的話這裏就感受跟彆扭。原文是「Each image consists of a series of layers」,若是按「Image」原本的意思「圖像」去理解就很好理解了,對PhotoShop有點兒瞭解的人都能理解這句話,「圖像由一系列圖層組成」,真是太形象了。)spring

Docker如此輕量級的緣由之一就是這些層(圖層)。當你修改鏡像(例如,將應用程序更新到新版本)時,將構建一個新的層。所以,只添加或更新該層,而不是像使用虛擬機那樣替換整個映像或徹底重建。如今,您不須要發佈整個新圖像,只須要更新便可,從而使分發Docker鏡像更快、更簡單。(PS:愈加以爲此處用「圖像」更好理解,加個新圖層或者在原先的圖層上作修改便可)docker

每一個鏡像都是從一個基本鏡像開始的。你也可使用本身的鏡像做爲新鏡像的基礎。若是你有一個基本的Apache鏡像,那麼你可使用它做爲全部web應用程序鏡像的基礎。shell

Docker使用一組稱爲指令的簡單描述性步驟來構建鏡像。每條指令在鏡像中建立一個新層。apache

  1. 運行一條命令
  2. 添加一個文件或目錄
  3. 建立一個環境變量
  4. 當啓動一個容器時運行一個進程

這些指令被存儲在一個叫「Dockerfile」的文件中。當你請求構建鏡像時,Docker讀取這個Dockerfile文件,而後執行這些指令,並返回最終的鏡像。ubuntu

(PS:關於鏡像,記住下面兩句話

  • Each image consists of a series of layers.
  • Each instruction creates a new layer in our image. 

1.3.  Docker Container

容器由操做系統、用戶添加的文件和元數據組成。正如咱們所看到的,每一個容器都是由一個鏡像構建的。鏡像告訴Docker容器持有什麼、啓動容器時運行什麼進程以及各類其餘配置數據。鏡像是隻讀的。當Docker從映像運行容器時,它會在鏡像之上添加一個讀寫層,而後你的應用程序就能夠在其中運行了。

1.4.  Docker Engine

Docker Host是在安裝Docker的時候建立的。一旦Docker Host被建立了,那麼你就能夠管理鏡像和容器了。例如,你能夠下載鏡像、啓動或中止容器。

1.5.  Docker Client

Docker Client與Docker Host通訊,進而你就能夠操做鏡像和容器了。

 

2.  構建一個鏡像

2.1.  Dockerfile

Docker經過從Dockerfile文件中讀取指令來構建鏡像。Dockerfile是一個文本文檔,它包含用戶能夠在命令行上調用的全部命令來組裝一個鏡像。docker image build命令會使用這個文件,並執行其中的全部命令。

build命令還傳遞一個在建立映像期間使用的上下文。這個上下文能夠是本地文件系統上的路徑,也能夠是Git存儲庫的URL。

關於Dockerfile中可使用的命令,詳見 https://docs.docker.com/engine/reference/builder/

下面是一些經常使用的命令:

2.2.  建立你的第一個鏡像

首先,建立一個目錄hellodocker,而後在此目錄下建立一個名爲Dockerfile的文本文件,編輯該文件,內容以下:

從以上兩行命令咱們能夠看到,該鏡像是以ubuntu做爲基礎基礎,CMD命令定義了須要運行的命令。它提供了一個不一樣的入口/bin/echo,並給出了一個參數「hello world」。

2.3.  用Java建立你的第一個鏡像

補充:OpenJDK是Java平臺標準版的一個開源實現,是Docker官方提供的鏡像

首先,讓咱們建立一個java工程,而後打個jar包,接着建立並編輯Dockerfile

使用docker image build構建鏡像

使用docker container run啓動容器

其實,跟咱們日常那一套沒多大區別,不過是把打好的jar包作成鏡像而已

2.4.  使用Docker Maven Plugin構建鏡像

利用Docker Maven Plugin插件咱們可使用Maven來管理Docker鏡像和容器。下面是一些預約義的目標:

詳見 https://github.com/fabric8io/docker-maven-plugin

補充:Maven中的生命週期、階段、目標

  1. 生命週期有三套:clean、default、site
  2. 生命週期由多個階段組成的,好比default生命週期的階段包括:clean、validate、compile、
  3. 每一個階段由多個目標組成,也就是說目標纔是定義具體行爲的
  4. 插件是目標的具體實現

稍微留一下IDEA裏面的Maven區域就不難理解了

言歸正傳,利用docker-maven-plugin來構建鏡像的方式有不少,好比,能夠配置插件或屬性文件,還能夠結合Dockerfile,都在這裏:

https://github.com/fabric8io/docker-maven-plugin/tree/master/samples

此處,咱們演示用屬性文件的方式,首先,定義一段profile配置,好比這樣:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 3          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 4     <modelVersion>4.0.0</modelVersion>
 5     <parent>
 6         <groupId>org.springframework.boot</groupId>
 7         <artifactId>spring-boot-starter-parent</artifactId>
 8         <version>2.1.4.RELEASE</version>
 9         <relativePath/> <!-- lookup parent from repository -->
10     </parent>
11     <groupId>com.cjs.example</groupId>
12     <artifactId>hello-demo</artifactId>
13     <version>0.0.1-SNAPSHOT</version>
14     <name>hello-demo</name>
15     <description>Demo project for Spring Boot</description>
16 
17     <properties>
18         <java.version>1.8</java.version>
19     </properties>
20 
21     <dependencies>
22         <dependency>
23             <groupId>org.springframework.boot</groupId>
24             <artifactId>spring-boot-starter-web</artifactId>
25         </dependency>
26 
27         <dependency>
28             <groupId>org.springframework.boot</groupId>
29             <artifactId>spring-boot-starter-test</artifactId>
30             <scope>test</scope>
31         </dependency>
32     </dependencies>
33 
34     <build>
35         <plugins>
36             <plugin>
37                 <groupId>org.springframework.boot</groupId>
38                 <artifactId>spring-boot-maven-plugin</artifactId>
39             </plugin>
40         </plugins>
41     </build>
42 
43     <profiles>
44         <profile>
45             <id>docker</id>
46             <build>
47                 <plugins>
48                     <plugin>
49                         <groupId>io.fabric8</groupId>
50                         <artifactId>docker-maven-plugin</artifactId>
51                         <version>0.30.0</version>
52                         <configuration>
53                             <images>
54                                 <image>
55                                     <name>hellodemo</name>
56                                     <build>
57                                         <from>openjdk:latest</from>
58                                         <assembly>
59                                             <descriptorRef>artifact</descriptorRef>
60                                         </assembly>
61                                         <cmd>java -jar maven/${project.name}-${project.version}.jar</cmd>
62                                     </build>
63                                 </image>
64                             </images>
65                         </configuration>
66                         <executions>
67                             <execution>
68                                 <id>docker:build</id>
69                                 <phase>package</phase>
70                                 <goals>
71                                     <goal>build</goal>
72                                 </goals>
73                             </execution>
74                             <execution>
75                                 <id>docker:start</id>
76                                 <phase>install</phase>
77                                 <goals>
78                                     <goal>run</goal>
79                                     <goal>logs</goal>
80                                 </goals>
81                             </execution>
82                         </executions>
83                     </plugin>
84                 </plugins>
85             </build>
86         </profile>
87     </profiles>
88 </project> 

 而後,在構建的時候指定使用docker這個profile便可

1 mvn clean package -Pdocker

 

 

2.5.  Dockerfile命令(番外篇)

CMD 與 ENTRYPOINT 的區別

容器默認的入口點是 /bin/sh,這是默認的shell。

當你運行 docker container run -it ubuntu 的時候,啓動的是默認shell。

ENTRYPOINT 容許你覆蓋默認的入口點。例如:

 

這裏默認的入口點被換成了/bin/cat

ADD 與 COPY 的區別

ADD有COPY全部的能力,並且還有一些額外的特性:

  1. 容許在鏡像中自動提取tar文件
  2. 容許從遠程URL下載文件 

 

3.  運行一個Docker容器

3.1.  交互

以交互模式運行WildFly容器,以下:

1 docker container run -it jboss/wildfly

默認狀況下,Docker在前臺運行。-i容許與STDIN交互,-t將TTY附加到進程上。它們能夠一塊兒用做 -it

按Ctrl+C中止容器

3.2.  分離容器

1 docker container run -d jboss/wildfly

 用-d選項代替-it,這樣容器就以分離模式運行

(PS:-it前臺運行,-d後臺運行)

3.3.  用默認端口

若是你想要容器接受輸入鏈接,則須要在調用docker run時提供特殊選項。 

1 $ docker container ls
2 CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
3 93712e8e5233        jboss/wildfly       "/opt/jboss/wildfly/…"   4 minutes ago       Up 4 minutes        8080/tcp            serene_margulis
4 02aa2ed22725        ubuntu              "/bin/bash"              2 hours ago         Up 2 hours                              frosty_bhabha 

重啓容器

1 docker container stop `docker container ps | grep wildfly | awk '{print $1}'`
2 docker container run -d -P --name wildfly jboss/wildfly

-P選項將鏡像中的任何公開端口映射到Docker主機上的隨機端口。--name選項給這個容器起個名字。

1 $ docker container ls
2 CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                     NAMES
3 3f2babcc1df7        jboss/wildfly       "/opt/jboss/wildfly/…"   47 seconds ago      Up 47 seconds       0.0.0.0:32768->8080/tcp   wildfly

3.4.  用指定端口

1 docker container stop wildfly
2 docker container rm wildfly 

或者你還能夠用 docker container rm -f wildfly 來中止並刪除容器

1 docker container run -d -p 8080:8080 --name wildfly jboss/wildfly

格式是: -p hostPort:containerPort 

此選項將主機上的端口映射到容器中的端口。這樣就使得咱們能夠經過主機上的特定的端口來訪問容器。

如今咱們訪問http://localhost:8080/跟剛纔http://localhost:32768/是同樣的 

3.5.  中止容器

1 # 按id或name中止指定的容器
2 docker container stop <CONTAINER ID>
3 docker container stop <NAME>
4 
5 # 中止全部容器
6 docker container stop $(docker container ps -q)
7 
8 # 中止已經退出的容器
9 docker container ps -a -f "exited=-1"

3.6.  刪除容器

1 # 按id或name刪除指定的容器
2 docker container rm <CONTAINER ID>
3 docker container rm <NAME>
4 
5 # 用正則表達式刪除匹配到的容器
6 docker container ps -a | grep wildfly | awk '{print $1}' | xargs docker container rm
7 
8 # 刪除全部容器
9 docker container rm $(docker container ps -aq)

3.7.  查看端口映射

1 docker container port <CONTAINER ID> or <NAME>

4.  參考

https://github.com/docker/labs/tree/master/developer-tools/java/ 

https://github.com/fabric8io/docker-maven-plugin 

相關文章
相關標籤/搜索