Docker支持:三分钟教你学会创建具有微服务的Docker镜像
lipiwang 2024-10-15 18:38 15 浏览 0 评论
创建具有微服务的Docker镜像
前文已经讨论了可用于运行、创建和管理容器的基本Docker命令。现在是时候创建和构建我们的第一个Docker镜像,以启动我们之前介绍的示例微服务。为此,开发人员应该回到地址htps:/ithb.co/piomi/saompl spring -cloud. comm.git.上的存储库,然后切换到feign. with. _discovery 分支( htpgithub.com/piomin/samople-spring cloud .comm/tee/feign_ with. discovery) 。在该地址上,开发人员将找到每个微服务、网关和发现的Dockerfile。
在讨论这些示例之前,开发人员应该参考Dockerfile的一些资料来理解其基本命令。实际上,Dockerfile 并不是构建Docker镜像的唯一方法, 之前的文章中还将演示如何使用Maven插件创建具有微服务的镜像。
Dockerfile
Docker可以通过读取Dockerfile中提供的指令自动构建镜像, Dockerfile是一个文档,其中包含在命令行上调用以组成镜像的所有命令。所有这些命令都必须以Dockerfile规范中定义的关键字开头。以下是最常用指令的列表,它们按照在Dockerfile中找到它们的顺序执行。在表14.1中,我们还可以附加一些注释,这些注释的后面必须跟着#字符。
现在来看一看它在实践中是如何运作的。我们应该为每个微服务定义一个Dockerfile,并将其放在Git项目的根目录中。以下是为account-service服务创建的Dockerfile.
FROM openjdk:8u151-jdk-slim-stretch
MAINTAINER Piotr Minkowski <piotr .minkows ki@gmail. com>
ENV SPRING PROFILES ACTIVE zonel
ENV EUREKA DEFAULT ZONE http://localhost:8761/eureka/
ADD target/account -service-1.0-SNAPSHOT.jar app.jar
ENTRYPOINT ["java", "-Xmx160m", "-jar",
"-Dspring.profiles .active-s (SPRING PROFILES ACTIVE}",
"-Deureka.client .serviceUrl. defaultZone-$ { EUREKA DEFAULT ZONE}",
"/app.jar"]
EXPOSE 8091
前面的例子并不复杂。它只将由微服务生成的胖JAR文件添加到Docker容器中,并使用java -jar命令作为ENTRYPOINT。为了更好地理解它,下 文将逐步进行分析。我们的示例Dockerfile将执行以下指令。
口 该镜像扩展了现有的OpenJDK镜像,该镜像是Java平台标准版(Java Platform Standard Edition) 的官方开源实现。OpenJDK镜像有很多种,可用镜像变体之间的主要区别在于它们的大小。标记为8ul51-jdk-slim-stretch 的镜像提供了JDK8,并包含运行Spring Boot微服务所需的所有库。它也比8u151-jdk 版本Java的基本镜像小得多。
口 在这里,我们使用dockerrun命令的-e选项定义了两个可以在运行时覆盖的环境变量。第一个是活动的Spring配置文件名称,默认情况下它将使用zonel值初始化。第二个是发现服务器的地址,默认情况下等于ht://ocalhost:/761/eureka/。
口 胖JAR文件包含所有必需的依赖项以及应用程序的二进制文件。因此,我们必须使用ADD指令将已生成的JAR文件放入容器中。
口 我们将容器配置为可执行Java应用程序。定义的ENTRYPOINT相当于在本地计算机上运行以下命令。
java -Xmx160m -jar -Dspring.profiles.active = zone1-
Deureka . client. serviceUrl. defaultZone = http: //localhost: 8761/eureka/
apP. jar
口 使用EXPOSE指令,我们告知Docker它可能会公开应用程序的HTTPAPI,该API在端口8091上的容器内可用。
运行容器化微服务
假设我们为每个服务准备了一个有效的Dockerfile, 下一步是使用mvn clean install命令构建整个Maven项目,然后为每个服务构建一个Docker镜像。
构建Docker镜像时,应始终位于每个微服务源代码的root目录中。在基于微服务的系统中运行的第一个容 器必须是发现服务器。其Docker镜像已被命名为piomin/discovery-service。在运行Docker的build命令之前,应转到模块discovery-service。这个Dockerfile比其他微服务稍微简单- - 些,因为在容器内没有设置环境变量,如下所示。
FROM openjdk:8u151-jdk-slim-stretch
MAINTAINER Piotr Minkowski <piotr . minkowski@gmail. com>
ADD target/discovery-service-1.0-SNAPSHOT.jar app.jar
ENTRYPOINT ["java", "-Xmx144m", "-jar", "/app.jar"]
EXPOSE 8761
这里仅执行5个步骤,可以在运行dockerbuild命令之后在目标镜像构建期间生成的日志中看到这些步骤。如果一切正常,开发人员应该看到在Dockerfile中定义的所有5个步骤的进度以及以下最终消息,这些消息告诉开发人员镜像已成功构建和标记。
$ docker build -七piomin/discovery-service:1.0.
Sending build context to Docker daemon 39 。9MB
Step 1/5 : FROM openjdk : 8u151- jdk-slim-stretch
8u151-jdk-slim-stretch: Pulling from library/openjdk
8176e34d5d92: Pull complete
2208661344b7: Pull complete
99f2896660b2: Pull complete
e991b55a8065: Pull complete
aee568884a84: Pull complete
18b6b371c215: Pull complete
Digest:
sha256 :bd394fdc7 6e8aa73adba2a7547fcb6cde3281 f70d6b3cae6fa62ef1 fbde327e3
Status: Downloaded newer image for openjdk: 8u151 -jdk-slim-stretch
---> 52de5d98a41d
Step 2/5 : MAINTAINER Piotr Minkowski <piotr . minkowskiegmail. com>
---> Running in 78fc78cc21f0
---> 0eba7a369e43
Removing intermediate container 78fc78cc21£0
Step 3/5 : ADD target/di scovery- service-1.0- SNAPSHOT. jar app. jar
---> 1c6a2e04c4dc
Removing intermediate container 98138425b5a0
Step 4/5 : ENTRYPOINT java -Xmx144m -jar /app . jar
---> Running in 7369ba693689
---> c24 6470366e4
Removing intermediate container 7369ba693689
Step 5/5 : EXPOSE 8761
---> Running in 74493ae54220
---> 06af6a3c2d41
Removing intermediate container 74493ae54220
Successfully built 06af6a3c2d41
Successfully tagged piomin/discovery- service:1.0
如果成功构建了一个镜像,则应该运行它。我们建议创建一个网络,其中将启动包含微服务的所有容器。要在新创建的网络中启动容器,必须使用--network 参数将其名称传递给docker run命令。要检查容器是否已成功启动,可以运行docker logs命令。此命令将应用程序记录的所有行打印到控制台,如下所示。
$ docker network create sample- spring-cloud network
$ docker run -d --name discovery -P 8761:8761 --network samp1e- spring-
cloud-network piomin/discovery-service:1. 0
de2 fac673806e134faedee3c0addaa31 f2bbadef fbdff42a53f8e4ee44ca0674
$ docker logs -f discovery
下一步是使用我们的4个微服务——account-service 服务、customer-service 服务、order-service服务和product-service服务来构建和运行容器。每个服务的过程都是相同的。例如,如果想要构建account-service 服务,则首先需要转到示例项目源代码的该目录中。这里的build命令与发现服务的命令相同,唯一的区别在于镜像名称,如下面的代码段所示。
$ docker build -t piomin/ account-service:1.0
运行Docker镜像的命令对于discovery-service来说有点复杂。在这种情况下,必须将Eureka服务器的地址传递给起始容器。由于此容器与发现服务容器在同一网络中运行,因此,开发人员可以使用其名称而不是其IP地址或任何其他标识符。或者,也可以使用-m参数设置容器的内存限制,如设置为256MB。最后,还可以使用docker logs命令查看运行在容器上的应用程序生成的日志,如下所示。
$ docker run -d --name account -P 8091:8091 -e
EUREKA DEFAULT ZONE http://discovery:8761/eureka -m 256M - - network
sample- spring-cloud network piomin/account- service:1.0
$ docker logs -f account
对于所有其他微服务,应该重复与前面描述相同的步骤。最终结果是5个正在运行的容器,这可以使用dockerps命令显示,如图14.4所示。
所有微服务都在Eureka服务器中注册。Eureka仪表板的地址为htp://92.1/8.99.100:8761/,如图14.5所示。
在这里有我们提到过的另一个有趣的Docker命令: docker stats。此命令打印一些与已启动容器相关的统计信息,如内存或CPU使用情况。如果使用该命令的-format参数,则可以自定义打印统计信息的方式。例如,可以打印容器名称而不是其ID.在运行该命令之前,可以执行一些测试,以检查-切是否正常 工作。开发人员可以注意检查在容器上启动的微服务之间的通信是否已成功完成。此外,如果想要尝试调用customer service服务的端点GET /withAccounts/{id} (它将调用account-service服务公开的端点),则可以运行以下命令。
docker stats -- format "table
{ { .Name}}\t { {. Container} }\tl{. CPUPerc} }\t{ {.MemUsage} }"
如图14.6所示的是docker stats命令的打印结果。
使用Maven插件构建镜像
如前文所述,Dockerfile 不是创建和构建容器的唯一方法, 还有一些其他方法可用,如使用Maven插件。我们有许多可用于构建镜像的插件,它们与mvn命令一起使用。其中一个比较受欢迎的是com. sotify:docker-Maven-plugin插件。它在配置中具有等效标记,可用于代替Dockerfile指令。pom.xml 文件中用于account- service服务的插件配置如下。
<plugin>
<groupId>com . spotify</groupId>
<artifactId>docker -maven-plugin</artifactId>
<version>1.0.0</version>
<configuration>
<imageName>piomin/$ {project . artifactId}</ imageName >
<imageTags>$lproject. version}</ imageTags>
<base Image>openjdk:8u151 -jdk-slim-stretch</base Image>
<entryPoint> ["java", "-Xmx160m", "-jar" ,
"- Dspring.profiles.active=${SPRING PROFILES ACTIVE}",
“一Deureka. client. serviceUrl. defaultZone=$ EUREKA_ DEFAULT ZONE}",
"/$ (project . build. finalName}.jar"] </entryPoint>
<env>
<SPRING PROFILES ACTIVE>zone1</SPRING PROFILES ACTIVE>
<EUREKA DEFAULT ZONE>http://localhost :8761/eureka/</EUREKA DEFAULT ZONE>
</env>
<exposes>8091</exposes>
<maintainer>piotr .minkowskiegmail. com</maintainer>
<dockerHost>https://192.168.99. 100:2376</dockerHost>
<dockerCe rtPath>C: \Users\Piotr \. docker \machine Amachines default
</docker CertPath>
<resources>
<resource>
<directory>${project . build.directory}</directory>
<include>$ {project。build. finalName}。jar</ include>
</ resource>
</ resources>
</ configuration>
</plugin>
可以在Maven的build命令期间调用此插件。如果想要在构建应用程序之后构建Docker镜像,可以使用以下Maven命令。
$ mvn clean install docker: build
或者,开发人员也可以设置dockerDirectory标记,以便基于Dockerfile 执行构建。无论选择哪种方法,效果都是一样的。使用应用程序构建的任何新镜像都可以在Docker机器上使用。使用docker-maven-plugin时,可以通过将pushlmage设置为true来强制自动将镜像推送到存储库,如下所示。
<plugin>
<groupId>com. spotify</groupId>
<arti factId>docker -maven-plugin</artifactId>
<version>1.0.0</version>
<configuration>
<imageName>piomin/S (project.artifactId}</ imageName>
<imageTags>$ {project.version}</ imageTags>
<pushImage>true</pushImage>
<dockerDirectory>src/main/ docker</ dockerDirectory>
<dockerHost>https://192.168.99.100:2376</dockerHost>
<dockerCertPath>C: \Users\Piotr \. docker machine \machines \default
</docker CertPath>
<resources>
<resource>
<directory>$ project.build.directory}</directory>
<include>S {project .build. finalName}. jar</include>
</resource>
</ resources>
</configuration>
</plugin>
高级Docker镜像
到目前为止,我们已经构建了相当简单的Docker镜像。但是,有时需要创建更高级的镜像,我们需要这样的镜像用于持续交付(Continuous Delivery) 演示。这个Docker镜像将作为Jenkins从属(Slave) 服务器运行,并将连接到Jenkins主(Master)服务器,作为Docker容器启动。我们还没有在Docker Hub上找到这样的镜像,所以我们自己创建了一个。
在这里,镜像必须包含Git. Maven、 JDK8和Docker.这些是使用Jenkins从属服务器构建示例微服务所需的所有工具。我们将在本章的后面部分简要介绍使用Jenkins服务器进行持续交付的基本知识。目前,我们将专注于构建所需的镜像。以下是Dockerfile中提供的镜像的完整定义。
FROM docker:18-dind
MAINTAINER Piotr Minkowski <piotr .minkowski@gmail. com>
ENV JENKINS MASTER http:/ /localhost: 8080
ENV JENKINS_ SLAVE NAME dind- node
ENV JENKINS_ SLAVE SECRET
ENV JENKINS HOME /home/jenkins
ENV JENKINS_ REMOTING VERSION 3.17
ENV DOCKER HOST tcp://0.0.0.0:2375
RUN apk - - update add cur1 tar git bash openjdkB sudo
ARG MAVEN VERSION-3.5.2
ARG USER HOME DIR="/root"
ARG
SHA=707b1 f 6e390a 65bde4 af4cdaf2a24d45fc1 9a6ded00fff02e9162 6e3e42ceaff
ARG
BASE URL-https://apache 。osuosl . org/ maven/maven- 3/$ (MAVEN VERSION}/binaries
RUN mkdir -p /usr/share/maven /usr/share/maven/ref \
&& curl -fsSL -0 /tmp/apache -maven.tar.gz $ (BASE URL}/ apache-maven-
$ (MAVEN VERSION}-bin.tar.gz \
&& echo "S{SHA) /tmp/apache -maven. tar.gz" 1 sha256sum -C一
&& tar -xzf /tmp/apache-maven.tar.gz -C /usr/share/maven --strip-
components=l
&& rm -f /tmp/apache -maven. tar.gz \
&& 1n -S /usr/share/maven/bin/mvn /usr/bin/mvn
ENV MAVEN HOME /usr/share/maven
ENV MAVEN CONFIG "SUSER HOME DIR/ . m2"
RUN adduser -D -h SJENKINS_ HOME -s /bin/sh jenkins jenkins && chmod
a+rwx SJENKINS_ HOME
RUN echo "jenkins ALL= (ALL) NOPASSWD: /usr/ local/bin/dockerd" >
/etc/sudoers.d/00jenkins && chmod 440 /etc/sudoers.d/00jenkins
RUN echo "jenkins ALL- (ALL) NOPASSWD: /usr/1ocal/bin/docker" >
/etc/sudoers.d/01jenkins && chmod 440 /etc/sudoers .d/01jenkins
RUN curl --create-dirs -sSLo /usr/share/jenkins/slave.jarhttp://repo . jenkins-ci . org/public/org/jenkins-ci/main/ remot ing/SJENKINS
REMOTING VERSION/ remoting- SJENKINS_ REMOTING VERSION.jar 5& chmod 755
/usr/share/jenkins G& chmod 644 /usr/share/jenkins/slave.jar
COPY entrypoint.sh /usr/loca1/bin/entrypoint
VOLUME $JENKINS HOME
WORKDIR SJENKINS HOME
USER jenkins
ENTRYPOINT ["/usr/1ocal/bin/entrypoint"]
现在我们来分析一下发生了什么。在这里,我们扩展了Docker基础镜像。这是一个非常聪明的解决方案,因为该镜像现在已经在Docker中提供了Docker. 虽然通常不建议在Docker中运行Docker,但是也有一些理想的用例,例如,使用Docker 进行持续交付。除了Docker之外,还使用RUN指令在镜像上安装其他软件,如Git、JDK、Maven或Curl。
我们还添加了一个操作系统用户,它在dockerd脚本中具有sudoers 权限,该脚本负责在机器上运行Docker守护程序。这不是必须在正在运行的容器中启动的唯一进程,还需要使用Jenkins从属服务器启动JAR。这两个命令在entrypoint.sh中执行,它被设置为镜像的ENTRYPOINT。有关此Docker镜像的完整源代码,请访问GitHub,其网址为htpt:/github. com/piomin/jenkins. slave- dind-jnlpgi.开发人员不必从源代码构建它,只需使用以下命令从笔者的Docker Hub账户下载已准备好的镜像。
docker pull piomin / jenkins-slave-dind-inlp
以下是Docker镜像中的脚本entrypoint.sh,它启动了Docker守护进程和Jenkins 从属服务器。
#! /bin/sh
set -e
echo "starting dockerd. . .
sudo dockerd --host=unix:///var/ run/docker.sock --
host=tcp://0.0.0.0:2375 --storage-driver =vfs &
echo "starting jnlp slave.. .”
exec java -jar /usr/share/jenkins/slave.jar \
-jnlpUrl $JENKINS URI/ computer/SJENKINS SLAVE NAME/slave-agent . jnlp \
-secret $JENKINS SIAVE SECRET
本文给大家讲解的内容是创建具有微服务的Docker镜像
1.下篇文章给大家讲解的是微服务的架构的关键优势——持续交付;
2.觉得文章不错的朋友可以转发此文关注小编,有需要的可以私信小编获取资料;
3.感谢大家的支持!
相关推荐
- Go语言图书管理RESTful API开发实战
-
Go(Golang)是最近流行起来,且相对较新的编程语言。它小而稳定,使用和学习简单,速度快,经过编译(原生代码),并大量用于云工具和服务(Docker、Kubernetes...)。考虑到它所带来的...
- 轻松搞定Golang 中的内存管理(golang设置内存大小)
-
除非您正在对服务进行原型设计,否则您可能会关心应用程序的内存使用情况。内存占用更小,基础设施成本降低,扩展变得更容易/延迟。尽管Go以不消耗大量内存而闻名,但仍有一些方法可以进一步减少消耗。其中一...
- golang实现deepseek 聊天功能(golang deepcopy)
-
在搭建完deepseek环境后在docker内部署deepseekrag环境,我们可以用golang实现聊天功能。在实现这个功能之前,我们先了解下提示词工程(prompt)。大模型虽然知道的东西多...
- golang slice的扩容机制(golang设置内存大小)
-
在Go语言中,切片(slice)是一种动态数组,其长度可以在运行时改变。当向切片中添加元素时,如果切片的容量不足以容纳新元素,就会触发扩容机制。下面详细介绍Go语言切片的扩容机制。扩容触发条件...
- Etcd服务注册与发现封装实现--golang
-
服务注册register.gopackageregisterimport("fmt""time"etcd3"github.com/cor...
- 嘿,轻松获取区间内所有日期的Golang小技巧!
-
在Go语言中,获取两个日期之间的所有日期可以手动实现一个函数来完成。以下是一个示例函数,它会返回一个日期切片,包含从开始日期到结束日期(包括这两个日期)的所有日期:packagemainimpo...
- 仓颉、Java、Golang性能测试——数组扩容
-
版本信息仓颉版本0.53.18Golang版本1.22.8Java版本corretto-1.8.0_452源码仓颉packagecangjie_testimportstd.collect...
- Golang 58个坑 – 中级篇:36-51(golang cef)
-
36.关闭HTTP的响应体37.关闭HTTP连接38.将JSON中的数字解码为interface类型39.struct、array、slice和map的值比较40.从panic...
- 一篇文章学会golang语法,golang简明教程快速入门
-
Go(又称Golang)是Google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言。——Go-wikipedia.org1Go安装最新版本下载地址官方下载https...
- 运维大神如何使用 Golang 日志监控应用程序
-
你是如何使用Golang日志监控你的应用程序的呢?Golang没有异常,只有错误。因此你的第一印象可能就是开发Golang日志策略并不是一件简单的事情。不支持异常事实上并不是什么问题,异常在...
- Golang操作elasticsearch(golang操作word)
-
简介开源的Elasticsearch是目前全文搜索引擎的首选,很多日志都是放到elasticsearch里面,然后再根据具体的需求进行分析。目前我们的运维系统是使用golang开发的,需要定时到e...
- 一文带你看懂Golang最新特性(golang x)
-
作者:腾讯PCG代码委员会经过十余年的迭代,Go语言逐渐成为云计算时代主流的编程语言。下到云计算基础设施,上到微服务,越来越多的流行产品使用Go语言编写。可见其影响力已经非常强大。一、Go语言发展历史...
- Golang 最常用函数(备用查询)(golang函数和方法)
-
hello.gopackagemainimport"fmt"funcmain(){fmt.Println("Hello,world!")}直...
- Golang:将日志以Json格式输出到Kafka
-
在上一篇文章中我实现了一个支持Debug、Info、Error等多个级别的日志库,并将日志写到了磁盘文件中,代码比较简单,适合练手。有兴趣的可以通过这个链接前往:https://github.com/...
- 如何从 PHP 过渡到 Golang?(php转go需要多久)
-
我是PHP开发者,转Go两个月了吧,记录一下使用Golang怎么一步步开发新项目。本着有坑填坑,有错改错的宗旨,从零开始,开始学习。因为我司没有专门的Golang大牛,所以我也只能一步步自己去...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- maven镜像 (69)
- undefined reference to (60)
- zip格式 (63)
- oracle over (62)
- date_format函数用法 (67)
- 在线代理服务器 (60)
- shell 字符串比较 (74)
- x509证书 (61)
- localhost (65)
- java.awt.headless (66)
- syn_sent (64)
- settings.xml (59)
- 弹出窗口 (56)
- applicationcontextaware (72)
- my.cnf (73)
- httpsession (62)
- pkcs7 (62)
- session cookie (63)
- java 生成uuid (58)
- could not initialize class (58)
- beanpropertyrowmapper (58)
- word空格下划线不显示 (73)
- jar文件 (60)
- jsp内置对象 (58)
- makefile编写规则 (58)