29

使用Jib快速简便地创建Docker镜像

 4 years ago
source link: http://dockone.io/article/9934
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

在本文中,我们将看看Jib,它是Google提供的一个工具,可以轻松快速地创建Docker镜像。无需创建Dockerfile文件,也无需安装Docker守护进程,Jib可直接使用。

  1. 简介

到目前为止,我们一直使用来自Spotify的 dockerfile-maven-plugin 来构建和推送Docker镜像。这要求我们根据 最佳实践 来编写Dockerfile,安装Docker守护进程并将插件添加到构建过程中。Jib将为我们提供一种更简便的方式来创建Docker镜像。我们只需要添加并配置Maven插件即可。当然,只有当我们自己亲自尝试了,我们才会相信它更轻便,这正是接下来要做的。

我们将创建一个简单的Spring Boot应用程序,使用 Jib Maven插件 将其容器化并将其推送到DockerHub。接着我们将拉取镜像并运行容器。这些资源可在 Github 获取。

我们正在使用:

  • Ubuntu 18.04
  • Spring Boot 2.2.1
  • Java 11
  • Jib Maven插件1.8.0
  • Docker Hub账号

有关Jib的更多信息请访问 Google Cloud Platform BlogGitHub

  1. 创建应用程序

第一步,我们将创建一个简单的Spring Boot应用程序。我们将Spring Actuator和Spring Web MVC依赖项添加到pom文件中。 Spring Actuator 将为我们提供添加运行状况检查的方法。

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-actuator</artifactId>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</dependency>

我们的应用程序由一个Rest控制器组成,该控制器返回问候消息和机器地址。

@RestController

public class HelloController {

@RequestMapping("/hello")

public String hello() {

    StringBuilder message = new StringBuilder("Hello Jib Maven Plugin!");

    try {

        InetAddress ip = InetAddress.getLocalHost();

        message.append(" From host: " + ip);

    } catch (UnknownHostException e) {

        e.printStackTrace();

    }

    return message.toString();

}

}

在本地运行:

$ mvn spring-boot:run

成功启动之后,我们调用URL http//localhost8080/hello,它将返回以下消息:

Hello Jib Maven Plugin! From host: gunter-Latitude-5590/127.0.1.1
  1. 设置Jib和Docker Hub

在本节中,我们将添加Jib Maven插件,并确保成功连接到Docker Hub注册中心。要使其正常工作是相当困难的,主要是由于缺乏文档。Jib官方文档对安全身份验证方法相当模糊。大多数示例都包括向pom或Maven配置文件中添加纯文本凭证。但这不是我们想要的。我们想要一种通过Docker Credential Helper连接到Docker Hub的安全方法。

为了测试连接,我们将Jib Maven插件添加到pom中并对其进行配置,以便检索基础镜像和将该镜像推送到Docker Hub。

<plugin>

<groupId>com.google.cloud.tools</groupId>

<artifactId>jib-maven-plugin</artifactId>

<version>1.8.0</version>

<configuration>

<!-- openjdk:11.0.5-jre -->

<from>

  <image>openjdk:11.0.5-jre</image>

</from>

<to>

  <image>docker.io/${docker.image.prefix}/${project.artifactId}</image>

  <credHelper>pass</credHelper>

</to>

</configuration>

</plugin>

from 标签包含我们的基础镜像,就像Dockerfile中的 FROM 语句。 to 标签包含我们想要推送的镜像。 ${docker.image.prefix} 设置为 mydeveloperplanet (我们的Docker Hub账号),你需要对应修改为你自己的账号。 ${project.artifactId} 包含 1.0-SNAPSHOT 版本。为了使用Credential Helper,我们将标签 credHelper 设置为 pass

在开始之前,如果你尚未设置GPG密钥,则需要设置它,请参阅 Ubuntu帮助页面

$ gpg --gen-key

为方便使用,你可以将生成的密钥作为环境变量添加到配置文件中。将以下行添加到你的 .profile 文件中,注意替换 Your_GPG_Key 内容。

export GPGKEY=Your_GPG_Key

执行source以使环境变量生效。

$ source .profile

你也可以选择将你的密钥发送到Ubuntu密钥服务器,但不是必要的。

$ gpg --send-keys --keyserver keyserver.ubuntu.com $GPGKEY

安装 pass 并使用你的GPG密钥初始化密码存储。

$ sudo apt install pass

$ pass init Your_GPG_Key

mkdir: created directory '/home/gunter/.password-store/'

Password store initialized for My Password Storage Key

接下来要做的是下载并解压缩Docker Credential Helper,并赋予可执行权限。

$ wget https://github.com/docker/docker-credential-helpers/releases/download/v0.6.3/docker-credential-pass-v0.6.3-amd64.tar.gz

$ tar xvzf docker-credential-pass-v0.6.3-amd64.tar.gz

$ mv docker-credential-pass /usr/bin

$ chmod +x docker-credential-pass

Docker Credential Helper需要正确配置,而这部分文档是缺失的。

创建包含以下内容的 config.json 文件。在文档中说明要添加内容 { &quot;credStore&quot;: &quot;pass&quot; } ,但是使用此配置,Jib将无法连接到Docker Hub注册表。我们发现该Issue中提及到 credStore 已不再支持Google Cloud Registry。

"credHelpers": {

"https://index.docker.io/v1": "pass"

}

初始化Docker Credential Helper。当pass初始化并要求输入密码时输入密码。

$ pass insert docker-credential-helpers/docker-pass-initialized-check

mkdir: created directory '/home/gunter/.password-store/docker-credential-helpers'

Enter password for docker-credential-helpers/docker-pass-initialized-check:

Retype password for docker-credential-helpers/docker-pass-initialized-check:

检查密码设置是否正确:

$ pass show docker-credential-helpers/docker-pass-initialized-check

pass is initialized

使用你的Docker凭证登陆。这里会出现警告提示你的密码以非加密方式保存在 config.json 文件中。不清楚为何会出现该提示,因为凭证已经是以加密形式保存在 config.json 中。

$ docker login

Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.

Username: your_user_name

Password: 

WARNING! Your password will be stored unencrypted in /home/gunter/.docker/config.json.

Configure a credential helper to remove this warning. See

https://docs.docker.com/engine/reference/commandline/login/#credentials-store



Login Succeeded

从现在开始, docker login 无需输入凭证即可执行。

$ docker login

Authenticating with existing credentials...

WARNING! Your password will be stored unencrypted in /home/gunter/.docker/config.json.

Configure a credential helper to remove this warning. See

https://docs.docker.com/engine/reference/commandline/login/#credentials-store



Login Succeeded

你可以使用 docker logout 再次注销

$ docker logout

Removing login credentials for https://index.docker.io/v1/

确保你已再次登陆,然后运行Maven Jib构建命令:

$ mvn compile jib:build

镜像会成功被构建并推送到Docker Hub。构建过程中将引发两个警告:

Base image 'openjdk:11.0.5-jre' does not use a specific image digest - build may not be reproducible

这可以通过替换基础镜像 openjdk:11.0.5-jreopenjdk@sha256:b3e19d27caa8249aad6f90c6e987943d03e915bbf3a66bc1b7f994a4fed668f6 (sha256格式)值来轻松解决。

The credential helper (docker-credential-pass) has nothing for server URL: https://index.docker.io/v1

这是一个奇怪的警告,因为此URL的凭据已解析并用于推送镜像。

  1. 为我们的应用程序配置Jib

现在我们已经以安全的方式配置了身份认证,我们可以继续为应用程序配置Jib Maven插件。我们在镜像中添加标签并指定主类。

<to>

<image>docker.io/${docker.image.prefix}/${project.artifactId}</image>

<credHelper>pass</credHelper>

<tags>

<tag>${project.version}</tag>

</tags>

</to>

<container>

<mainClass>com.mydeveloperplanet.myjibplanet.MyJibPlanetApplication</mainClass>

</container>

不要将标签 format 和OCI值添加到容器配置中。Docker Hub尚未完全支持OCI,将会显示 An error occurred while loading the tags. Try reloading the page 错误信息。

再次构建镜像并拉取Docker镜像:

$ docker pull mydeveloperplanet/myjibplanet

Using default tag: latest

latest: Pulling from mydeveloperplanet/myjibplanet

844c33c7e6ea: Pull complete 

ada5d61ae65d: Pull complete 

f8427fdf4292: Pull complete 

a5217f27a28f: Pull complete 

176e83ebae4f: Pull complete 

800204250483: Pull complete 

492e142ab90b: Pull complete 

7c8e6198cd4b: Pull complete 

c49bb7f02774: Pull complete 

Digest: sha256:b7144bfdf6ee47d6b38914a84789ef9f7e2117320080b28ce39c385ee399a0c8

Status: Downloaded newer image for mydeveloperplanet/myjibplanet:latest

docker.io/mydeveloperplanet/myjibplanet:latest

运行该镜像并映射8080端口:

$ docker run -p 127.0.0.1:8080:8080/tcp mydeveloperplanet/myjibplanet

...

2019-12-25 09:57:13.196 INFO 1 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'

2019-12-25 09:57:13.205 INFO 1 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 9 ms

查看Docker容器列表:

$ docker ps

CONTAINER ID    IMAGE                           COMMAND                  CREATED                 STATUS           PORTS                      NAMES

c05e431b0bd1    mydeveloperplanet/myjibplanet   "java -cp /app/resou…"   13 seconds ago    Up 12 seconds    127.0.0.1:8080->8080/tcp   recursing_meninsky

我们只需要检索Docker容器的IP地址。

$ docker inspect c05e431b0bd1

...

"NetworkSettings": {

...

"IPAddress": "172.17.0.2",

...

}

...

现在可以使用 http://172.17.0.2:8080/hello 调用我们应用程序的URL 。

这将向我们返回欢迎信息:

Hello Jib Maven Plugin! From host: c05e431b0bd1/172.17.0.2

我们还有一个问题要解决:我们的应用程序在Docker容器中以root用户运行。由于安全性原因,这不是我们想要的。首先,我们将检查Docker容器中有哪些用户可用:

$ docker exec -it -u root c05e431b0bd1 cat /etc/passwd

...

nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin

...

可发现该Docker容器包含了一个 nobody 用户,我们可以用它来运行应用程序。添加 user 标签到pom文件中:

<container>

<mainClass>com.mydeveloperplanet.myjibplanet.MyJibPlanetApplication</mainClass>

<user>nobody</user>

</container>

再次构建镜像,拉取并运行它。使用 docker inspect 检验是否是使用 nobody 作为用户。

...

"Config": {

"Hostname": "76b3afaca3af",

"Domainname": "",

"User": "nobody",

...

}

...

在pom中,我们还添加了Spring Actuator。没有方法通过Jib添加Docker运行状态检查,必须通过在Kubernetes配置中的存活探针和就绪探针来解决,另请参阅此 issue

  1. 结论

我们尝试了使用Jib Maven插件来创建我们的Docker镜像。为Docker Hub注册表配置凭据非常困难,但是一旦设置好了,这个插件就非常容易使用了。除此之外,不需要Docker守护进程,也不需要编写单独的Dockerfile。最后不能不提的是,它确实非常快。我们肯定会在不久的将来使用这个插件。

相关链接:

- Docker镜像和容器

- 使用Docker和Jib容器化Spring Boot应用程序

【原文链接】: Create Fast and Easy Docker Images With Jib 翻译:冯旭松


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK