1. 基本概念java
1.1. 主要組件git
Docker有三個主要組件:github
爲了上這三個組件協同工做,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
這些指令被存儲在一個叫「Dockerfile」的文件中。當你請求構建鏡像時,Docker讀取這個Dockerfile文件,而後執行這些指令,並返回最終的鏡像。ubuntu
(PS:關於鏡像,記住下面兩句話
)
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中的生命週期、階段、目標
稍微留一下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全部的能力,並且還有一些額外的特性:
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/