写在前面

在部署第一篇中,我们学习了如何使用通过docker-maven-plugin来构建docker镜像,遗憾的是此方式需要依赖自建的Registry镜像仓库,这在实际开发过程中还是有困难的。

鉴于此,本篇来学习另一种方式,使用Dockerfile来构建docker镜像。注意此方式不需要依赖自建的镜像仓库,只需应用的jar包和一个Dockerfile文件。

本篇在第二篇《整合Swagger-UI实现在线API文档》的基础上,使用Dockerfile为SpringBoot应用构建Docker镜像。

Dockerfile常用指令

FROM

FROM用于指定所需依赖的基础镜像,格式如下:

1
FROM <image>:<tag>

举个例子,如某个镜像需要依赖java8的镜像:

1
FROM java:8

注意FROM命令必须放在Dockerfile文件的第一行。

MAINTAINER

MAINTAINER用于指定镜像维护者的名字,格式如下:

1
MAINTAINER <name>

举个例子,如某个镜像的维护者为kenbings:

1
MAINTAINER kenbings

ADD

ADD用于复制文件,格式如下:

1
ADD <src> <dest>

举个例子,如将当前目录下的shop-docker-file.jar包复制到docker容器的/目录下:

1
ADD shop-docker-file.jar /shop-docker-file.jar

ENTRYPOINT

ENTRYPOINT用于指定docker容器启动时执行的命令,格式如下:

1
ENTRYPOINT ["executable", "param1","param2"...]

举个例子,在启动容器时启动运行jar包:

1
ENTRYPOINT ["java", "-jar","/shop-docker-file.jar"]

ENV

ENV用于设置环境变量,格式如下:

1
ENV <key> <value>

举个例子,在mysql运行时设置root用户的密码:

1
ENV MYSQL_ROOT_PASSWORD envy123

EXPOSE

EXPOSE用于声明要暴露的端口(注意只会声明不会打开端口),格式如下:

1
EXPOSE <port1> <port2> ...

举个例子,声明服务运行在8080端口:

1
EXPOSE 8080

RUN

RUN用于自定义容器在构建过程中需要执行的命令,如安装一些软件、创建一些文件等,格式如下:

1
2
RUN <command>
RUN ["executable", "param1","param2"...]

举个例子,在容器构建过程中需要在/目录下创建一个名为shop-docker-file.jar的文件:

1
RUN bash -c 'touch /shop-docker-file.jar'

使用Dockerfile构建SpringBoot应用镜像

复制一个Module

开发者可以复制一份shop-swagger-ui源码,将其名字修改为shop-docker-file,然后对应包和文件中的信息也记得修改,本篇后续所有操作均在shop-docker-file这一Module中进行。

编写Dockerfile文件

我们在项目的src/main目录中新建一个名为docker的目录,然后在docker目录中新建一个名为Dockerfile的文件,里面的内容如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
# 指定该镜像所依赖的基础镜像
FROM openjdk:8u102
# 指定镜像的维护人
MAINTAINER kenbings
# 将当前目录下的jar包复制到docker容器中的/目录下
ADD shop-docker-file-0.0.1-SNAPSHOT.jar /shop-docker-file.jar
# 容器在运行过程中创建一个名为shop-docker-file.jar的文件
RUN bash -c 'touch /shop-docker-file.jar'
# 声明服务暴露在8080端口
EXPOSE 8080
# 指定容器启动时执行的命令
ENTRYPOINT ["java","-jar","/shop-docker-file.jar"]

使用maven打包应用

接下来我们按照图示操作进行打包:

可以看到镜像构建成功:

1
2
3
4
5
6
7
8
9
10
[INFO] Building jar: E:\MyShop\myshop-all\shop-docker-file\target\shop-docker-file-0.0.1-SNAPSHOT.jar
[INFO]
[INFO] --- spring-boot-maven-plugin:2.1.3.RELEASE:repackage (repackage) @ shop-docker-file ---
[INFO] Replacing main artifact with repackaged archive
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.759 s
[INFO] Finished at: 2021-12-13T14:59:31+08:00
[INFO] ------------------------------------------------------------------------

接着我们新建/mydata/app/shop-docker-file目录,然后将打包生成的jar包以及Dockerfile文件上传到该目录中。

在Linux系统上构建Docker镜像

/mydata/app/shop-docker-file目录下,执行如下命令来构建docker镜像:

1
docker build -t myshop-all/shop-docker-file:0.0.1-SNAPSHOT .

其中-t表示指定镜像仓库名称/镜像名称:镜像标签,.表示使用当前目录下的Dockerfile文件。上述命令执行结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[root@kenbings shop-docker-file]# docker build -t myshop-all/shop-docker-file:0.0.1-SNAPSHOT .
Sending build context to Docker daemon 36.5MB
Step 1/6 : FROM openjdk:8u102
---> ca5dd051db43
Step 2/6 : MAINTAINER kenbings
---> Running in 89102f5205f6
Removing intermediate container 89102f5205f6
---> 3a095a2cfe51
Step 3/6 : ADD shop-docker-file-0.0.1-SNAPSHOT.jar /shop-docker-file.jar
---> 0429582ab23e
Step 4/6 : RUN bash -c 'touch /shop-docker-file.jar'
---> Running in 3083441e10a6
Removing intermediate container 3083441e10a6
---> 10be5dacfb00
Step 5/6 : EXPOSE 8080
---> Running in 505f2c42fbdf
Removing intermediate container 505f2c42fbdf
---> fbab2deea31e
Step 6/6 : ENTRYPOINT ["java","-jar","/shop-docker-file.jar"]
---> Running in bde857feb023
Removing intermediate container bde857feb023
---> 7c0df63d8996
Successfully built 7c0df63d8996
Successfully tagged myshop-all/shop-docker-file:0.0.1-SNAPSHOT

查看一下该镜像是否确实生成:

1
2
[root@kenbings shop-docker-file]# docker images|grep 'docker-file'
myshop-all/shop-docker-file 0.0.1-SNAPSHOT 7c0df63d8996 About a minute ago 714MB

启动MySQL服务

第一步,下载MySQL5.7的docker镜像:

1
docker pull mysql:5.7

第二步,创建对应目录:

1
2
3
mkdir -p /mydata/mysql/log
mkdir -p /mydata/mysql/data
mkdir -p /mydata/mysql/conf

第三步,启动MySQL服务:

1
2
3
4
5
docker run -p 3306:3306 --name mysql \
-v /mydata/mysql/log:/var/log/mysql \
-v /mydata/mysql/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=envy123 \
-d mysql:5.7

简单解释一下参数含义:
(1)-p 3306:3306,表示将容器的3306端口映射到宿主机的3306端口,注意格式为“宿主机端口:容器端口”;
(2)-v /mydata/mysql/log:/var/log/mysql,表示将容器的日志文件夹挂载到宿主机,注意格式为“宿主机:容器;
(3)-v /mydata/mysql/data:/var/lib/mysql,表示将容器的数据文件夹挂载到宿主机,注意格式为“宿主机:容器;
(4)-e MYSQL_ROOT_PASSWORD=envy123,表示初始化容器中root用户的密码。

第四步,进入到运行MySQL服务的docker容器中:

1
docker exec -it mysql /bin/bash

第五步,使用MySQL命令进入客户端:

1
mysql -uroot -penvy123 --default-character-set=utf8

第六步,创建shop数据库:

1
create database shop character set utf8;

第七步,打开一个新的终端,安装上传下载插件,将shop.sql文件上传到Linux服务器上,可指定目录为/mydata

1
yum -y install lrzsz

然后将shop.sql文件拷贝到mysql容器的/目录下:

1
docker cp /mydata/shop.sql mysql:/

接着进入到第六步中的sql命令环境,将shop文件导入到数据库:

1
2
use shop;
source /shop.sql;

第八步,root的账号的权限,使得任何ip都能访问到:

1
grant all privileges on *.* to 'root'@'%';

这样就完成了MySQL的启动服务。

启动shop-docker-file应用服务

第一步,创建对应目录:

1
mkdir -p /mydata/app/shop-docker-file/logs

第二步,使用如下命令来启动该服务,注意这里我们需要使用--link参数来让应用使用db域名来访问MySQL服务:

1
2
3
4
5
docker run -p 8080:8080 --link mysql:db \
-v /etc/localtime:/etc/localtime \
-v /mydata/app/shop-docker-file/logs:/var/logs \
--name shop-docker-file \
-d myshop-all/shop-docker-file:0.0.1-SNAPSHOT

第三步,开放8080端口(注意只有当防火墙是运行状态下才需要进行此操作):

1
2
firewall-cmd --zone=public --add-port=8080/tcp --permanent
firewall-cmd --reload

第四步,打开浏览器,访问http://宿主机IP:8080/swagger-ui.html连接,查看shop-docker-file服务是否已经正常启动:

然后我们测试一下“获取所有的品牌信息”的接口,可以看到数据是可以正常返回的:

这样我们就完成了使用Dockerfile为SpringBoot应用构建Docker镜像,并运行项目这一功能。