将微服务运行在docker上(代码片段)

shi_zi_183 shi_zi_183     2023-01-31     419

关键词:

将微服务运行在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是全球最大的正版流媒体音乐服务平台。

docker的一些常用命令(代码片段)

 Docker采用的是Client/Server架构。客户端向服务器发送请求,服务器负责构建、运行和分发容器。客户端和服务器可以运行在同一个Host上,客户端也可以通过socket或RESTAPI与远程的服务器通信。Dockerdaemon运行在Dockerhost上,负责... 查看详情

dockergetstartediv(代码片段)

...一个应用以及如何运行在生产环境中,然后将它变为一个服务,在同一个进程中将服务能力伸缩到原来的5倍。在本部分,你将在集群上部署一个应用,运行在多台机器上。通过将多个机器加入到docker化的集群中,多容器多机器... 查看详情

docker学习1-centos7安装docker环境(代码片段)

...机器上运行多个Docker微容器,而每个微容器里都有一个微服务或独立应用,例如你可以将Tomcat运行在一个Docker,而MySQL运行在另外一个Docker,两者可以运行在同一个服务器,或多个服务器上。未来可能每个应用都要Docker化环境准... 查看详情

docker理论基础(代码片段)

...常使用Linux或者macOS时,我们并没有运行多个完全分离的服务器的需要,但是如果我们在服务器上启动了多个服务,这些服务其实会相互影响的,每一个服务都能看到其他服务的进程,也可以访问宿主机器上的任意文件,这是很... 查看详情

docker开启远程连接(代码片段)

注意,端口不要写2375,这是默认端口,要是开了,服务器上的docker会被别人恶意连接,运行挖矿服务。1、编辑vim/usr/lib/systemd/system/docker.service2、添加#在ExecStart添加-Htcp://0.0.0.0:2355-Hunix:///var/run/docker.sock注意,端口不要写2375,这... 查看详情

我们可以在多台机器(主机)上运行单个容器吗?(代码片段)

...中查看了有关多主机设施的一些文档,例如:Docker群Docker服务(带副本)而且我也知道群集模式中的volume问题,容器的最大资源(RAM和CPU)限制会有所不同,取决于swarmmanager分配的位置(在什么机器上)。所以这里我的问题是,... 查看详情

分享在mpsoczcu106单板上运行docker(代码片段)

在MPSoC单板上运行Docker目录在MPSoC单板上运行Docker作者测试环境Linux内核配置Linux文件系统配置启动命令测试命令常见问题网络权限存储空间docker启动失败文件/var/run/docker.pid已经存在参考文档作者HankFU付汉杰hankf@xilinx.com测试环境Xi... 查看详情

docker(代码片段)

...693772.html  Docker采用的是Client/Server架构。客户端向服务器发送请求,服务器负责构建、运行和分发容器。客户端和服务器可以运行在同一个Host上,客户端也可以通过socket或RESTAPI与远程的服务器通信。 Dockerdaemon是服务... 查看详情

sh在gcp上运行docker上的tensorflowgpu(代码片段)

查看详情

docker概览(代码片段)

...元。准备就绪后,可以将应用程序作为容器或精心安排的服务部署到生产环境。无论您的生产环境是本地数据中心、云提供商还是两者的混合,都是一样的。Docker引擎Docker引擎是客户端-服务器应用程序,具有以下主要组件:服... 查看详情

docker——核心实现技术(代码片段)

...一、基本架构 Docker目前采用了标准的C/S架构。 客户端和服务端既可以在同一台机器上,也可以运行在不同机器上通过socket或RESTfulAPI来进行通讯。1.服务端 DockerDaemon一般在宿主主机后台运行,作为服务端接收来自客户的请求,并... 查看详情

sh在docker上运行openvpn容器,并创建用户(代码片段)

查看详情

docker私有镜像服务器搭建(代码片段)

1.准备一台服务器A(已安装docker,IP:192.168.39.111)2.在服务器A上通过运行registry容器进行搭建dockerrun-itd-v/my_registry:/var/lib/registry-p5000:5000--restart=always--nameregistryregistry:latest参数说明-itd:在容器中打开一个伪终端进行交互操作,并... 查看详情

pycharm如何远程连接服务器上的docker容器(代码片段)

...束语前言  在上篇博客已经介绍了pycharm如何远程连接服务器,本篇文章介绍一下pycharm如何远程连接服务器上的docker容器,并在本地完成代码的运行与调试。  所需软硬件环境:环境版本localsystemwindows10servicesystemu... 查看详情

pycharm如何远程连接服务器上的docker容器(代码片段)

...束语前言  在上篇博客已经介绍了pycharm如何远程连接服务器,本篇文章介绍一下pycharm如何远程连接服务器上的docker容器,并在本地完成代码的运行与调试。  所需软硬件环境:环境版本localsystemwindows10servicesystemu... 查看详情

dockermacos上安装docker(代码片段)

...se--versiondocker-composeversion1.24.1,build4667896b尝试运行一个Nginx服务器:dockerrun-d-p80:80--namewebservernginx服务运行后,可以访问http://localhost,如果看到了"Welcometonginx!",就说明DockerDesktopforMac安装成功了。  查看详情

docker简介与安装(代码片段)

...3DockerImage镜像4DockerContainer容器Docker架构Docker使用客户端--服务器(c/s)架构模式,使用远程API来管理和创建Docker容器。Docker容器通过Docker镜像来创建。容器与镜像的关系类似于面向对象编程中的对象与类Docker面向对象容器对象镜像... 查看详情

shmachinediskutil用于在virtualbox上运行的docker机器内安装/卸载外部卷(代码片段)

查看详情