Add the following flags to buildah bud and from
--add-host --cgroup-parent --cpu-period --cpu-quota --cpu-shares --cpuset-cpus --cpuset-mems --memory --memory-swap --security-opt --ulimit Signed-off-by: umohnani8 <umohnani@redhat.com> Closes: #477 Approved by: rhatdan
This commit is contained in:
parent
b23f145416
commit
93a3c89943
30
buildah.go
30
buildah.go
|
@ -94,6 +94,7 @@ type Builder struct {
|
|||
Docker docker.V2Image `json:"docker,omitempty"`
|
||||
// DefaultMountsFilePath is the file path holding the mounts to be mounted in "host-path:container-path" format
|
||||
DefaultMountsFilePath string `json:"defaultMountsFilePath,omitempty"`
|
||||
CommonBuildOpts *CommonBuildOptions
|
||||
}
|
||||
|
||||
// BuilderInfo are used as objects to display container information
|
||||
|
@ -136,6 +137,34 @@ func GetBuildInfo(b *Builder) BuilderInfo {
|
|||
}
|
||||
}
|
||||
|
||||
// CommonBuildOptions are reseources that can be defined by flags for both buildah from and bud
|
||||
type CommonBuildOptions struct {
|
||||
// AddHost is the list of hostnames to add to the resolv.conf
|
||||
AddHost []string
|
||||
//CgroupParent it the path to cgroups under which the cgroup for the container will be created.
|
||||
CgroupParent string
|
||||
//CPUPeriod limits the CPU CFS (Completely Fair Scheduler) period
|
||||
CPUPeriod uint64
|
||||
//CPUQuota limits the CPU CFS (Completely Fair Scheduler) quota
|
||||
CPUQuota int64
|
||||
//CPUShares (relative weight
|
||||
CPUShares uint64
|
||||
//CPUSetCPUs in which to allow execution (0-3, 0,1)
|
||||
CPUSetCPUs string
|
||||
//CPUSetMems memory nodes (MEMs) in which to allow execution (0-3, 0,1). Only effective on NUMA systems.
|
||||
CPUSetMems string
|
||||
//Memory limit
|
||||
Memory int64
|
||||
//MemorySwap limit value equal to memory plus swap.
|
||||
MemorySwap int64
|
||||
//SecruityOpts modify the way container security is running
|
||||
LabelOpts []string
|
||||
SeccompProfilePath string
|
||||
ApparmorProfile string
|
||||
//Ulimit options
|
||||
Ulimit []string
|
||||
}
|
||||
|
||||
// BuilderOptions are used to initialize a new Builder.
|
||||
type BuilderOptions struct {
|
||||
// FromImage is the name of the image which should be used as the
|
||||
|
@ -175,6 +204,7 @@ type BuilderOptions struct {
|
|||
SystemContext *types.SystemContext
|
||||
// DefaultMountsFilePath is the file path holding the mounts to be mounted in "host-path:container-path" format
|
||||
DefaultMountsFilePath string
|
||||
CommonBuildOpts *CommonBuildOptions
|
||||
}
|
||||
|
||||
// ImportOptions are used to initialize a Builder from an existing container
|
||||
|
|
|
@ -80,7 +80,7 @@ var (
|
|||
Aliases: []string{"bud"},
|
||||
Usage: "Build an image using instructions in a Dockerfile",
|
||||
Description: budDescription,
|
||||
Flags: budFlags,
|
||||
Flags: append(budFlags, fromAndBudFlags...),
|
||||
Action: budCmd,
|
||||
ArgsUsage: "CONTEXT-DIRECTORY | URL",
|
||||
}
|
||||
|
@ -201,6 +201,11 @@ func budCmd(c *cli.Context) error {
|
|||
runtimeFlags = append(runtimeFlags, "--"+arg)
|
||||
}
|
||||
|
||||
commonOpts, err := parseCommonBuildOptions(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
options := imagebuildah.BuildOptions{
|
||||
ContextDirectory: contextDir,
|
||||
PullPolicy: pullPolicy,
|
||||
|
@ -214,7 +219,9 @@ func budCmd(c *cli.Context) error {
|
|||
RuntimeArgs: runtimeFlags,
|
||||
OutputFormat: format,
|
||||
SystemContext: systemContext,
|
||||
CommonBuildOpts: commonOpts,
|
||||
}
|
||||
|
||||
if !c.Bool("quiet") {
|
||||
options.ReportWriter = os.Stderr
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"reflect"
|
||||
"regexp"
|
||||
|
@ -11,6 +12,7 @@ import (
|
|||
is "github.com/containers/image/storage"
|
||||
"github.com/containers/image/types"
|
||||
"github.com/containers/storage"
|
||||
units "github.com/docker/go-units"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/projectatomic/buildah"
|
||||
|
@ -18,6 +20,13 @@ import (
|
|||
"golang.org/x/crypto/ssh/terminal"
|
||||
)
|
||||
|
||||
const (
|
||||
// SeccompDefaultPath defines the default seccomp path
|
||||
SeccompDefaultPath = "/usr/share/containers/seccomp.json"
|
||||
// SeccompOverridePath if this exists it overrides the default seccomp path
|
||||
SeccompOverridePath = "/etc/crio/seccomp.json"
|
||||
)
|
||||
|
||||
var needToShutdownStore = false
|
||||
|
||||
func getStore(c *cli.Context) (storage.Store, error) {
|
||||
|
@ -217,3 +226,161 @@ func validateFlags(c *cli.Context, flags []cli.Flag) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var fromAndBudFlags = []cli.Flag{
|
||||
cli.StringSliceFlag{
|
||||
Name: "add-host",
|
||||
Usage: "add a custom host-to-IP mapping (host:ip) (default [])",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "cgroup-parent",
|
||||
Usage: "optional parent cgroup for the container",
|
||||
},
|
||||
cli.Uint64Flag{
|
||||
Name: "cpu-period",
|
||||
Usage: "limit the CPU CFS (Completely Fair Scheduler) period",
|
||||
},
|
||||
cli.Int64Flag{
|
||||
Name: "cpu-quota",
|
||||
Usage: "limit the CPU CFS (Completely Fair Scheduler) quota",
|
||||
},
|
||||
cli.Uint64Flag{
|
||||
Name: "cpu-shares",
|
||||
Usage: "CPU shares (relative weight)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "cpuset-cpus",
|
||||
Usage: "CPUs in which to allow execution (0-3, 0,1)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "cpuset-mems",
|
||||
Usage: "memory nodes (MEMs) in which to allow execution (0-3, 0,1). Only effective on NUMA systems.",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "memory, m",
|
||||
Usage: "memory limit (format: <number>[<unit>], where unit = b, k, m or g)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "memory-swap",
|
||||
Usage: "swap limit equal to memory plus swap: '-1' to enable unlimited swap",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "security-opt",
|
||||
Usage: "security Options (default [])",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "ulimit",
|
||||
Usage: "ulimit options (default [])",
|
||||
},
|
||||
}
|
||||
|
||||
func parseCommonBuildOptions(c *cli.Context) (*buildah.CommonBuildOptions, error) {
|
||||
var (
|
||||
memoryLimit int64
|
||||
memorySwap int64
|
||||
err error
|
||||
)
|
||||
if c.String("memory") != "" {
|
||||
memoryLimit, err = units.RAMInBytes(c.String("memory"))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "invalid value for memory")
|
||||
}
|
||||
}
|
||||
if c.String("memory-swap") != "" {
|
||||
memorySwap, err = units.RAMInBytes(c.String("memory-swap"))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "invalid value for memory-swap")
|
||||
}
|
||||
}
|
||||
if len(c.StringSlice("add-host")) > 0 {
|
||||
for _, host := range c.StringSlice("add-host") {
|
||||
if err := validateExtraHost(host); err != nil {
|
||||
return nil, errors.Wrapf(err, "invalid value for add-host")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
commonOpts := &buildah.CommonBuildOptions{
|
||||
AddHost: c.StringSlice("add-host"),
|
||||
CgroupParent: c.String("cgroup-parent"),
|
||||
CPUPeriod: c.Uint64("cpu-period"),
|
||||
CPUQuota: c.Int64("cpu-quota"),
|
||||
CPUSetCPUs: c.String("cpuset-cpus"),
|
||||
CPUSetMems: c.String("cpuset-mems"),
|
||||
CPUShares: c.Uint64("cpu-shares"),
|
||||
Memory: memoryLimit,
|
||||
MemorySwap: memorySwap,
|
||||
Ulimit: c.StringSlice("ulimit"),
|
||||
}
|
||||
if err := parseSecurityOpts(c.StringSlice("security-opt"), commonOpts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return commonOpts, nil
|
||||
}
|
||||
|
||||
func parseSecurityOpts(securityOpts []string, commonOpts *buildah.CommonBuildOptions) error {
|
||||
for _, opt := range securityOpts {
|
||||
if opt == "no-new-privileges" {
|
||||
return errors.Errorf("no-new-privileges is not supported")
|
||||
}
|
||||
con := strings.SplitN(opt, "=", 2)
|
||||
if len(con) != 2 {
|
||||
return errors.Errorf("Invalid --security-opt 1: %q", opt)
|
||||
}
|
||||
|
||||
switch con[0] {
|
||||
case "label":
|
||||
commonOpts.LabelOpts = append(commonOpts.LabelOpts, con[1])
|
||||
case "apparmor":
|
||||
commonOpts.ApparmorProfile = con[1]
|
||||
case "seccomp":
|
||||
commonOpts.SeccompProfilePath = con[1]
|
||||
default:
|
||||
return errors.Errorf("Invalid --security-opt 2: %q", opt)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if commonOpts.SeccompProfilePath == "" {
|
||||
if _, err := os.Stat(SeccompOverridePath); err == nil {
|
||||
commonOpts.SeccompProfilePath = SeccompOverridePath
|
||||
} else {
|
||||
if !os.IsNotExist(err) {
|
||||
return errors.Wrapf(err, "can't check if %q exists", SeccompOverridePath)
|
||||
}
|
||||
if _, err := os.Stat(SeccompDefaultPath); err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
return errors.Wrapf(err, "can't check if %q exists", SeccompDefaultPath)
|
||||
}
|
||||
} else {
|
||||
commonOpts.SeccompProfilePath = SeccompDefaultPath
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// validateExtraHost validates that the specified string is a valid extrahost and returns it.
|
||||
// ExtraHost is in the form of name:ip where the ip has to be a valid ip (ipv4 or ipv6).
|
||||
// for add-host flag
|
||||
func validateExtraHost(val string) error {
|
||||
// allow for IPv6 addresses in extra hosts by only splitting on first ":"
|
||||
arr := strings.SplitN(val, ":", 2)
|
||||
if len(arr) != 2 || len(arr[0]) == 0 {
|
||||
return fmt.Errorf("bad format for add-host: %q", val)
|
||||
}
|
||||
if _, err := validateIPAddress(arr[1]); err != nil {
|
||||
return fmt.Errorf("invalid IP address in add-host: %q", arr[1])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// validateIPAddress validates an Ip address.
|
||||
// for dns, ip, and ip6 flags also
|
||||
func validateIPAddress(val string) (string, error) {
|
||||
var ip = net.ParseIP(strings.TrimSpace(val))
|
||||
if ip != nil {
|
||||
return ip.String(), nil
|
||||
}
|
||||
return "", fmt.Errorf("%s is not an ip address", val)
|
||||
}
|
||||
|
|
|
@ -105,9 +105,13 @@ func pullTestImage(t *testing.T, imageName string) (string, error) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
commonOpts := &buildah.CommonBuildOptions{
|
||||
LabelOpts: nil,
|
||||
}
|
||||
options := buildah.BuilderOptions{
|
||||
FromImage: imageName,
|
||||
SignaturePolicyPath: signaturePolicyPath,
|
||||
CommonBuildOpts: commonOpts,
|
||||
}
|
||||
|
||||
b, err := buildah.NewBuilder(store, options)
|
||||
|
|
|
@ -56,7 +56,7 @@ var (
|
|||
Name: "from",
|
||||
Usage: "Create a working container based on an image",
|
||||
Description: fromDescription,
|
||||
Flags: fromFlags,
|
||||
Flags: append(fromFlags, fromAndBudFlags...),
|
||||
Action: fromCmd,
|
||||
ArgsUsage: "IMAGE",
|
||||
}
|
||||
|
@ -94,6 +94,11 @@ func fromCmd(c *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
commonOpts, err := parseCommonBuildOptions(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
options := buildah.BuilderOptions{
|
||||
FromImage: args[0],
|
||||
Container: c.String("name"),
|
||||
|
@ -101,7 +106,9 @@ func fromCmd(c *cli.Context) error {
|
|||
SignaturePolicyPath: signaturePolicy,
|
||||
SystemContext: systemContext,
|
||||
DefaultMountsFilePath: c.GlobalString("default-mounts-file"),
|
||||
CommonBuildOpts: commonOpts,
|
||||
}
|
||||
|
||||
if !c.Bool("quiet") {
|
||||
options.ReportWriter = os.Stderr
|
||||
}
|
||||
|
|
|
@ -352,20 +352,31 @@ return 1
|
|||
"
|
||||
|
||||
local options_with_args="
|
||||
--add-host
|
||||
--authfile
|
||||
--build-arg
|
||||
--cert-dir
|
||||
--cgroup-parent
|
||||
--cpu-period
|
||||
--cpu-quota
|
||||
--cpu-shares
|
||||
--cpuset-cpus
|
||||
--cpuset-mems
|
||||
--creds
|
||||
-f
|
||||
--file
|
||||
--format
|
||||
--label
|
||||
-m
|
||||
--memory
|
||||
--memory-swap
|
||||
--runtime
|
||||
--runtime-flag
|
||||
--security-opt
|
||||
--signature-policy
|
||||
-t
|
||||
--tag
|
||||
--ulimit
|
||||
"
|
||||
|
||||
local all_options="$options_with_args $boolean_options"
|
||||
|
@ -646,11 +657,23 @@ return 1
|
|||
"
|
||||
|
||||
local options_with_args="
|
||||
--add-host
|
||||
--authfile
|
||||
--cert-dir
|
||||
--cgroup-parent
|
||||
--cpu-period
|
||||
--cpu-quota
|
||||
--cpu-shares
|
||||
--cpuset-cpus
|
||||
--cpuset-mems
|
||||
--creds
|
||||
-m
|
||||
--memory
|
||||
--memory-swap
|
||||
--name
|
||||
--signature-policy
|
||||
--security-opt
|
||||
--ulimit
|
||||
"
|
||||
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ BuildRequires: gpgme-devel
|
|||
BuildRequires: device-mapper-devel
|
||||
BuildRequires: btrfs-progs-devel
|
||||
BuildRequires: libassuan-devel
|
||||
BuildRequires: libseccomp-devel
|
||||
BuildRequires: glib2-devel
|
||||
BuildRequires: ostree-devel
|
||||
BuildRequires: make
|
||||
|
|
|
@ -13,6 +13,13 @@ build context directory. The build context directory can be specified as the
|
|||
to a temporary location.
|
||||
|
||||
## OPTIONS
|
||||
|
||||
**--add-host**=[]
|
||||
|
||||
Add a custom host-to-IP mapping (host:ip)
|
||||
|
||||
Add a line to /etc/hosts. The format is hostname:ip. The **--add-host** option can be set multiple times.
|
||||
|
||||
**--authfile** *path*
|
||||
|
||||
Path of the authentication file. Default is ${XDG_RUNTIME\_DIR}/containers/auth.json, which is set using `podman login`.
|
||||
|
@ -30,6 +37,73 @@ resulting image's configuration.
|
|||
Use certificates at *path* (*.crt, *.cert, *.key) to connect to the registry.
|
||||
Default certificates directory is _/etc/containers/certs.d_.
|
||||
|
||||
**--cgroup-parent**=""
|
||||
|
||||
Path to cgroups under which the cgroup for the container will be created. If the path is not absolute, the path is considered to be relative to the cgroups path of the init process. Cgroups will be created if they do not already exist.
|
||||
|
||||
**--cpu-period**=*0*
|
||||
|
||||
Limit the CPU CFS (Completely Fair Scheduler) period
|
||||
|
||||
Limit the container's CPU usage. This flag tell the kernel to restrict the container's CPU usage to the period you specify.
|
||||
|
||||
**--cpu-quota**=*0*
|
||||
|
||||
Limit the CPU CFS (Completely Fair Scheduler) quota
|
||||
|
||||
Limit the container's CPU usage. By default, containers run with the full
|
||||
CPU resource. This flag tell the kernel to restrict the container's CPU usage
|
||||
to the quota you specify.
|
||||
|
||||
**--cpu-shares**=*0*
|
||||
|
||||
CPU shares (relative weight)
|
||||
|
||||
By default, all containers get the same proportion of CPU cycles. This proportion
|
||||
can be modified by changing the container's CPU share weighting relative
|
||||
to the weighting of all other running containers.
|
||||
|
||||
To modify the proportion from the default of 1024, use the **--cpu-shares**
|
||||
flag to set the weighting to 2 or higher.
|
||||
|
||||
The proportion will only apply when CPU-intensive processes are running.
|
||||
When tasks in one container are idle, other containers can use the
|
||||
left-over CPU time. The actual amount of CPU time will vary depending on
|
||||
the number of containers running on the system.
|
||||
|
||||
For example, consider three containers, one has a cpu-share of 1024 and
|
||||
two others have a cpu-share setting of 512. When processes in all three
|
||||
containers attempt to use 100% of CPU, the first container would receive
|
||||
50% of the total CPU time. If you add a fourth container with a cpu-share
|
||||
of 1024, the first container only gets 33% of the CPU. The remaining containers
|
||||
receive 16.5%, 16.5% and 33% of the CPU.
|
||||
|
||||
On a multi-core system, the shares of CPU time are distributed over all CPU
|
||||
cores. Even if a container is limited to less than 100% of CPU time, it can
|
||||
use 100% of each individual CPU core.
|
||||
|
||||
For example, consider a system with more than three cores. If you start one
|
||||
container **{C0}** with **-c=512** running one process, and another container
|
||||
**{C1}** with **-c=1024** running two processes, this can result in the following
|
||||
division of CPU shares:
|
||||
|
||||
PID container CPU CPU share
|
||||
100 {C0} 0 100% of CPU0
|
||||
101 {C1} 1 100% of CPU1
|
||||
102 {C1} 2 100% of CPU2
|
||||
|
||||
**--cpuset-cpus**=""
|
||||
|
||||
CPUs in which to allow execution (0-3, 0,1)
|
||||
|
||||
**--cpuset-mems**=""
|
||||
|
||||
Memory nodes (MEMs) in which to allow execution (0-3, 0,1). Only effective on NUMA systems.
|
||||
|
||||
If you have four memory nodes on your system (0-3), use `--cpuset-mems=0,1`
|
||||
then processes in your container will only use memory from the first
|
||||
two memory nodes.
|
||||
|
||||
**--creds** *creds*
|
||||
|
||||
The [username[:password]] to use to authenticate with the registry if required.
|
||||
|
@ -53,6 +127,27 @@ Control the format for the built image's manifest and configuration data.
|
|||
Recognized formats include *oci* (OCI image-spec v1.0, the default) and
|
||||
*docker* (version 2, using schema format 2 for the manifest).
|
||||
|
||||
**-m**, **--memory**=""
|
||||
|
||||
Memory limit (format: <number>[<unit>], where unit = b, k, m or g)
|
||||
|
||||
Allows you to constrain the memory available to a container. If the host
|
||||
supports swap memory, then the **-m** memory setting can be larger than physical
|
||||
RAM. If a limit of 0 is specified (not using **-m**), the container's memory is
|
||||
not limited. The actual limit may be rounded up to a multiple of the operating
|
||||
system's page size (the value would be very large, that's millions of trillions).
|
||||
|
||||
**--memory-swap**="LIMIT"
|
||||
|
||||
A limit value equal to memory plus swap. Must be used with the **-m**
|
||||
(**--memory**) flag. The swap `LIMIT` should always be larger than **-m**
|
||||
(**--memory**) value. By default, the swap `LIMIT` will be set to double
|
||||
the value of --memory.
|
||||
|
||||
The format of `LIMIT` is `<number>[<unit>]`. Unit can be `b` (bytes),
|
||||
`k` (kilobytes), `m` (megabytes), or `g` (gigabytes). If you don't specify a
|
||||
unit, `b` is used. Set LIMIT to `-1` to enable unlimited swap.
|
||||
|
||||
**--pull**
|
||||
|
||||
Pull the image if it is not present. If this flag is disabled (with
|
||||
|
@ -82,6 +177,23 @@ runtime, the manpage to consult is `runc(8)`).
|
|||
Note: Do not pass the leading `--` to the flag. To pass the runc flag `--log-format json`
|
||||
to buildah bud, the option given would be `--runtime-flag log-format=json`.
|
||||
|
||||
**--security-opt**=[]
|
||||
|
||||
Security Options
|
||||
|
||||
"label=user:USER" : Set the label user for the container
|
||||
"label=role:ROLE" : Set the label role for the container
|
||||
"label=type:TYPE" : Set the label type for the container
|
||||
"label=level:LEVEL" : Set the label level for the container
|
||||
"label=disable" : Turn off label confinement for the container
|
||||
"no-new-privileges" : Not supported
|
||||
|
||||
"seccomp=unconfined" : Turn off seccomp confinement for the container
|
||||
"seccomp=profile.json : White listed syscalls seccomp Json file to be used as a seccomp filter
|
||||
|
||||
"apparmor=unconfined" : Turn off apparmor confinement for the container
|
||||
"apparmor=your-profile" : Set the apparmor confinement profile for the container
|
||||
|
||||
**--signature-policy** *signaturepolicy*
|
||||
|
||||
Pathname of a signature policy file to use. It is not recommended that this
|
||||
|
@ -97,6 +209,10 @@ process completes successfully.
|
|||
|
||||
Require HTTPS and verify certificates when talking to container registries (defaults to true).
|
||||
|
||||
**--ulimit**=[]
|
||||
|
||||
Ulimit options
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
buildah bud .
|
||||
|
@ -117,5 +233,9 @@ buildah bud --runtime-flag debug .
|
|||
|
||||
buildah bud --authfile /tmp/auths/myauths.json --cert-dir ~/auth --tls-verify=true --creds=username:password -t imageName -f Dockerfile.simple
|
||||
|
||||
buildah bud --memory 40m --cpu-period 10000 --cpu-quota 50000 --ulimit nofile=1024:1028 -t imageName .
|
||||
|
||||
buildah bud --security-opt label=level:s0:c100,c200 --cgroup-parent /path/to/cgroup/parent -t imageName .
|
||||
|
||||
## SEE ALSO
|
||||
buildah(1), podman-login(1), docker-login(1)
|
||||
|
|
|
@ -36,6 +36,12 @@ The container ID of the container that was created. On error, -1 is returned an
|
|||
|
||||
## OPTIONS
|
||||
|
||||
**--add-host**=[]
|
||||
|
||||
Add a custom host-to-IP mapping (host:ip)
|
||||
|
||||
Add a line to /etc/hosts. The format is hostname:ip. The **--add-host** option can be set multiple times.
|
||||
|
||||
**--authfile** *path*
|
||||
|
||||
Path of the authentication file. Default is ${XDG_RUNTIME\_DIR}/containers/auth.json, which is set using `podman login`.
|
||||
|
@ -46,12 +52,100 @@ If the authorization state is not found there, $HOME/.docker/config.json is chec
|
|||
Use certificates at *path* (*.crt, *.cert, *.key) to connect to the registry.
|
||||
Default certificates directory is _/etc/containers/certs.d_.
|
||||
|
||||
**--cgroup-parent**=""
|
||||
|
||||
Path to cgroups under which the cgroup for the container will be created. If the path is not absolute, the path is considered to be relative to the cgroups path of the init process. Cgroups will be created if they do not already exist.
|
||||
|
||||
**--cpu-period**=*0*
|
||||
|
||||
Limit the CPU CFS (Completely Fair Scheduler) period
|
||||
|
||||
Limit the container's CPU usage. This flag tell the kernel to restrict the container's CPU usage to the period you specify.
|
||||
|
||||
**--cpu-quota**=*0*
|
||||
|
||||
Limit the CPU CFS (Completely Fair Scheduler) quota
|
||||
|
||||
Limit the container's CPU usage. By default, containers run with the full
|
||||
CPU resource. This flag tell the kernel to restrict the container's CPU usage
|
||||
to the quota you specify.
|
||||
|
||||
**--cpu-shares**=*0*
|
||||
|
||||
CPU shares (relative weight)
|
||||
|
||||
By default, all containers get the same proportion of CPU cycles. This proportion
|
||||
can be modified by changing the container's CPU share weighting relative
|
||||
to the weighting of all other running containers.
|
||||
|
||||
To modify the proportion from the default of 1024, use the **--cpu-shares**
|
||||
flag to set the weighting to 2 or higher.
|
||||
|
||||
The proportion will only apply when CPU-intensive processes are running.
|
||||
When tasks in one container are idle, other containers can use the
|
||||
left-over CPU time. The actual amount of CPU time will vary depending on
|
||||
the number of containers running on the system.
|
||||
|
||||
For example, consider three containers, one has a cpu-share of 1024 and
|
||||
two others have a cpu-share setting of 512. When processes in all three
|
||||
containers attempt to use 100% of CPU, the first container would receive
|
||||
50% of the total CPU time. If you add a fourth container with a cpu-share
|
||||
of 1024, the first container only gets 33% of the CPU. The remaining containers
|
||||
receive 16.5%, 16.5% and 33% of the CPU.
|
||||
|
||||
On a multi-core system, the shares of CPU time are distributed over all CPU
|
||||
cores. Even if a container is limited to less than 100% of CPU time, it can
|
||||
use 100% of each individual CPU core.
|
||||
|
||||
For example, consider a system with more than three cores. If you start one
|
||||
container **{C0}** with **-c=512** running one process, and another container
|
||||
**{C1}** with **-c=1024** running two processes, this can result in the following
|
||||
division of CPU shares:
|
||||
|
||||
PID container CPU CPU share
|
||||
100 {C0} 0 100% of CPU0
|
||||
101 {C1} 1 100% of CPU1
|
||||
102 {C1} 2 100% of CPU2
|
||||
|
||||
**--cpuset-cpus**=""
|
||||
|
||||
CPUs in which to allow execution (0-3, 0,1)
|
||||
|
||||
**--cpuset-mems**=""
|
||||
|
||||
Memory nodes (MEMs) in which to allow execution (0-3, 0,1). Only effective on NUMA systems.
|
||||
|
||||
If you have four memory nodes on your system (0-3), use `--cpuset-mems=0,1`
|
||||
then processes in your container will only use memory from the first
|
||||
two memory nodes.
|
||||
|
||||
**--creds** *creds*
|
||||
|
||||
The [username[:password]] to use to authenticate with the registry if required.
|
||||
If one or both values are not supplied, a command line prompt will appear and the
|
||||
value can be entered. The password is entered without echo.
|
||||
|
||||
**-m**, **--memory**=""
|
||||
|
||||
Memory limit (format: <number>[<unit>], where unit = b, k, m or g)
|
||||
|
||||
Allows you to constrain the memory available to a container. If the host
|
||||
supports swap memory, then the **-m** memory setting can be larger than physical
|
||||
RAM. If a limit of 0 is specified (not using **-m**), the container's memory is
|
||||
not limited. The actual limit may be rounded up to a multiple of the operating
|
||||
system's page size (the value would be very large, that's millions of trillions).
|
||||
|
||||
**--memory-swap**="LIMIT"
|
||||
|
||||
A limit value equal to memory plus swap. Must be used with the **-m**
|
||||
(**--memory**) flag. The swap `LIMIT` should always be larger than **-m**
|
||||
(**--memory**) value. By default, the swap `LIMIT` will be set to double
|
||||
the value of --memory.
|
||||
|
||||
The format of `LIMIT` is `<number>[<unit>]`. Unit can be `b` (bytes),
|
||||
`k` (kilobytes), `m` (megabytes), or `g` (gigabytes). If you don't specify a
|
||||
unit, `b` is used. Set LIMIT to `-1` to enable unlimited swap.
|
||||
|
||||
**--name** *name*
|
||||
|
||||
A *name* for the working container
|
||||
|
@ -70,6 +164,23 @@ Pull the image even if a version of the image is already present.
|
|||
|
||||
If an image needs to be pulled from the registry, suppress progress output.
|
||||
|
||||
**--security-opt**=[]
|
||||
|
||||
Security Options
|
||||
|
||||
"label=user:USER" : Set the label user for the container
|
||||
"label=role:ROLE" : Set the label role for the container
|
||||
"label=type:TYPE" : Set the label type for the container
|
||||
"label=level:LEVEL" : Set the label level for the container
|
||||
"label=disable" : Turn off label confinement for the container
|
||||
"no-new-privileges" : Not supported
|
||||
|
||||
"seccomp=unconfined" : Turn off seccomp confinement for the container
|
||||
"seccomp=profile.json : White listed syscalls seccomp Json file to be used as a seccomp filter
|
||||
|
||||
"apparmor=unconfined" : Turn off apparmor confinement for the container
|
||||
"apparmor=your-profile" : Set the apparmor confinement profile for the container
|
||||
|
||||
**--signature-policy** *signaturepolicy*
|
||||
|
||||
Pathname of a signature policy file to use. It is not recommended that this
|
||||
|
@ -80,6 +191,10 @@ option be used, as the default behavior of using the system-wide default policy
|
|||
|
||||
Require HTTPS and verify certificates when talking to container registries (defaults to true)
|
||||
|
||||
**--ulimit**=[]
|
||||
|
||||
Ulimit options
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
buildah from imagename --pull
|
||||
|
@ -96,5 +211,9 @@ buildah from myregistry/myrepository/imagename:imagetag --creds=myusername:mypas
|
|||
|
||||
buildah from myregistry/myrepository/imagename:imagetag --authfile=/tmp/auths/myauths.json
|
||||
|
||||
buildah from --memory 40m --cpu-shares 2 --cpuset-cpus 0,2 --security-opt label=level:s0:c100,c200 myregistry/myrepository/imagename:imagetag
|
||||
|
||||
buildah from --ulimit nofile=1024:1028 --cgroup-parent /path/to/cgroup/parent myregistry/myrepository/imagename:imagetag
|
||||
|
||||
## SEE ALSO
|
||||
buildah(1), podman-login(1), docker-login(1)
|
||||
|
|
|
@ -104,7 +104,8 @@ type BuildOptions struct {
|
|||
// Accepted values are OCIv1ImageFormat and Dockerv2ImageFormat.
|
||||
OutputFormat string
|
||||
// SystemContext holds parameters used for authentication.
|
||||
SystemContext *types.SystemContext
|
||||
SystemContext *types.SystemContext
|
||||
CommonBuildOpts *buildah.CommonBuildOptions
|
||||
}
|
||||
|
||||
// Executor is a buildah-based implementation of the imagebuilder.Executor
|
||||
|
@ -136,6 +137,7 @@ type Executor struct {
|
|||
volumeCache map[string]string
|
||||
volumeCacheInfo map[string]os.FileInfo
|
||||
reportWriter io.Writer
|
||||
commonBuildOptions *buildah.CommonBuildOptions
|
||||
}
|
||||
|
||||
// Preserve informs the executor that from this point on, it needs to ensure
|
||||
|
@ -433,6 +435,7 @@ func NewExecutor(store storage.Store, options BuildOptions) (*Executor, error) {
|
|||
out: options.Out,
|
||||
err: options.Err,
|
||||
reportWriter: options.ReportWriter,
|
||||
commonBuildOptions: options.CommonBuildOpts,
|
||||
}
|
||||
if exec.err == nil {
|
||||
exec.err = os.Stderr
|
||||
|
@ -475,6 +478,7 @@ func (b *Executor) Prepare(ib *imagebuilder.Builder, node *parser.Node, from str
|
|||
SignaturePolicyPath: b.signaturePolicyPath,
|
||||
ReportWriter: b.reportWriter,
|
||||
SystemContext: b.systemContext,
|
||||
CommonBuildOpts: b.commonBuildOptions,
|
||||
}
|
||||
builder, err := buildah.NewBuilder(b.store, builderOptions)
|
||||
if err != nil {
|
||||
|
|
3
new.go
3
new.go
|
@ -269,7 +269,7 @@ func newBuilder(store storage.Store, options BuilderOptions) (*Builder, error) {
|
|||
if err = reserveSELinuxLabels(store, container.ID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
processLabel, mountLabel, err := label.InitLabels(nil)
|
||||
processLabel, mountLabel, err := label.InitLabels(options.CommonBuildOpts.LabelOpts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -288,6 +288,7 @@ func newBuilder(store storage.Store, options BuilderOptions) (*Builder, error) {
|
|||
ProcessLabel: processLabel,
|
||||
MountLabel: mountLabel,
|
||||
DefaultMountsFilePath: options.DefaultMountsFilePath,
|
||||
CommonBuildOpts: options.CommonBuildOpts,
|
||||
}
|
||||
|
||||
if options.Mount {
|
||||
|
|
111
run.go
111
run.go
|
@ -1,7 +1,9 @@
|
|||
package buildah
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
@ -9,6 +11,8 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/containers/storage/pkg/ioutils"
|
||||
"github.com/docker/docker/profiles/seccomp"
|
||||
units "github.com/docker/go-units"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/opencontainers/runtime-tools/generate"
|
||||
|
@ -69,6 +73,76 @@ type RunOptions struct {
|
|||
Quiet bool
|
||||
}
|
||||
|
||||
func addRlimits(ulimit []string, g *generate.Generator) error {
|
||||
var (
|
||||
ul *units.Ulimit
|
||||
err error
|
||||
)
|
||||
|
||||
for _, u := range ulimit {
|
||||
if ul, err = units.ParseUlimit(u); err != nil {
|
||||
return errors.Wrapf(err, "ulimit option %q requires name=SOFT:HARD, failed to be parsed", u)
|
||||
}
|
||||
|
||||
g.AddProcessRlimits("RLIMIT_"+strings.ToUpper(ul.Name), uint64(ul.Hard), uint64(ul.Soft))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func addHostsToFile(hosts []string) error {
|
||||
file, err := os.OpenFile("/etc/hosts", os.O_APPEND|os.O_WRONLY, os.ModeAppend)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
w := bufio.NewWriter(file)
|
||||
for _, host := range hosts {
|
||||
fmt.Fprintln(w, host)
|
||||
}
|
||||
return w.Flush()
|
||||
}
|
||||
|
||||
func addCommonOptsToSpec(commonOpts *CommonBuildOptions, g *generate.Generator) error {
|
||||
// RESOURCES - CPU
|
||||
if commonOpts.CPUPeriod != 0 {
|
||||
g.SetLinuxResourcesCPUPeriod(commonOpts.CPUPeriod)
|
||||
}
|
||||
if commonOpts.CPUQuota != 0 {
|
||||
g.SetLinuxResourcesCPUQuota(commonOpts.CPUQuota)
|
||||
}
|
||||
if commonOpts.CPUShares != 0 {
|
||||
g.SetLinuxResourcesCPUShares(commonOpts.CPUShares)
|
||||
}
|
||||
if commonOpts.CPUSetCPUs != "" {
|
||||
g.SetLinuxResourcesCPUCpus(commonOpts.CPUSetCPUs)
|
||||
}
|
||||
if commonOpts.CPUSetMems != "" {
|
||||
g.SetLinuxResourcesCPUMems(commonOpts.CPUSetMems)
|
||||
}
|
||||
|
||||
// RESOURCES - MEMORY
|
||||
if commonOpts.Memory != 0 {
|
||||
g.SetLinuxResourcesMemoryLimit(commonOpts.Memory)
|
||||
}
|
||||
if commonOpts.MemorySwap != 0 {
|
||||
g.SetLinuxResourcesMemorySwap(commonOpts.MemorySwap)
|
||||
}
|
||||
|
||||
if commonOpts.CgroupParent != "" {
|
||||
g.SetLinuxCgroupsPath(commonOpts.CgroupParent)
|
||||
}
|
||||
|
||||
if err := addRlimits(commonOpts.Ulimit, g); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := addHostsToFile(commonOpts.AddHost); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
logrus.Debugln("Resources:", commonOpts)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Builder) setupMounts(mountPoint string, spec *specs.Spec, optionMounts []specs.Mount, bindFiles, volumes []string) error {
|
||||
// The passed-in mounts matter the most to us.
|
||||
mounts := make([]specs.Mount, len(optionMounts))
|
||||
|
@ -181,6 +255,11 @@ func (b *Builder) Run(command []string, options RunOptions) error {
|
|||
g.AddProcessEnv(env[0], env[1])
|
||||
}
|
||||
}
|
||||
|
||||
if err := addCommonOptsToSpec(b.CommonBuildOpts, &g); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(command) > 0 {
|
||||
g.SetProcessArgs(command)
|
||||
} else {
|
||||
|
@ -265,6 +344,38 @@ func (b *Builder) Run(command []string, options RunOptions) error {
|
|||
return errors.Wrapf(err, "error ensuring working directory %q exists", spec.Process.Cwd)
|
||||
}
|
||||
|
||||
//Security Opts
|
||||
g.SetProcessApparmorProfile(b.CommonBuildOpts.ApparmorProfile)
|
||||
|
||||
// HANDLE SECCOMP
|
||||
if b.CommonBuildOpts.SeccompProfilePath != "unconfined" {
|
||||
if b.CommonBuildOpts.SeccompProfilePath != "" {
|
||||
seccompProfile, err := ioutil.ReadFile(b.CommonBuildOpts.SeccompProfilePath)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "opening seccomp profile (%s) failed", b.CommonBuildOpts.SeccompProfilePath)
|
||||
}
|
||||
seccompConfig, err := seccomp.LoadProfile(string(seccompProfile), spec)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "loading seccomp profile (%s) failed", b.CommonBuildOpts.SeccompProfilePath)
|
||||
}
|
||||
spec.Linux.Seccomp = seccompConfig
|
||||
} else {
|
||||
seccompConfig, err := seccomp.GetDefaultProfile(spec)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "loading seccomp profile (%s) failed", b.CommonBuildOpts.SeccompProfilePath)
|
||||
}
|
||||
spec.Linux.Seccomp = seccompConfig
|
||||
}
|
||||
}
|
||||
|
||||
cgroupMnt := specs.Mount{
|
||||
Destination: "/sys/fs/cgroup",
|
||||
Type: "cgroup",
|
||||
Source: "cgroup",
|
||||
Options: []string{"nosuid", "noexec", "nodev", "relatime", "ro"},
|
||||
}
|
||||
g.AddMount(cgroupMnt)
|
||||
|
||||
bindFiles := []string{"/etc/hosts", "/etc/resolv.conf"}
|
||||
err = b.setupMounts(mountPoint, spec, options.Mounts, bindFiles, b.Volumes())
|
||||
if err != nil {
|
||||
|
|
|
@ -128,3 +128,57 @@ load helpers
|
|||
buildah rm ${cid}
|
||||
buildah rmi alpine alpine2
|
||||
}
|
||||
|
||||
@test "from cpu-period test" {
|
||||
cid=$(buildah from --cpu-period=5000 --pull --signature-policy ${TESTSDIR}/policy.json alpine)
|
||||
run buildah run $cid cat /sys/fs/cgroup/cpu/cpu.cfs_period_us
|
||||
echo $output
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "5000" ]]
|
||||
buildah rm $cid
|
||||
}
|
||||
|
||||
@test "from cpu-quota test" {
|
||||
cid=$(buildah from --cpu-quota=5000 --pull --signature-policy ${TESTSDIR}/policy.json alpine)
|
||||
run buildah run $cid cat /sys/fs/cgroup/cpu/cpu.cfs_quota_us
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ 5000 ]]
|
||||
buildah rm $cid
|
||||
}
|
||||
|
||||
@test "from cpu-shares test" {
|
||||
cid=$(buildah from --cpu-shares=2 --pull --signature-policy ${TESTSDIR}/policy.json alpine)
|
||||
run buildah run $cid cat /sys/fs/cgroup/cpu/cpu.shares
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ 2 ]]
|
||||
buildah rm $cid
|
||||
}
|
||||
|
||||
@test "from cpuset-cpus test" {
|
||||
cid=$(buildah from --cpuset-cpus=0 --pull --signature-policy ${TESTSDIR}/policy.json alpine)
|
||||
run buildah run $cid cat /sys/fs/cgroup/cpuset/cpuset.cpus
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ 0 ]]
|
||||
buildah rm $cid
|
||||
}
|
||||
|
||||
@test "from cpuset-mems test" {
|
||||
cid=$(buildah from --cpuset-mems=0 --pull --signature-policy ${TESTSDIR}/policy.json alpine)
|
||||
run buildah run $cid cat /sys/fs/cgroup/cpuset/cpuset.mems
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ 0 ]]
|
||||
buildah rm $cid
|
||||
}
|
||||
|
||||
@test "from memory test" {
|
||||
cid=$(buildah from --memory=40m --pull --signature-policy ${TESTSDIR}/policy.json alpine)
|
||||
run buildah run $cid cat /sys/fs/cgroup/memory/memory.limit_in_bytes
|
||||
echo $output
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ 41943040 ]]
|
||||
buildah rm $cid
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue