在上一篇笔记 Docker基本概念与安装 中,我们已经获取到了一个Docker服务,并了解了Docker的基本组成及其各个组件的作用。
我们了解到,使用Docker的其中一个目的,是为了更加简单,方便的部署我们编写的服务,接下来,就以发布一个SpringBoot
的服务为例,来学习部署服务需要是用到的API指令。
首先,需要准备一个Springboot
的项目,这里准备一个简单的 Hello World 工程:
@RestController
@RequestMapping("hello")
public class HelloController {
@GetMapping("sayHello")
public String sayHello(String name) {
return "hello " + name;
}
}
提供一个GET请求的接口,在请求参数中输入什么就返回什么,这里不过多的赘述。
接下来,需要使用Maven
或Gradle
打包工具,将这个服务打成jar
包,我这里使用的是Gradle
,打包完成之后在build目录中就可以找到一个可运行的jar
包。
由于我的Docker是安装在虚拟机中的,所以我还需要将这个jar
拷贝到我的虚拟机中完成Docker镜像的构建,如果Docker是直接安装在当前系统中的话,后续的操作在当前系统中就可以完成了。
此处使用Xftp将生成的jar包拷贝到了虚拟机的/user/hello-boot
下,接下来的操作都在这里面完成。
下一步就是将刚刚生成的jar
包构建成可供Docker运行的image
文件,这一步需要使用到两个知识点:
docker build
指令Dockerfile
文件docker build
指令的作用,是解析Dockerfile
文件中的的脚本,把可执行文件(如上面的jar
包)打包到Docker镜像文件中,这个镜像文件可以在后续使用docker run
时,按照Dockerfile
文件中的脚本,执行相应的操作。简单的说,就是构建出docker的可执行文件。
先看构建语法:
docker build [OPTIONS] PATH | URL | -
[OPTIONS] 是执行build时的可选项,常用是有-t
,-f
:
其他先选项可以参考: docker build options
PATH 与 URL 是当前构建操作的context,它可以是一个文件路径(PATH),也可以是远程地址(URL),构建时需要引用的文件就应该放在context中,例如刚刚生成的jar
包。
综上,可以进入jar
包所在的文件目录,输入构建指令:
cd /usr/hello-boot/
docker build -t hello-boot:1.0.0 -f ./Dockerfile .
我们知道默认使用的就是当前路径下的Dockerfile,所以构建指令可以简化为:
docker build -t hello-boot:1.0.0 .
指令中最后那个.
就是上述语法中的 PATH ,在这里的含义就是执行当前目录为构建的context。
现在我们得到了一个完整的构建指令,但是仔细观察一下这个指令,会发现其中还缺少处理jar
包的指令,思考一下,这个指令会在什么位置呢?
Dockerfile 是一个脚本文件,里面定义了context的各种操作指令,以生成SpringBoot
镜像为例:
FROM openjdk:8-alpine3.9
MAINTAINER huizhiyimo
RUN mkdir -p /user/my-demo
COPY ./*.jar /user/my-demo
WORKDIR /user/my-demo
EXPOSE 8080
ENTRYPOINT java -Xms256m -Xmx256m -jar -Dspring.profiles.active=${SPRING_PROFILES_ACTIVE} *.jar
openjdk:8-alpine3.9
上构建。/user/my-demo
jar
,复制到容器中的/user/my-demo
中cd /user/my-demo
SpringBoot
服务Docker的镜像是像集装箱那样一层一层往上搭建的,通过 FROM 指令可以实现下图的分层效果:
FROM后面的镜像会先从本地的镜像仓库中寻找,如果本地没有就会从 DockerHub 中寻找,此处的openjdk:8-alpine3.9
是一个带有Java
运行环境的轻量级服务器,在DockerHub中找到这个镜像,打开IMAGE LAYERS就能大概知道这个镜像会怎么运行,如下图红框中的内容。
显然,通过这个镜像我们就可以得到一个Java的运行环境,以此为基础来运行SpringBoot
的服务就是顺理成章的事情了。
将编写好的DockerFile与jar
包放在同一目录下,执行构建指令:
docker build -t hello-boot:1.0.0 .
提示构建成功,此时再运行查看镜像的指令,就可以看到刚才通过FROM下载的openjdk
镜像与hello-boot
镜像:
docker images
如果构建的镜像有问题,可以通过删除镜像指令删掉再重新构建:
docker rmi [name:tag]
docker rmi hello-boot:1.0.0
通过docker run
指令可以将镜像运行起来:
docker run -d -p 8080:8080 -e SPRING_PROFILES_ACTIVE=test --restart=always --name=hello-1 hello-boot:1.0.0
-d
: 后台运行程序-p
:指定端口映射,左边的是宿主机端口,右边的是容器中的应用端口,与-d可以合并为-dp-e
: 指定环境变量,此处是指定profiles为test
(在Dockerfile的ENTRYPOINT中定义的变量)--restart=always
:启动docker容器时,自动运行--name
:指定运行容器的名称运行起来之后,可以通过docker ps
查看:
此时容器已经正常启动了,通过curl
指令来测试一下是否启动成功:
curl "http://127.0.0.1:8080/hello/sayHello?name=zhangsan"
至此,SpringBoot
服务就通过Docker发布成功了,如果想停止这个服务,可以使用下面的指令:
# 停止容器,hello-1为容器名
docker stop hello-1
# 删除容器
docker rm hello -1
注:如果项目迭代到了下一个版本,要发布新的服务,就需要执行上面的两个指令删除旧的容器,再通过新构建的镜像来运行新的容器。
Docker的运行指令可以参考 官方指令教程
本篇通过打包、构建镜像、运行容器、停止容器、删除容器的过程,学习了Docker的基本指令:
docker build
:构建镜像docker images
:查看本地镜像docker rmi
:删除镜像docker run
:运行容器docker ps
:查看容器docker stop
:停止容器docker rm
:删除容器一些思考
本篇描述的Docker使用方式,相对于传统的服务发布方式并没有太大的优势,不管是发布新服务,还是对服务进行扩展都需要按照流程重新构建镜像。
这是由于没有做到镜像的共享与复用导致的,在后续的笔记中,会接受如何通过远程镜像仓库来复用镜像来提升部署的效率。