使用Source-to-image(S2I)构建镜像

目录
  1. 创建你自己的S2I镜像
    1. 1. 创建s2i环境
    2. 2. 创建你的项目
    3. 3. 创建构建程序镜像
    4. 4. 构建应用程序镜像

作者:杨冬 欢迎转载,也请保留这段声明。谢谢!
出处:https://andyyoung01.github.io/http://andyyoung01.16mb.com/

我们可以通过Dockerfile来从头构建Docker镜像。然而,有其它选择来构建Docker镜像,使得对于Docker并不感兴趣的开发人员构建镜像更加方便,或者可以给构建过程提供更加强大的功能。使用Source-to-image(S2I)框架构建镜像便是其中的一种。

Source-to-image(S2I)是一种创建Docker镜像的架构,它可以通过将源代码放入一个单独定义的负责编译源代码的Docker镜像中,来将编译后的代码打包成docker镜像。
为什么会有这种构建方式呢?主要的原因是它允许应用程序开发人员对他们的代码进行更改,而不用知道Dockerfile或Docker镜像的细节。如果镜像交付给PaaS平台(application platform as a service),开发工程师并不需要理解Docker来对项目作出贡献。这在一个由很多人组成的企业环境中是非常有用的,这些人都有不同的专业方向,而且并不直接涉及到他们项目的构建过程。
下图显示了S2I的主要工作流程:
“S2I的工作流程”
一旦上述流程建立起来,为了将源代码扩展到不同的环境,开发工程师只需要关心他们想要的对自己源代码的修改。所有其它的事情都由s2i工具驱动。
上述方式的优点可以分为下面几个方面:

  • 灵活——此过程可以非常容易地插入到任何已经存在的软件交付流程中,并且它可以使用几乎任何的Docker镜像作为它的基础。
  • 快速——此种构建方式可以比基于Dockerfile的构建方式更加快速,因为任何数量的复杂操作可以添加进构建流程而不用在每个步骤都创建一个新的层。S2I也提供了在不同的构建过程中重用构件的能力,这可以节省时间。
  • 关注点分离——因为源代码和Docker镜像是清楚的分离开的,开发人员可以只关注代码,而基础设施人员可以关注Docker镜像和交付。因为代码和镜像是分离的,升级和修补更加容易交付。
  • 安全——此过程可以限制在构建过程中的操作是由某个用户执行的,而不像Dockerfile允许以root用户执行任意命令。

下面将展示如何使用这种方式进行代码的构建,虽然此处要构建的代码非常简单有限。此应用包括:

  • 源代码:只包含一行代码的shell脚本。
  • 构建程序s2i:它创建一个镜像,这个镜像包含上述代码,使其可执行,然后执行它。

创建你自己的S2I镜像

创建S2I镜像需要如下几步:

  1. 创建s2i环境,从github上下载安装s2i程序
  2. 创建你的项目。
  3. 创建构建程序镜像。
  4. 构建应用程序镜像。

一旦创建好了构建镜像,修改和重新构建就比较容易了。

1. 创建s2i环境

releases页面下载与你机器环境一致的版本,然后使用tar解压缩安装包:

$ tar -xvf release.tar.gz.

可以发现包中就是一个可执行文件s2i(还有一个sti的文件不再使用)。或者将s2i的位置加入到你的PATH环境变量,或者将其移动到已经在PATH中存在的目录中。这样就可以直接敲入s2i命令使用了。

2. 创建你的项目

选定一个目录,创建你自己的项目,可以是任何类型的项目。这里为了简单起见,在用户的家目录中新建myproject文件夹,作为项目的文件夹。然后在此文件夹下建立一个简单的脚本文件:

1
2
mkdir ~/myproject
cat > ~/myproject/app.sh <<< "echo 'Hello World!'"

3. 创建构建程序镜像

为了创建构建程序镜像,我们需要使用s2i create命令来为我们创建构建程序镜像的目录结构:

1
2
s2i create new-s2i-image new-s2i-image
cd new-s2i-image

s2i create命令后的第一个参数为构建程序镜像的名称,第二个参数为在此目录下创建Dockerfile等构建程序镜像需要用到的相关文件、程序。进入该目录后,为了使工作流程运行起来,我们将注意如下几个文件:

  • Makefile
  • Dockerfile
  • .sti/bin/assemble
  • .sti/bin/run

先来修改Dockerfile:

Dockerfile
1
2
3
FROM openshift/base-centos7
COPY ./.s2i/bin/ /usr/libexec/s2i
USER 1001

上面由s2i生成的Dockerfile里有许多注释文档可以参考,这里为了使流程运行起来使用了最小化的配置。
再来修改.sti/bin/assemble文件,这里只修改该文件的最后一行:

.sti/bin/assemble
1
2
# TODO: Add build steps for your application, eg npm install, bundle install
chmod +x ./app.sh

上述文件负责取得源代码并编译代码,然后准备运行。这里只是给予了app.sh可执行权限,实际上可以根据注释中的描述,在里面填加实际的构建步骤。
最后是.sti/bin/run文件,同样只做最简单的修改:

.sti/bin/run
1
exec ./app.sh

上面的文件负责程序的执行,它是最后构建好的镜像的默认运行的命令。
现在准备好了构建程序镜像的相关文件,可以运行make来创建S2I构建程序镜像了。它将创建一个名为new-s2i-image的镜像,此镜像中提供了可以编译你的应用程序的环境。

4. 构建应用程序镜像

为了通过S2I构建应用程序镜像,现在需要三样东西:

  • 源代码
  • 构建程序镜像,此镜像提供了编译和运行源代码的环境
  • s2i程序
    通过前面的步骤,这三样东西都已经准备就绪,你可以使用s2i程序开始构建过程:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    [yangdong@centos7 ~]$ s2i build --force-pull=false --loglevel=1 myproject/ new-s2i-image my-hello-world-app
    Running S2I version "v1.1.1"
    Preparing to build my-hello-world-app
    Copying sources from "/home/yangdong/myproject" to "/tmp/s2i112157938/upload/src"
    Clean build will be performed
    Running "assemble" in "my-hello-world-app"
    ---> Installing application source...
    ---> Building application from source...

上面的例子中,源代码是通过本地目录得到的(参数myproject/),当然也可以提供一个git代码仓库的URL。最后一个参数my-hello-world-app指定了构建的镜像的名称,倒数第二个参数提供了构建程序镜像的名称。构建成功后,就可以通过容器运行该镜像:

1
2
[yangdong@centos7 ~]$ docker run my-hello-world-app
Hello World!

有了一个可以运行的示例,就更容易理解这种构建方式的目的。假设你是一个新的开发人员,准备将你的代码贡献给项目。你可以很容易的修改源代码,然后通过一个简单的命令来重新构建镜像,而不需要对Docker有任何了解:

1
2
3
cd ~/myproject
cat > ~/myproject/app.sh <<< "echo 'Hello S2I!'"
s2i build --force-pull=false --loglevel=1 myproject/ new-s2i-image my-S2I-app

运行修改后的新镜像:

1
2
[yangdong@centos7 ~]$ docker run my-S2I-app
Hello S2I!

这个示例虽然简单,但说明了使用此框架,可以使开发人员关注于项目的源代码,而不用对构建Docker镜像的任何细节有了解。
其它技术也可以和此技术一起使用来推动DevOps流程。