2019-09-12 18:19:51 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# Buildah Tutorial 4
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								## Include Buildah in your build tool
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								The purpose of this tutorial is to demonstrate how to include Buildah as a library in your build tool.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								You can take advantage of all features provided by Buildah, like using Dockerfiles and building using rootless mode.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								In this tutorial I'll show you how to create a simple CLI tool that creates an image containing NodeJS and a JS main file.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								## Bootstrap the project and install the dependencies
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Bootstrap the installation of development dependencies of Buildah by following the [Building from scratch ](https://github.com/slinkydeveloper/buildah/blob/master/install.md#building-from-scratch ) instructions and in particular creating a directory for the Buildah project by completing the instructions in the [Installation from GitHub ](https://github.com/containers/buildah/blob/master/install.md#installation-from-github ) section of that page.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-22 02:23:02 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Now let's bootstrap our project. Assuming you are in the directory of the project, run the following to initialize the go modules:
							 
						 
					
						
							
								
									
										
										
										
											2019-09-12 18:19:51 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```shell
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								go mod init
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-22 02:23:02 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Next, we should import Buildah as a dependency. However, make sure that you have the following
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								developer packages installed:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```shell
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								dnf install btrfs-progs-devel gpgme-devel device-mapper-devel
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Depending on your Linux distribution, the names of the packages can be slightly different. For instance, on
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								OpenSUSE it would be
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```shell
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								zypper in libbtrfs-devel libgpgme-devel device-mapper-devel
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Now import Buildah as a dependency:
							 
						 
					
						
							
								
									
										
										
										
											2019-09-12 18:19:51 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```shell
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								go get github.com/containers/buildah
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								## Build the image
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Now you can develop your application. To access to the build features of Buildah, you need to instantiate `buildah.Builder` . This struct has methods to configure the build, define the build steps and run it.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								To instantiate a `Builder` , you need a `storage.Store`  (the Store interface found in [store.go ](https://github.com/containers/storage/blob/master/store.go )) from [`github.com/containers/storage` ](https://github.com/containers/storage ), where the intermediate and result images will be stored:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```go
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								buildStoreOptions, err := storage.DefaultStoreOptions(unshare.IsRootless(), unshare.GetRootlessUID())
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								buildStore, err := storage.GetStore(buildStoreOptions)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Define the builder options:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```go
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								builderOpts := buildah.BuilderOptions{
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    FromImage:        "node:12-alpine", // Starting image
							 
						 
					
						
							
								
									
										
										
										
											2021-02-07 06:49:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    Isolation:        define.IsolationChroot, // Isolation environment
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    CommonBuildOpts:  & define.CommonBuildOptions{},
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ConfigureNetwork: define.NetworkDefault,
							 
						 
					
						
							
								
									
										
										
										
											2019-09-12 18:19:51 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    SystemContext: 	  & types.SystemContext {},
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Now instantiate the `Builder` :
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```go
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								builder, err := buildah.NewBuilder(context.TODO(), buildStore, builderOpts)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Let's add our JS file (assuming is in your local directory with name `script.js` ):
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```go
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								err = builder.Add("/home/node/", false, buildah.AddAndCopyOptions{}, "script.js")
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								And configure the command to run:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```go
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								builder.SetCmd([]string{"node", "/home/node/script.js"})
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Before completing the build, create the image reference:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```go
							 
						 
					
						
							
								
									
										
										
										
											2020-01-03 17:07:04 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								imageRef, err := is.Transport.ParseStoreReference(buildStore, "docker.io/myusername/my-image")
							 
						 
					
						
							
								
									
										
										
										
											2019-09-12 18:19:51 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Now you can run commit the build:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```go
							 
						 
					
						
							
								
									
										
										
										
											2021-02-07 06:49:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								imageId, _, _ , err := builder.Commit(context.TODO(), imageRef, define.CommitOptions{})
							 
						 
					
						
							
								
									
										
										
										
											2019-09-12 18:19:51 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								## Rootless mode
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-03-31 21:56:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								To enable rootless mode, import `github.com/containers/storage/pkg/unshare`  and add this code at the beginning of your main method:
							 
						 
					
						
							
								
									
										
										
										
											2019-09-12 18:19:51 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```go
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								if buildah.InitReexec() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								unshare.MaybeReexecUsingUserNamespace(false)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								This code ensures that your application is re executed in an isolated environment with root privileges.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								## Complete code
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```go
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								package main
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import (
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"context"
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"fmt"
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/containers/buildah"
							 
						 
					
						
							
								
									
										
										
										
											2021-02-07 06:49:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/containers/buildah/define"
							 
						 
					
						
							
								
									
										
										
										
											2020-03-31 21:56:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/containers/storage/pkg/unshare"
							 
						 
					
						
							
								
									
										
										
										
											2020-01-03 17:07:04 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									is "github.com/containers/image/v5/storage"
							 
						 
					
						
							
								
									
										
										
										
											2019-10-26 05:19:30 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/containers/image/v5/types"
							 
						 
					
						
							
								
									
										
										
										
											2019-09-12 18:19:51 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"github.com/containers/storage"
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func main() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if buildah.InitReexec() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									unshare.MaybeReexecUsingUserNamespace(false)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									buildStoreOptions, err := storage.DefaultStoreOptions(unshare.IsRootless(), unshare.GetRootlessUID())
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if err != nil {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										panic(err)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									buildStore, err := storage.GetStore(buildStoreOptions)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if err != nil {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										panic(err)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									opts := buildah.BuilderOptions{
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										FromImage:        "node:12-alpine",
							 
						 
					
						
							
								
									
										
										
										
											2021-02-07 06:49:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										Isolation:        define.IsolationChroot,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										CommonBuildOpts:  & define.CommonBuildOptions{},
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ConfigureNetwork: define.NetworkDefault,
							 
						 
					
						
							
								
									
										
										
										
											2019-09-12 18:19:51 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										SystemContext: 	  & types.SystemContext {},
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									builder, err := buildah.NewBuilder(context.TODO(), buildStore, opts)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if err != nil {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										panic(err)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									err = builder.Add("/home/node/", false, buildah.AddAndCopyOptions{}, "script.js")
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if err != nil {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										panic(err)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									builder.SetCmd([]string{"node", "/home/node/script.js"})
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-03 17:07:04 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									imageRef, err := is.Transport.ParseStoreReference(buildStore, "docker.io/myusername/my-image")
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if err != nil {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										panic(err)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}
							 
						 
					
						
							
								
									
										
										
										
											2019-09-12 18:19:51 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-02-07 06:49:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									imageId, _, _ , err := builder.Commit(context.TODO(), imageRef, define.CommitOptions{})
							 
						 
					
						
							
								
									
										
										
										
											2019-09-12 18:19:51 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									fmt.Printf("Image built! %s\n", imageId)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```