Docker for Java Developers
1.? 基本概念 1.1.? 主要组件 Docker有三个主要组件:
为了上这三个组件协同工作,Docker守护进程(或者叫Docker容器)运行在一个主机上,并负责构建、运行和分发Docker容器。此外,客户端是一个Docker二进制文件,它接受来自用户的命令并与引擎来回通信。 1.2.??Docker Image Docker镜像是一个可以从其中启动Docker容器的只读模板。每个镜像又一系列的层组成。(PS:现在发现,把“Image”翻译成专业术语“镜像”的话这里就感觉跟别扭。原文是“Each image consists of a series of layers”,如果按“Image”本来的意思“图像”去理解就很好理解了,对PhotoShop有点儿了解的人都能理解这句话,“图像由一系列图层组成”,真是太形象了。) Docker如此轻量级的原因之一就是这些层(图层)。当你修改镜像(例如,将应用程序更新到新版本)时,将构建一个新的层。因此,只添加或更新该层,而不是像使用虚拟机那样替换整个映像或完全重建。现在,您不需要发布整个新图像,只需要更新即可,从而使分发Docker镜像更快、更简单。(PS:越发觉得此处用“图像”更好理解,加个新图层或者在原先的图层上做修改即可) 每个镜像都是从一个基本镜像开始的。你也可以使用自己的镜像作为新镜像的基础。如果你有一个基本的Apache镜像,那么你可以使用它作为所有web应用程序镜像的基础。 Docker使用一组称为指令的简单描述性步骤来构建镜像。每条指令在镜像中创建一个新层。
这些指令被存储在一个叫“Dockerfile”的文件中。当你请求构建镜像时,Docker读取这个Dockerfile文件,然后执行这些指令,并返回最终的镜像。 (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.example12 <artifactId>hello-demo13 <version>0.0.1-SNAPSHOT14 <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 24 <artifactId>spring-boot-starter-web25 </dependency>
26
27 28 29 <artifactId>spring-boot-starter-test30 <scope>test</scope>
31 32 </dependencies>
33
34 <build>
35 <plugins>
36 <plugin>
37 38 <artifactId>spring-boot-maven-plugin39 </plugin>
40 </plugins>
41 </build>
42
43 <profiles>
44 <profile>
45 <id>docker</id>
46 47 48 49 <groupId>io.fabric850 <artifactId>docker-maven-plugin51 <version>0.30.052 <configuration>
53 <images>
54 <image>
55 <name>hellodemo56 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 63 </image>
64 </images>
65 </configuration>
66 <executions>
67 <execution>
68 <id>docker:build69 <phase>package</phase>
70 <goals>
71 <goal>build</goal>
72 </goals>
73 </execution>
74 75 <id>docker:start76 <phase>install77 78 <goal>run79 <goal>logs80 81 82 </executions>
83 84 85 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选项给这个容器起个名字。 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 ID3 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 3 docker container rm 5 # 用正则表达式删除匹配到的容器
6 docker container ps -a | grep wildfly | awk '{print $1}' | xargs docker container rm
8 # 删除所有容器
9 docker container rm $(docker container ps -aq)
3.7.? 查看端口映射 1 docker container port > or <NAME>
4.? 参考 https://github.com/docker/labs/tree/master/developer-tools/java/? https://github.com/fabric8io/docker-maven-plugin? ?? (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |