存储器映像
在本系列的前两篇文章中,我们探讨了Source To Image(S2I)系统的一般要求,并准备了专门用于Go(Golang)应用程序的环境。 现在让我们旋转一下。
建立建造者形象
一旦Dockerfile和Source-to-Image(S2I)脚本准备就绪,就可以使用docker build命令创建Golang构建器映像:
docker build -t golang-builder .
这将在当前目录的上下文中生成一个名为golang-builder的生成器映像。
构建应用程序映像
没有要构建的应用程序,golang-builder映像用处不大。 对于本练习,我们将构建一个简单的hello-world应用程序。
GoHelloWorld
让我们来看看我们的测试应用程序GoHelloWorld 。 如果要继续 ,请下载最新版本的Go 。 此存储库中有两个重要的(对于本练习而言)文件:
// goHelloWorld.go
package main
import
"fmt"
func main
()
{
fmt
. Println
(
"Hello World!"
)
}
这是一个非常基本的应用程序,但是可以很好地测试构建器图像。 我们还对GoHelloWorld进行了基本测试:
// goHelloWorld_test.go
package main
import
"testing"
func TestMain
( t
* testing
. T
)
{
t
. Log
(
"Hello World!"
)
}
构建应用程序映像
要构建应用程序映像,需要运行s2i build命令,并为包含要构建的代码(或。使用当前目录中的代码进行构建)的存储库的参数运行s2i build命令,使用的构建器映像的名称以及生成的应用程序映像的名称创造。
$ s2i build https: // github.com / clcollins / goHelloWorld.git golang-builder go-hello-world
要从文件系统上的本地目录进行构建,请将Git URL替换为一个句点以表示当前目录。 例如:
$ s2i build . golang-builder go-hello-world
注意:如果在当前目录中初始化了Git存储库,则S2I将从存储库URL中获取代码,而不是使用本地代码。 这将导致在构建映像时不使用本地的,未提交的更改(如果您不熟悉“未提交的更改”的意思,请在此处重新使用Git术语 )。 不是Git初始化存储库的目录的行为符合预期。
运行应用程序映像
构建应用程序映像后,可以通过使用Docker命令运行它来对其进行测试。 从源到映像已用之前创建的运行脚本替换了映像中的CMD ,因此它将执行在构建过程中创建的/ go / src / app / app二进制文件:
$ docker run go-hello-world
Hello World
!
成功! 现在,我们在Docker映像中有了一个已编译的Go应用程序,该映像是通过将Git存储库的内容传递给S2I而创建的,而无需为我们的应用程序使用特殊的Dockerfile。
我们刚刚构建的应用程序映像不仅包括应用程序,还包括其源代码,测试代码,S2I脚本,Golang库以及许多Debian Linux发行版 (因为Golang映像基于Debian基础映像)。 结果图像不小:
$ docker images
|
grep go-hello-world
go-hello-world latest 75a70c79a12f
4 minutes ago
789 MB
对于使用在运行时解释并依赖于链接库(例如Ruby或Python)的语言编写的应用程序,必须具有所有源代码和操作系统才能运行。 结果,构建映像将非常大,但至少我们知道它将能够运行。 使用这些语言,我们可以在这里停止我们的S2I构建。
但是,可以选择更明确地定义应用程序的生产要求。
由于生成的应用程序映像与运行生产应用程序的映像相同,因此我想确保将所需的端口,卷和环境变量添加到构建器映像的Dockerfile中。 通过以声明的方式编写这些内容,我们的应用程序更接近于“ 十二要素”应用程序推荐的做法。 例如,如果要使用构建器映像为运行Puma的Ruby on Rails应用程序创建应用程序映像,则需要打开一个端口以访问Web服务器。 我们应该在构建器Dockerfile中添加PORT 3000行,以便它生成的所有图像都可以继承它。
但是对于Go应用程序,我们可以做得更好。
生成运行时映像
由于我们的构建器映像使用我们的应用程序创建了静态编译的Go二进制文件,因此我们可以创建最终的“运行时”映像,该映像仅包含二进制文件,而不包含其他任何废项。
一旦创建了应用程序映像,就可以使用save-artifacts脚本将已编译的GoHelloWorld应用程序提取并放入新的空白映像中。
运行时文件
仅需要应用程序二进制文件和Dockerfile即可创建运行时映像。
应用二进制
在应用程序映像内部,编写了save-artifacts脚本,以将应用程序二进制文件的tar存档流式传输到stdout。 我们可以使用tar的-vt标志来检查save-artifacts创建的tar归档文件中包含的文件:
$ docker run go-hello-world
/ usr
/ libexec
/ s2i
/ save-artifacts
|
tar
-tvf -
-rwxr-xr-x
1001
/ root
1997502
2019 -05-03
18 :
20 app
如果这导致沿“这似乎不是tar归档文件”的错误,则如上所述,save-artifacts脚本可能会输出除tar流之外的其他数据。 我们必须确保抑制除tar流之外的所有输出。
如果一切正常,我们可以使用save-artifacts将二进制文件复制到应用程序映像之外:
$ docker run go-hello-world / usr / libexec / s2i / save-artifacts | tar -xf -
这会将应用程序文件复制到当前目录,准备添加到其自己的映像中。
Docker文件
Dockerfile非常简单,只有三行。 FROM草稿源表示它使用一个空的空白父图像。 Dockerfile的其余部分指定将应用程序二进制文件复制到映像中的/ app中,并将该二进制文件用作映像ENTRYPOINT :
FROM scratch
COPY app
/ app
ENTRYPOINT
[
"/app"
]
将此Dockerfile保存为Dockerfile-runtime 。
为什么选择ENTRYPOINT而不选择CMD ? 我们可以执行任何操作,但是由于映像中没有其他内容(没有文件系统,没有shell),因此我们无论如何都无法运行其他任何东西。
构建运行时映像
准备好Dockerfile和二进制文件后,我们可以构建新的运行时映像:
$ docker build -f Dockerfile-runtime -t go-hello-world:slim .
新的运行时映像要小得多,只有2MB!
$ docker images
|
grep
-e
'go-hello-world *slim'
go-hello-world slim 4bd091c43816
3 minutes ago
2 MB
我们可以使用docker run来测试它是否仍然可以正常工作:
$ docker run go-hello-world:slim
Hello World
!
使用s2i create引导s2i
在此示例中,我们手工创建了所有S2I文件,但是s2i命令有一个子命令来帮助搭建从源到映像构建所需的所有文件: s2i create 。
使用s2i create命令,我们可以在./ghw2目录中生成一个新项目,创意名为go-hello-world-2 :
$ s2i create go-hello-world-
2 .
/ ghw2
$
ls .
/ ghw2
/
Dockerfile Makefile README.md s2i
test
create子命令创建一个占位符Dockerfile,一个README.md,其中包含有关如何使用Source-to-Image的信息,一些示例S2I脚本,一个基本的测试框架以及一个Makefile。 Makefile是自动构建和测试Source-to-Image生成器映像的好方法。 开箱即用,运行make将构建我们的图像,并且可以扩展它以执行更多操作。 例如,我们可以添加一些步骤来构建基本应用程序映像,运行测试或生成运行时Dockerfile。
结论
在本教程中,我们学习了如何使用Source-to-Image构建自定义的Golang构建器映像,如何使用s2i build创建应用程序映像,以及提取应用程序二进制文件以创建超薄运行时映像。
在本系列的后续扩展中,我想看看如何使用通过OKD创建的构建器映像来通过buildConfigs , imageStreams和deploymentConfigs自动部署Golang应用程序。 如果您对我继续本系列感兴趣,请在评论中让我知道,并感谢您的阅读。
翻译自: https://opensource.com/article/19/5/source-image-golang-part-3
存储器映像