将微服务运行在Docker上

本文详细介绍了如何使用Dockerfile构建Docker镜像,包括编写Dockerfile、构建和运行镜像的步骤。同时,讨论了Docker镜像的管理,如使用DockerRegistry(包括DockerHub和私有仓库)进行存储和推送。此外,还展示了如何利用Maven插件简化Docker镜像的构建和推送过程。
摘要由CSDN通过智能技术生成

将微服务运行在Docker上

使用Dockerfile构建Docker镜像

Dockerfile构建Docker镜像。Dockerfile是一个文本文件,其中包含了若干条指令,指令描述了构建镜像的细节。
1)准备一个文件,名为Dockerfile:

FORM nginx
RUN echo '<h1>test</h1>' > /usr/share/nginx/html/index.html

FORM、RUN都是Dockerfile的指令。FROM指令用于指定基础镜像,RUN指令用于执行命令。
2)在Dockerfile所在路径执行以下命令构建镜像

docker build -t nginx:my .

其中,命令最后的点(.)用于路径参数传递,表示当前路径。
3)执行以下命令,即可使用该镜像启动一个Docker容器

docker run -d -p 92:80 nginx:my

4)访问
在这里插入图片描述

Dockerfile常用指令

ADD复制文件

ADD指令用于复制文件

ADD <src>... <dest>
ADD ["<src>",... "<dest>"]

从src目录复制文件到容器dest。其中src可用是Dockerfile所在目录的相对路径,也可以是一个URL,还可以是一个压缩包。
注:src必须在构建的上下文内,不能使用例如ADD …/somehine /something这样的命令,因为docker build命令首先会将上下文路径和其子目录发送到docker daemon。
如果src是一个URL,同时dest不以斜杠结尾,dest将被视为文件,src对应内容文件将被下载到dest。
如果src是一个URL,同时dest以斜杠结尾,dest将被视为目录,src对应内容将被下载到dest目录。
如果src是一个目录,那么整个目录下的内容将被复制,包括文件系统元数据。
如果文件是可识别的压缩包格式,则docker会自动解压。

ADD microservice-discovery-eureka.jar app.jar
ARG设置构建参数

ARG指令用于设置构建参数,类似于ENV。和ENV不同的是,ARG设置的是构建时的环境变量,在容器运行时是不会存在这些变量的。

ARG user1=someuser
CMD容器启动命令

CMD指令用于为执行容器提供默认值。每个Dockerfile只有一个CMD命令,如果指定了多个CMD命令,那么只有最后一条会被执行,如果启动容器时指定了运行的命令,则会覆盖CMD指定的命令。

CMD ["executable","param1","param2"](推荐使用)
CMD ["param1","param2"] (为ENTRYPOINT指令提供预设参数)
CMD command param1 param2 (在shell中执行)
CMD echo "This is a test." | wc -
COPY复制文件
COPY <src>... <dest>
COPY ["<src>",... "<dest>"]

复制本地端的src到容器的dest。COPY指令和ADD指令类似,COPY不支持URL和压缩包

ENTRYPOINT入口点
ENTRYPOINT ["executable","param1","param2"]
ENTRYPOINT command param1 param2

ENTRYPOINT和CMD指令的目的一样,都是指定Docker容器启动时执行的命令,可多次设置,但只有最后一个有效。

ENV设置环境变量

ENV指令用于设置环境变量

ENV <key> <value>
ENV <key>=<value> ...

ENV JAVA_JOME /path/to/java

EXPOSE声明暴露的端口

EXPOSE指令用于声明在运行时容器提供服务的端口,格式为EXPOSE <port> [<port>....]
需要注意的是,这只是一个声明,运行时并不会因为该声明就打开相应端口,该指令的作用主要是帮助镜像使用者理解该镜像服务的守护端口;其次是当运行时使用随机映射时,会自动映射EXPOSE的端口。

#声明暴露一个端口示例
EXPOSE port1
#相应的运行容器使用的命令
docker run -p port1 image
#声明暴露多个端口示例
EXPOSE port1 port2 port3
#相应的运行容器使用的命令
docker run -p port1 -p port2 -p port3 image
#也可指定需要映射到宿主机器上的端口号
docker run -p host_port1:port1 -p host_port2:port2 -p host_port3:port3 image
FROM指定基础镜像

使用FROM指令基础镜像,FROM指令有点像Java里面的extends关键字。需要注意的是,FROM指令必须指定且需要写在其他指令之前。FROM指令后的所有指令都依赖于该指定的镜像。

FROM <image>
FROM <image>:<tag>
FROM <image>@<digest>
LABEL为镜像添加元数据

LABEL指令用于为镜像添加元数据。
格式为LABEL <key>=<value> <key>=<value> <key>=<value>....
使用"""和”\“转换命令行

LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.lable-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates \
that label-values can span multiple lines."
MAINTAINER指定维护者的信息

MAINTAINER指令用于指定维护者的信息,用于为Dockerfile署名。
格式为MAINTAINER <name>

RUN执行命令
RUN <command>
RUN ["executable","param1","param2"]

RUN <command>在shell终端中运行,在Linux中默认是/bin/sh -c,在Windows中是cmd /s /c使用这种格式,使用这种格式,就像直接在命令行中输入命令一样。RUN ["executable","param1","param2"]使用exec执行,这种方式类似于函数调用。指定其他终端可以通过该方式操作,例如RUN ["/bin/bash","-c","echo hello"],该方式必须使用双引号["]而不能使用单引号[‘],因为该方式会被转换成一个JSON数组。

USER设置用户

该指令用于设置启动镜像时的用户或者UID,写在该指令后的RUN,CMD以及ENTRYPOINT指令都将使用该用户执行命令。

USER daemon
VOLUME指定挂载点

该指令使容器中的一个目录具有持久化存储的功能,该目录可被容器本身使用,也可共享给其他容器。当容器中的应用有持久化数据的需求时可以在Dockerfile中使用该指令。
VOLUME /data

WORKDIR 指定工作目录
WORKDIR /path/to/workdir

切换目录指令,类似于cd命令,写在该指令后的RUN、CMD以及ENTRYPOINT指令都将该目录作为当前目录,并执行相应的命令。

其他

Dockerfile还有一些其他的指令,例如STOPSINGAL、HEEALTHCHECK、SHELL等。不常用略。

使用Dockerfile构建镜像

准备工作

以项目microservice-discovery-eureka为例,首先执行以下命令,将项目构建成jar包:microservice-discovery-eureka-0.0.1-SNAPSHOT.jar

mvn clean package #使用Maven打包项目

在这里插入图片描述

镜像构建

1)在jar包所在目录,创建名为Dockerfile的文件。
touch Dockerfile
在Dockerfile中添加以下内容。

#基于哪个镜像
FROM java:8

#将本地文件夹挂载到当前容器
VOLUME /tmp

#复制文件到容器
ADD microservice-discovery-eureka-1.0-SNAPSHOT.jar app.jar
RUN bash -c 'touch /app.jar'

#声明需要暴露的端口
EXPOSE 8761

#配置容器启动后执行的命令
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

3)使用docker build命令构建镜像

docker build -t example/microservice-discovery-eureka:0.0.1 .
#格式:docker build -t 仓库名称/镜像名称(:标签) Dockerfile的相对位置

在这里插入图片描述
测试
1)启动镜像
docker run -d -p 8761:8761 example/microservice-discovery-eureka:0.0.1
2)访问http://Docker宿主机IP:8761/,可正常显示Eureka Server首页。
在这里插入图片描述

使用Docker Registry管理Docker镜像

至此,已经构建了Docker镜像,并将微服务运行在Docker之上。但是,一个完整的应用系统可能包含上百个微服务,那就可能对应着上百个镜像,如果考虑各个微服务的版本,那么可能会构建更多的镜像。这些镜像该如何管理呢?

使用Docker Hub管理镜像

Docker Hub是Docker官方维护的Docker Registry,上面存放着很多优秀的镜像。不仅如此,Docker Hub还提供认证、工作组结构、工作流工具、构建触发器等工具来简化工作。

注册与登录

Docker Hub的使用非常简单,只需注册一个Docker Hub账号,就可正常使用了。登录后,可看到Docker Hub的主页。
也可使用docker login命令登录Docker Hub。输入该命令并按照提示输入账号和密码,即可完成登录。
在这里插入图片描述

创建仓库

单击Docker Hub主页上的Create Repository按钮,按照提示填入信息即可创建一个仓库。只需填入相关信息,并单击Create按钮,就可创建一个名为microservice-discovery-eureka的公共仓库。
在这里插入图片描述

推送镜像

下面来将前文构建的镜像推送到Docker Hub。使用以下命令

docker push example/microservice-discovery-eureka:0.0.1

经过一段时间的等待,就可推送成功。这样,就可在Docker Hub查看已推送的镜像。
在这里插入图片描述

使用私有仓库管理镜像

很多场景下,需使用私有仓库管理Docker镜像。相比Docker Hub,私有仓库有以下优势

  • 节省带宽,对于私有仓库中已有的镜像,无须从Docker Hub下载,只需从私有仓库中下载即可。
  • 更加安全。
  • 便于内部镜像的统一管理
搭建私有仓库

Docker Registry 2.0的搭建非常简单,只需执行以下命令即可新建并启动一个Docker Registry 2.0

docker run -d -p 5000:5000 --restart=always --name registry2 registry:2

在这里插入图片描述

将镜像推送到私有仓库

前文使用了docker push命令将镜像推送到了Docker Hub,现在将前文构建的容器推送到私有仓库

docker push localhost:5000/example/microservice-discovery-eureka:0.0.1

执行以上命令,发现推送并没有成功,且提示以下内容:
在这里插入图片描述

Docker Hub默认的Docker Registry,所以example/microservice-discovery-eureka:0.0.1相当于docker.io/example/microservice-discovery-eureka:0.0.1。因此,想要将推送到私有仓库,需要修改镜像标签。

docker tag example/microservice-discovery-eureka:0.0.1 localhost:5000/example/microservice-discovery-eureka:0.0.1

修改标签后,再次执行
在这里插入图片描述

注:Docker Registry2.0需要Docker版本高于1.6
还可为私有仓库配置域名、SSL登录、认证等。
Docker Registry 2.0能够满足大部分场景下的需求,但它不包含界面、用户管理、权限控制等功能。如果想要使用这些功能,可使用Docker Trusted Registry。

使用Maven插件构建Docker镜像

Maven是一个强大的项目管理与构建工具。如果可以使用Maven构建Docker镜像,工作就能得到进一步的简化。
这里使用一款由Spotify公司开发的Maven插件

打开Docker远程API
# vim /usr/lib/systemd/system/docker.service
[Service]
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock

“unix:///var/run/docker.sock”:unix socket,本地客户端将通过这个来连接 Docker Daemon。
“tcp://0.0.0.0:2375”:tcp socket,表示允许任何远程客户端通过 2375 端口连接 Docker Daemon。
在这里插入图片描述
可以看到已经docker启动了一个新的守护进程。

设置白名单

vim /etc/docker/daemon.json 
{
  "insecure-registries":["192.168.238.10:5000"],									#是registries不是registry
}

将java8上传到私有仓库里

启动仓库

docker start registry:2

给java:8镜像修改标签并上传

docker tag java:8 192.168.185.120:5000/java
docker push 192.168.185.120:5000/java

在这里插入图片描述

快速入门

以项目microservice-discovery-eureka为例
1)在pom.xml中添加Maven的Docker插件。

            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <version>0.4.13</version>
                <configuration>
                    <imageName>example/microservice-discovery-eureka:0.0.1</imageName>
                    <dockerHost>http://192.168.185.120:2375</dockerHost>
                    <baseImage>192.168.185.120:5000/java</baseImage>
                    <entryPoint>["java","-jar","/${project.build.finalName}.jar"]</entryPoint>
                    <resources>
                        <resource>
                            <targetPath>/</targetPath>
                            <directory>${project.build.directory}</directory>
                            <include>${project.build.finalName}</include>
                        </resource>
                    </resources>
                </configuration>
            </plugin>
  • imageName:用于指定镜像名称,其中example是仓库名称,microservice-discovery-eureka是镜像名称,0.0.1是标签名称。
  • baseImage:用于指定基础镜像,类似于Dockerfile中的FROM指令。
  • entrypoint:类似于Dockerfile的ENTRYPOINT指令。
  • resources.resource.directory:用于指定需要复制的根目录,${project.build.directory}表示target目录。
  • resources.resource.include:用于指定需要复制的文件。${project.build.finalName}.jar指的是打包后的jar包文件。

2)执行以下命令,构建Docker镜像。

mvn clean package docker:build

在这里插入图片描述
在这里插入图片描述

插件读取Dockerfile进行构建

首先在/microservice-discovery-eureka/src/main/docker目录下,新建一个Dockerfile文件

#基于哪个镜像
FROM java:8

#将本地文件夹挂载到当前容器
VOLUME /tmp

#复制文件到容器
ADD microservice-discovery-eureka-1.0-SNAPSHOT.jar app.jar
RUN bash -c 'touch /app.jar'

#声明需要暴露的端口
EXPOSE 8761

#配置容器启动后执行的命令
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

修改pom.xml

            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <version>1.0.0</version>
                <configuration>
                    <imageName>example/microservice-discovery-eureka:0.0.1</imageName>
                    <dockerHost>http://192.168.2.120:2375</dockerHost>
                    <dockerDirectory>${project.basedir}/src/main/docker</dockerDirectory>
                    <resources>
                        <resource>
                            <targetPath>/</targetPath>
                            <directory>${project.build.directory}</directory>
                            <include>${project.build.finalName}.jar</include>
                        </resource>
                    </resources>
                </configuration>
            </plugin>

可以看到,不再指定baseImage和entrypoint,而是使用dockerDirectory指定Dockerfile所在的路径。这样,就可以使用Dockefiler构建Docker镜像了。
在这里插入图片描述
在这里插入图片描述

将插件绑定到某个phase执行

很多场景下,有这样的需求,执行例如mvn clean package时,插件就自动为构建Docker镜像。要想实现这点,执行将插件goal绑定在某个phase即可。
phase和goal可以这样理解:maven命令格式是mvn phase:goal,例如mvn package docker build。那么package docker都是phase,build则是goal。

            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <version>1.0.0</version>
                <executions>
                    <execution>
                        <id>build-image</id>
                        <phase>package</phase>
                        <goals>
                            <goal>build</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <imageName>example/microservice-discovery-eureka:0.0.1</imageName>
                    <dockerHost>http://192.168.2.120:2375</dockerHost>
                    <dockerDirectory>${project.basedir}/src/main/docker</dockerDirectory>
                    <resources>
                        <resource>
                            <targetPath>/</targetPath>
                            <directory>${project.build.directory}</directory>
                            <include>${project.build.finalName}.jar</include>
                        </resource>
                    </resources>
                </configuration>
            </plugin>

由配置可知,只需添加如下配置

                <executions>
                    <execution>
                        <id>build-image</id>
                        <phase>package</phase>
                        <goals>
                            <goal>build</goal>
                        </goals>
                    </execution>
                </executions>

就可将插件绑定在package这个phase上。

推送镜像

前文使用docker push命令实现了镜像的推送,也可使用Maven插件推送镜像。不妨使用Maven插件推送一个Docker镜像到Docker Hub。
1)修改Maven的全局配置文件settings.xml,在其中添加以下内容,配置Docker Hub的用户信息。

	<server>
      <id>docker-hub</id>
      <username>repouser</username>
      <password>repopwd</password>
	  <configuration>
	    <email>email</email>
	  </configuration>
    </server>

2)修改pom.xml

            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <version>1.0.0</version>
                <executions>
                    <execution>
                        <id>build-image</id>
                        <phase>package</phase>
                        <goals>
                            <goal>build</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <imageName>18332104715/microservice-discovery-eureka:0.0.1</imageName>
                    <dockerHost>http://192.168.2.120:2375</dockerHost>
                    <dockerDirectory>${project.basedir}/src/main/docker</dockerDirectory>
                    <resources>
                        <resource>
                            <targetPath>/</targetPath>
                            <directory>${project.build.directory}</directory>
                            <include>${project.build.finalName}.jar</include>
                        </resource>
                    </resources>
                    <serverId>docker-hub</serverId>
                </configuration>
            </plugin>

3)执行以下命令,添加pushImage的标识,表示推送镜像。

mvn clean package docker:build -DpushImage

在这里插入图片描述

在这里插入图片描述
同理,也可推送镜像到私有仓库,只需要将imageName指定成类似

<imageName>localhost:5000/microservice-discovery-eureka:0.0.1</imageName>

注:以上实例是通过imageName指定镜像名称和标签的

<imageName>localhost:5000/microservice-discovery-eureka:0.0.1</imageName>

也可借助imageTags元素更为灵活地指定镜像名称和标签

<configuration>
	<imageName>example/microservice-discovery-eureka</imageName>
	<imageTags>
		<imageTag>0.0.5</imageTag>
		<imageTag>latest</imageTag>
	</imageTags>
</configuration>

这样就可为同一个镜像指定两个标签。
也可在构建命令时,使用dockerImageTags参数指定标签名称

mvn clean pachage docker:build -DpushImageTags -DdockerImageTags=latest -DdockerImageTags=another-tag

如需重复构建相同标签名称地镜像,可将forceTags设为true,这样就会覆盖构建相同标签的镜像。

<configuration>
	<forceTags>true</forceTags>
</configuration>

Spotify是全球最大的正版流媒体音乐服务平台。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值