Docker for Java Developers
1. 基本概念
1.1. 主要组件
Docker有三个主要组件:
- 镜像是Docker的构建组件,而且是定义应用程序操作系统的只读模板
- 容器是Docker的运行组件,它是从镜像创建的。容器可以运行、启动、停止、移动和删除
- 镜像在注册中心中存储、共享和管理,并且是Docker的分发组件。Docker Store 是一个公开可用的注册中心。https://hub.docker.com/
为了上这三个组件协同工作,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:关于镜像,记住下面两句话
- 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中的生命周期、阶段、目标
- 生命周期有三套:clean、default、site
- 生命周期由多个阶段组成的,比如default生命周期的阶段包括:clean、validate、compile、
- 每个阶段由多个目标组成,也就是说目标才是定义具体行为的
- 插件是目标的具体实现
稍微留一下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所有的能力,而且还有一些额外的特性:
- 允许在镜像中自动提取tar文件
- 允许从远程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
Docker for Java Developers的更多相关文章
- Deployment Pipeline using Docker, Jenkins, Java
Deployment Pipeline using Docker, Jenkins, Java and Couchbase http://blog.couchbase.com/2016/septemb ...
- Watch out for these 10 common pitfalls of experienced Java developers & architects--转
原文地址:http://zeroturnaround.com/rebellabs/watch-out-for-these-10-common-pitfalls-of-experienced-java- ...
- Top 10 Mistakes Java Developers Make--reference
This list summarizes the top 10 mistakes that Java developers frequently make. #1. Convert Array to ...
- 100 high quality blogs from java developers
This list collects 100 high quality blogs from Java developers from all over the world. Some of thes ...
- Yet Another 10 Common Mistakes Java Developers Make When Writing SQL (You Won’t BELIEVE the Last One)--reference
(Sorry for that click-bait heading. Couldn’t resist ;-) ) We’re on a mission. To teach you SQL. But ...
- Top 10 Mistakes Java Developers Make(转)
文章列出了Java开发者最常犯的是个错误. 1.将数组转换为ArrayList 为了将数组转换为ArrayList,开发者经常会这样做: ? 1 List<String> list = A ...
- Top 10 Books For Advanced Level Java Developers
Java is one of the most popular programming language nowadays. There are plenty of books for beginne ...
- Docker最全教程之使用Docker搭建Java开发环境(十七)
前言 Java是一门面向对象的优秀编程语言,市场占有率极高,但是在容器化实践过程中,发现官方支持并不友好,同时与其他编程语言的基础镜像相比(具体见各语言镜像比较),确实是非常臃肿. 本篇仅作探索,希望 ...
- Forget Guava: 5 Google Libraries Java Developers Should Know
Forget Guava: 5 Google Libraries Java Developers Should Know Published on 2016 7 13 Somenath PandaFo ...
随机推荐
- Spring Cloud Alibaba 新一代微服务解决方案
本篇是「跟我学 Spring Cloud Alibaba」系列的第一篇, 每期文章会在公众号「架构进化论」进行首发更新,欢迎关注. 1.Spring Cloud Alibaba 是什么 Spring ...
- Django项目BBS博客论坛
BBS 项目开发逻辑梳理 第一步:先进行数据库设计 数据库设计规则是: 1.先创建基表:用户表.站点表.文章表.标签表.分类表.文章2标签第三张关系表.点赞点踩表.评论表 2.书写表中的基本含有的字段 ...
- 《Java基础知识》Java super关键字
super可以理解为是指向自己超(父)类对象的一个指针,而这个超类指的是离自己最近的一个父类. super也有三种用法: 1.普通的直接引用 与this类似,super相当于是指向当前对象的父类,这样 ...
- Blog 须知
转载 转载需通过博主同意方可 代码格式 博主遵循 \(Google\) 代码格式,代码满足以下规范: 字符数 每行代码必需不超过 80 字符 缩进 缩进不使用制表符,而是 2 个空格缩进 函数 函数左 ...
- WinForm WebBrowser 设置cookie
[DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)] public static exte ...
- Servlet是什么?JSP和Servlet的区别。Servlet的生命周期。
Servlet(Server Applet),全称Java Servlet, 是用Java编写的服务器端程序.而这些Sevlet都要实现Servlet这个借口.其主要功能在于交互式地浏览和修改数据,生 ...
- How to: Use XPO Upcasting in XAF 如何:在 XAF 中使用 XPO 强制转换
In this topic, you will learn how to use the Upcasting feature of XPO in XAF. It is useful when you ...
- IDEA去除掉虚线,波浪线,和下划线实线的方法
初次安装使用IDEA,总是能看到导入代码后,出现很多的波浪线,下划线和虚线,这是IDEA给我们的一些提示和警告,但是有时候我们并不需要,反而会让人看着很不爽,这里简单记录一下自己的调整方法,供其他的小 ...
- js数组对象过滤——filter,find,some,every
1.filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素. 原数组不变 不会对空数组进行检测 let arr1 = [1,2,3,4] let ...
- Android8.1 SystemUI源码分析之 电池时钟刷新
SystemUI源码分析相关文章 Android8.1 SystemUI源码分析之 Notification流程 分析之前再贴一下 StatusBar 相关类图 电池图标刷新 从上篇的分析得到电池图标 ...