podman-build(1)
โจ podman-build(1) โ build a container image using a Containerfile โจ
okay bestie, welcome to podman-build(1) from the General Commands Manual ๐
this is the page where we build a container image using a Containerfile, and yes, we are going through every single flag because you deserve the full lore ๐ซถ
๐ธ NAME ๐ธ
podman-build โ Build a container image using a Containerfile. That's the whole vibe โจ
๐ฆ SYNOPSIS ๐ฆ
podman build [options] [context]
podman image build [options] [context]
๐ DESCRIPTION ๐
podman build builds an image using instructions from one or more Containerfiles or Dockerfiles and a specified build context directory. A Containerfile uses the same syntax as a Dockerfile internally, so no cap there ๐ง For this document, a file referred to as a Containerfile can be a file named either Containerfile or Dockerfile exclusively. Any file that has additional extension attached will not be recognized by podman build unless a -f flag is used to specify the file ๐
The build context directory can be specified as the http(s) URL of an archive, git repository or Containerfile. Slay, flexible much? ๐ซ
When invoked with -f and a path to a Containerfile, with no explicit CONTEXT directory, Podman uses the Containerfile's parent directory as its build context. Cute and convenient, honestly ๐
Containerfiles ending with a .in suffix are preprocessed via CPP(1). This can be useful to decompose Containerfiles into several reusable parts that can be used via CPP's #include directive. Containerfiles ending in .in are restricted to no comment lines unless they are CPP commands. Note, a Containerfile.in file can still be used by other tools when manually preprocessing them via cpp -E ๐
When the URL is an archive, the contents of the URL is downloaded to a temporary location and extracted before execution.
When the URL is a Containerfile, the Containerfile is downloaded to a temporary location.
When a Git repository is set as the URL, the repository is cloned locally and then set as the context. A URL is treated as a Git repository if it has a git:// prefix or a .git suffix ๐
NOTE:podman builduses code sourced from the Buildah project to build container images. This Buildah code creates Buildah containers for theRUNoptions in container storage. In certain situations, when thepodman buildcrashes or users kill thepodman buildprocess, these external containers can be left in container storage. Use thepodman ps --all --externalcommand to see these containers ๐
podman buildx build command is an alias of podman build. Not all buildx build features are available in Podman. The buildx build option is provided for scripting compatibility. iykyk โจ
๐ OPTIONS ๐
okay, options time. buckle up, bestie โ we are not skipping a single one ๐
๐ธ --add-host=hostname[;hostname[;...]]:ip
Add a custom host-to-IP mapping to the container's /etc/hosts file.
The option takes one or multiple semicolon-separated hostnames to be mapped to a single IPv4 or IPv6 address, separated by a colon. It can also be used to overwrite the IP addresses of hostnames Podman adds to /etc/hosts by default (also see the --name and --hostname options). This option can be specified multiple times to add additional mappings to /etc/hosts. It conflicts with the --no-hosts option and conflicts with no_hosts=true in containers.conf.
Instead of an IP address, the special flag host-gateway can be given. This resolves to an IP address the container can use to connect to the host. The IP address chosen depends on your network setup, thus there's no guarantee that Podman can determine the host-gateway address automatically, which will then cause Podman to fail with an error message. You can overwrite this IP address using the host_containers_internal_ip option in containers.conf.
The host-gateway address is also used by Podman to automatically add the host.containers.internal and host.docker.internal hostnames to /etc/hosts. You can prevent that by either giving the --no-hosts option, or by setting host_containers_internal_ip="none" in containers.conf. If no host-gateway address was configured manually and Podman fails to determine the IP address automatically, Podman will silently skip adding these internal hostnames to /etc/hosts. If Podman is running in a virtual machine using podman machine (this includes Mac and Windows hosts), Podman will silently skip adding the internal hostnames to /etc/hosts, unless an IP address was configured manually; the internal hostnames are resolved by the gvproxy DNS resolver instead.
Podman will use the /etc/hosts file of the host as a basis by default, i.e. any hostname present in this file will also be present in the /etc/hosts file of the container. A different base file can be configured using the base_hosts_file config in containers.conf.
๐ฆ --all-platforms
Instead of building for a set of platforms specified using the --platform option, inspect the build's base images, and build for all of the platforms for which they are all available. Stages that use scratch as a starting point can not be inspected, so at least one non-scratch stage must be present for detection to work usefully. no cap, that scratch stage just can't give us the info ๐ญ
๐ --annotation=annotation=value
Add an image annotation (e.g. annotation=value) to the image metadata. Can be used multiple times.
Note: this information is not present in Docker image formats, so it is discarded when writing images in Docker formats. it's giving "not portable, bestie" ๐
๐ --arch=arch
Set the architecture of the image to be built, and that of the base image to be pulled, if the build uses one, to the provided value instead of using the architecture of the build host. Unless overridden, subsequent lookups of the same image in the local storage matches this architecture, regardless of the host. (Examples: arm, arm64, 386, amd64, ppc64le, s390x) ๐
๐ --authfile=path
Path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json on Linux, and $HOME/.config/containers/auth.json on Windows/macOS. The file is created by podman login. If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using docker login.
Note: There is also the option to override the default path of the authentication file by setting theREGISTRY_AUTH_FILEenvironment variable. This can be done withexport REGISTRY_AUTH_FILE=path.
โจ --build-arg=arg=value
Specifies a build argument and its value, which is interpolated in instructions read from the Containerfiles in the same way that environment variables are, but which are not added to environment variable list in the resulting image's configuration. sneaky little build-time bestie ๐ซถ
๐ --build-arg-file=path
Specifies a file containing lines of build arguments of the form arg=value. The suggested file name is argfile.conf.
Comment lines beginning with # are ignored, along with blank lines. All others must be of the arg=value format passed to --build-arg.
If several arguments are provided via the --build-arg-file and --build-arg options, the build arguments are merged across all of the provided files and command line arguments.
Any file provided in a --build-arg-file option is read before the arguments supplied via the --build-arg option.
When a given argument name is specified several times, the last instance is the one that is passed to the resulting builds. This means --build-arg values always override those in a --build-arg-file. last one wins, periodt ๐
๐ง --build-context=name=value
Specify an additional build context using its short name and its location. Additional build contexts can be referenced in the same manner as we access different stages in COPY instruction.
Valid values are:
- Local directory โ e.g.
--build-context project2=../path/to/project2/src - HTTP URL to a tarball โ e.g.
--build-context src=https://example.org/releases/src.tar - Container image โ specified with a
container-image://prefix, e.g.--build-context alpine=container-image://alpine:3.15, (also acceptsdocker://,docker-image://)
On the Containerfile side, reference the build context on all commands that accept the โfromโ parameter. Hereโs how that might look:
FROM [name]
COPY --from=[name] ...
RUN --mount=from=[name] โฆ
The value of [name] is matched with the following priority order:
- Named build context defined with
--build-context [name]=.. - Stage defined with
AS [name]inside Containerfile - Image
[name], either local or in a remote registry
๐ฅ --cache-from=image
Repository to utilize as a potential cache source. When specified, Buildah tries to look for cache images in the specified repository and attempts to pull cache images instead of actually executing the build steps locally. Buildah only attempts to pull previously cached images if they are considered as valid cache hits.
Use the --cache-to option to populate a remote repository with cache content.
Example:
# populate a cache and also consult it
buildah build -t test --layers --cache-to registry/myrepo/cache --cache-from registry/myrepo/cache .
Note:--cache-fromoption is ignored unless--layersis specified. no layers, no cache lore ๐ญ
๐ซ --cache-to=image
Set this flag to specify a remote repository that is used to store cache images. Buildah attempts to push newly built cache image to the remote repository.
Note: Use the --cache-from option in order to use cache content in a remote repository.
Example:
# populate a cache and also consult it
buildah build -t test --layers --cache-to registry/myrepo/cache --cache-from registry/myrepo/cache .
Note:--cache-tooption is ignored unless--layersis specified. same rule, bestie ๐
๐ฆ --cache-ttl
Limit the use of cached images to only consider images with created timestamps less than duration ago. For example if --cache-ttl=1h is specified, Buildah considers intermediate cache images which are created under the duration of one hour, and intermediate cache images outside this duration is ignored.
Note: Setting--cache-ttl=0manually is equivalent to using--no-cachein the implementation since this means that the user does not want to use cache at all. expired cache? we don't know her ๐
๐ธ --cap-add=CAP_xxx
When executing RUN instructions, run the command specified in the instruction with the specified capability added to its capability set. Certain capabilities are granted by default; this option can be used to add more. more power, more responsibility, etc. โจ
๐ --cap-drop=CAP_xxx
When executing RUN instructions, run the command specified in the instruction with the specified capability removed from its capability set. The CAP_CHOWN, CAP_DAC_OVERRIDE, CAP_FOWNER, CAP_FSETID, CAP_KILL, CAP_NET_BIND_SERVICE, CAP_SETFCAP, CAP_SETGID, CAP_SETPCAP, and CAP_SETUID capabilities are granted by default; this option can be used to remove them.
If a capability is specified to both the --cap-add and --cap-drop options, it is dropped, regardless of the order in which the options were given. drop always wins, no cap ๐ญ
๐ --cert-dir=path
Use certificates at path (*.crt, *.cert, *.key) to connect to the registry. (Default: /etc/containers/certs.d) For details, see containers-certs.d(5). (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) ๐ซถ
--cgroup-parent=pathโ where the cgroup for the container gets born ๐ Give it apathand that's where it lives. If the path isn't absolute, it's treated as relative to the cgroups path of the init process. And bestie, don't stress about making it first โ cgroups are created if they don't already exist. โจ--cgroupns=howโ sets how cgroup namespaces get handled while RUN instructions are doing their thing. The value can be""(the empty string, iconic) or"private", both of which mean "make a brand new cgroup namespace," or it can be"host", which means "reuse the cgroup namespace buildah itself is running in." Pick your vibe ๐ธ--compat-volumesโ this one's giving strict-parent energy ๐ It handles directories marked with theVOLUMEinstruction (both the ones in this build and the ones inherited from base images) so their contents can only be modified byADDandCOPYinstructions. Any changes made in those locations byRUNinstructions get reverted, periodt. Before this option existed, this behavior was the default, but it's now disabled by default. So if you want the old strictness back, this is the flag, no cap.--compressโ okay so this option is literally just here to be aligned with other containers CLIs ๐ญ Podman doesn't talk to a daemon or a remote server, so compressing the data before sending it is irrelevant to Podman. That's the whole tea.
Heads up: this option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines ๐
--compression-format=gzip | zstd | zstd:chunkedโ specifies the compression format to use. Supported values aregzip,zstdandzstd:chunked. The default isgzipunless it's overridden in thecontainers.conffile. Also important:zstd:chunkedis incompatible with encrypting images, and will be treated aszstdwith a warning in that case. Lowkey a glow-down but okay ๐--compression-level=levelโ specifies the compression level to use. The value is specific to the compression algorithm used, bestie โ forzstdthe accepted values are in the range 1-20 (inclusive) with a default of 3, while forgzipit's 1-9 (inclusive) and has a default of 5. Slay responsibly โจ--cpp-flag=flagsโ sets additional flags to pass to the C Preprocessorcpp(1). Containerfiles ending with a.insuffix get preprocessed viacpp(1), and this option is how you pass extra flags tocpp. ๐ง
Note: you can also set defaultCPPFLAGSby setting theBUILDAH_CPPFLAGSenvironment variable (e.g.,export BUILDAH_CPPFLAGS="-DDEBUG"). iykyk ๐
--cpu-period=limitโ sets the CPU period for the Completely Fair Scheduler (CFS), which is a duration in microseconds. Once the container's CPU quota is used up, it will not be scheduled to run until the current period ends. Defaults to100000microseconds. โญ
On some systems, changing the resource limits may not be allowed for non-root users. For more details, see https://github.com/containers/podman/blob/main/troubleshooting.md#26-running-containers-with-resource-limits-fails-with-a-permissions-error
Not supported on cgroups V1 rootless systems. ๐ซถ
--cpu-quota=limitโ limits the CPU Completely Fair Scheduler (CFS) quota. It caps the container's CPU usage; by default, containers run with the full CPU resource. The limit is a number in microseconds. If a number is provided, the container is allowed to use that much CPU time until the CPU period ends (controllable via--cpu-period). ๐ฆ
On some systems, changing the resource limits may not be allowed for non-root users. For more details, see https://github.com/containers/podman/blob/main/troubleshooting.md#26-running-containers-with-resource-limits-fails-with-a-permissions-error
Not supported on cgroups V1 rootless systems. ๐ซถ
--cpu-shares,-c=sharesโ CPU shares, aka 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 combined weight of all the running containers. Default weight is1024.
The proportion only applies when CPU-intensive processes are running โ when tasks in one container are idle, other containers can use the leftover CPU time. The actual amount of CPU time varies 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 receives 50% of the total CPU time. If a fourth container is added 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 the container C0 is started with --cpu-shares=512 running one process, and another container C1 with --cpu-shares=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 โ
โโโโโโโดโโโโโโโโโโโโดโโโโโโดโโโโโโโโโโโโโโโ
On some systems, changing the resource limits may not be allowed for non-root users. For more details, see https://github.com/containers/podman/blob/main/troubleshooting.md#26-running-containers-with-resource-limits-fails-with-a-permissions-error
Not supported on cgroups V1 rootless systems. ๐ซถ
--cpuset-cpus=numberโ which CPUs you're allowing execution on, bestie ๐ Can be specified as a comma-separated list (e.g.0,1), as a range (e.g.0-3), or any combination thereof (e.g.0-3,7,11-15). Choose your fighters wisely โจ
On some systems, changing the resource limits may not be allowed for non-root users. For more details, see https://github.com/containers/podman/blob/main/troubleshooting.md#26-running-containers-with-resource-limits-fails-with-a-permissions-error
Not supported on cgroups V1 rootless systems. ๐ซถ
--cpuset-mems=nodesโ memory nodes (MEMs) in which to allow execution (0-3,0,1). Only effective on NUMA systems, ngl. If there are four memory nodes on the system (0-3), use--cpuset-mems=0,1and then processes in the container only use memory from the first two memory nodes. ๐ง โจ
On some systems, changing the resource limits may not be allowed for non-root users. For more details, see https://github.com/containers/podman/blob/main/troubleshooting.md#26-running-containers-with-resource-limits-fails-with-a-permissions-error
Not supported on cgroups V1 rootless systems. ๐ซถ
--created-annotationโ adds an image annotation (see also--annotation) to the image metadata, setting"org.opencontainers.image.created"to the current time, or to the datestamp specified to the--source-date-epochor--timestampflag, if either was used. If false, no such annotation will be present in the written image. Main character metadata energy ๐
Note: this information is not present in Docker image formats, so it is discarded when writing images in Docker formats. It's giving "lost in translation" ๐ญ
--creds=[username[:password]]โ the[username[:password]]to use to authenticate with the registry, if required. If one or both values are not supplied, a command line prompt appears and the value can be entered. The password is entered without echo โ your secret is safe with us ๐คซ๐
Note that the specified credentials are only used to authenticate against target registries. They are not used for mirrors or when the registry gets rewritten (seecontainers-registries.conf(5)); to authenticate against those, consider using acontainers-auth.json(5)file. Fr fr, different door, different key ๐
--cw=optionsโ produces an image suitable for use as a confidential workload running in a trusted execution environment (TEE) using krun (i.e.,crunbuilt with the libkrun feature enabled and invoked as krun). Instead of the conventional contents, the root filesystem of the image will contain an encrypted disk image and configuration information for krun. This is highkey spy-movie tech ๐ต๏ธโโ๏ธโจ
The value for options is a comma-separated list of key=value pairs, supplying configuration information which is needed for producing the additional data which will be included in the container image.
Recognized keys are:
attestation_urlโ the location of a key broker / attestation server. If a value is specified, the new image's workload ID, along with the passphrase used to encrypt the disk image, will be registered with the server, and the server's location will be stored in the container image. At run-time, krun is expected to contact the server to retrieve the passphrase using the workload ID, which is also stored in the container image. If no value is specified, apassphrasevalue must be specified. ๐cpusโ the number of virtual CPUs which the image expects to be run with at run-time. If not specified, a default value will be supplied. ๐ฅ๏ธfirmware_libraryโ the location of thelibkrunfw-sevshared library. If not specified, buildah checks for its presence in a number of hard-coded locations. ๐memoryโ the amount of memory which the image expects to be run with at run-time, as a number of megabytes. If not specified, a default value will be supplied. ๐งpassphraseโ the passphrase to use to encrypt the disk image which will be included in the container image. If no value is specified, but anattestation_urlvalue is specified, a randomly-generated passphrase will be used. The authors recommend setting anattestation_urlbut not apassphrase. ๐slopโ extra space to allocate for the disk image compared to the size of the container image's contents, expressed either as a percentage (..%) or a size value (bytes, or larger units if suffixes likeKBorMBare present), or a sum of two or more such specifications. If not specified, buildah guesses that 25% more space than the contents will be enough, but this option is provided in case its guess is wrong. Always good to have slop ๐typeโ the type of trusted execution environment (TEE) which the image should be marked for use with. Accepted values are"SEV"(AMD Secure Encrypted Virtualization - Encrypted State) and"SNP"(AMD Secure Encrypted Virtualization - Secure Nested Paging). If not specified, defaults to"SNP". ๐
Okay so, picking up right where we left off: workload_id is a workload identifier that gets recorded in the container image, and itโs used at run-time to retrieve the passphrase that encrypted the disk image. If you donโt specify it, a semi-random value will be derived from the base imageโs image ID. Heads-up: this option is not supported on the remote client, including Mac and Windows (excluding WSL2) machines. ๐
--decryption-key=key[:passphrase]โ the[key[:passphrase]]used to decrypt images. The key can point to keys and/or certificates, and decryption is tried with all keys. If the key is protected by a passphrase, youโre required to pass it in the argument โ and omit it otherwise. ๐--device=host-device[:container-device][:permissions]โ add a host device to the container. The format isHOST-DEVICE[:CONTAINER-DEVICE][:PERMISSIONS], whereHOST-DEVICEis the path of the device node on the host,CONTAINER-DEVICEis the path of the device node in the container, andPERMISSIONSis a list combining'r'for read,'w'for write, and'm'formknod(2).
Example: --device=/dev/sdc:/dev/xvdc:rwm.
Note: if host-device is a symbolic link, itโs resolved first. The container only stores the major and minor numbers of the host device. ๐
Podman may load kernel modules required for using the specified device. The devices Podman loads modules for when necessary are: /dev/fuse.
In rootless mode, the new device is bind mounted in the container from the host rather than Podman creating it within the container space. Because the bind mount retains its SELinux label on SELinux systems, the container can get permission denied when accessing the mounted device. Modify SELinux settings to allow containers to use all device labels via this command:
$ sudo setsebool -P container_use_devices=true
Note: if the user only has access rights via a group, accessing the device from inside a rootless container fails. The crun(1) runtime offers a workaround by adding the option --annotation run.oci.keep_original_groups=1. ๐ซถ
--disable-compression,-Dโ donโt compress filesystem layers when building the image unless the location where the image is being written requires it. This is the default setting, because image layers are compressed automatically when theyโre pushed to registries, and images being written to local storage only need to be decompressed again to be stored. Compression can be forced in all cases by specifying--disable-compression=false. ๐--disable-content-trustโ this is a Docker-specific option to disable image verification to a container registry and is not supported by Podman. Itโs a NOOP and provided solely for scripting compatibility. Periodt.--dns=ipaddrโ set custom DNS servers.
This option can override the DNS configuration passed to the container. Typically this is necessary when the host DNS configuration is invalid for the container (e.g., 127.0.0.1). When thatโs the case, the --dns flag is necessary for every run.
The special value none can be specified to disable creation of /etc/resolv.conf in the container by Podman. The /etc/resolv.conf file in the image is then used without changes.
Note that ipaddr may be added directly to the containerโs /etc/resolv.conf โ but this is not guaranteed. For example, passing a custom network whose dns_enabled is set to true to --network results in /etc/resolv.conf only referring to the aardvark-dns server. aardvark-dns then forwards to the supplied ipaddr for all non-container name queries.
This option cannot be combined with --network that is set to none.
Note: this option takes effect only during RUN instructions in the build. It does not affect /etc/resolv.conf in the final image. ๐
--dns-option=optionโ set custom DNS options to be used during the build. โจ--dns-search=domainโ set custom DNS search domains to be used during the build. ๐ธ--env=env[=value]โ add a value (e.g.env=value) to the built image. Can be used multiple times. If neither=nor a value are specified, butenvis set in the current environment, the value from the current environment is added to the image.
To remove an environment variable from the built image, use the --unsetenv option. ๐
--file,-f=Containerfileโ specifies a Containerfile containing instructions for building the image, either a local file or anhttporhttpsURL. If more than one Containerfile is specified,FROMinstructions are only accepted from the last specified file.
If a build context is not specified, and at least one Containerfile is a local file, the directory in which it resides is used as the build context.
Specifying the option -f - causes the Containerfile contents to be read from stdin. ๐
--force-compressionโ if set, push uses the specified compression algorithm even if the destination already contains a differently-compressed variant. Defaults totrueif--compression-formatis explicitly specified on the command-line,falseotherwise. ๐ฅ--force-rmโ always remove intermediate containers after a build, even if the build fails (defaulttrue). No leftover little messes, bestie. ๐ง--formatโ control the format for the built imageโs manifest and configuration data. Recognized formats includeoci(OCI image-spec v1.0, the default) anddocker(version 2, using schema format 2 for the manifest).
Note: you can also override the default format by setting the BUILDAH_FORMAT environment variable. export BUILDAH_FORMAT=docker ๐ซ
--fromโ overrides the firstFROMinstruction within the Containerfile. If there are multipleFROMinstructions in a Containerfile, only the first is changed.
With the remote podman client, not all container transports work as expected. For example, oci-archive:/x.tar references /x.tar on the remote machine instead of on the client. When using podman remote clients it is best to restrict use to containers-storage, and docker:// transports. ๐
--group-add=group | keep-groupsโ assign additional groups to the primary user running within the container process.keep-groupsis a special flag that tells Podman to keep the supplementary group access.
Allows the container to use the userโs supplementary group access. If file systems or devices are only accessible by the rootless userโs group, this flag tells the OCI runtime to pass the group access into the container. Currently only available with the crun OCI runtime. Note: keep-groups is exclusive โ other groups cannot be specified with this flag. (Not available for remote commands, including Mac and Windows (excluding WSL2) machines.) ๐
--help,-hโ print usage statement. Simple, iconic. โจ--hooks-dir=pathโ each*.jsonfile in the path configures a hook forbuildah buildcontainers. Thereโs more detail on the syntax of the JSON files and the semantics of hook injection. Buildah currently supports both the1.0.0and0.1.0hook schemas, although the0.1.0schema is deprecated.
This option may be set multiple times; paths from later options have higher precedence.
For the annotation conditions, buildah uses any annotations set in the generated OCI configuration.
For the bind-mount conditions, only mounts explicitly requested by the caller via --volume are considered. Bind mounts that buildah inserts by default (e.g. /dev/shm) are not considered.
If --hooks-dir is unset for root callers, Buildah currently defaults to /usr/share/containers/oci/hooks.d and /etc/containers/oci/hooks.d in order of increasing precedence. Using these defaults is deprecated. Migrate to explicitly setting --hooks-dir. ๐ช
--http-proxyโ by default proxy environment variables are passed into the container if set for the Podman process. This can be disabled by setting the value tofalse. The environment variables passed in includehttp_proxy,https_proxy,ftp_proxy,no_proxy, and also the upper case versions of those. This option is only needed when the host system must use a proxy but the container does not use any proxy. Proxy environment variables specified for the container in any other way overrides the values that have been passed through from the host. (Other ways to specify the proxy for the container include passing the values with the--envflag, or hard coding the proxy environment at container build time.) When used with the remote client it uses the proxy environment variables that are set on the server process.
Defaults to true. ๐
--identity-labelโ adds default identity labelio.buildah.versionif set. (defaulttrue). ๐ท๏ธ--ignorefileโ path to an alternative.containerignorefile. ๐--iidfile=ImageIDfileโ write the built imageโs ID to the file. When--platformis specified more than once, attempting to use this option triggers an error. ๐พ--iidfile-raw=ImageIDfileโ write the built imageโs ID to the file without the algorithm prefix (e.g.,sha256:). When--platformis specified more than once, attempting to use this option triggers an error. ๐--inherit-annotations=bool-valueโ inherit the annotations from the base image or base stages. (defaulttrue). Use cases which set this flag tofalsemay need to do the same for the--created-annotationflag. ๐ซง--inherit-labelsโ inherit the labels from the base image or base stages. (defaulttrue). ๐--ipc=howโ sets the configuration for IPC namespaces when handlingRUNinstructions. The configured value can be""(the empty string) or"container"to indicate that a new IPC namespace is created, or it can be"host"to indicate that the IPC namespace in whichpodmanitself is being run is reused, or it can be the path to an IPC namespace which is already in use by another process. ๐ง--isolation=typeโ controls what type of isolation is used for running processes as part ofRUNinstructions. Recognized types includeoci(OCI-compatible runtime, the default),rootless(OCI-compatible runtime invoked using a modified configuration and its--rootlessoption enabled, with--no-new-keyring--no-pivotadded to its create invocation, with network and UTS namespaces disabled, and IPC, PID, and user namespaces enabled; the default for unprivileged users), andchroot(an internal wrapper that leans more towardchroot(1)than container technology).
Note: you can also override the default isolation type by setting the BUILDAH_ISOLATION environment variable. export BUILDAH_ISOLATION=oci ๐ฆ
--jobs=numberโ run up to N concurrent stages in parallel. If the number of jobs is greater than1, stdin is read from/dev/null. If0is specified, then there is no limit in the number of jobs that run in parallel. โก--label=labelโ add an image label (e.g.label=value) to the image metadata. Can be used multiple times. ๐
Ok so back to the capabilities tea โ โ users can drop a special label io.containers.capabilities=CAP1,CAP2,CAP3 in a Containerfile that lists out exactly which Linux capabilities the container needs to run properly. This label lives in the container image and basically tells Podman "bestie, just these ones, nothing more." Podman launches the container with only the specified capabilities โ but only as long as that list is a subset of the default list. ๐
If the specified capabilities are not in the default set? Podman prints an error message and runs the container with the default capabilities instead. Slightly embarrassing but we move.
--layer-label=label[=value]โ adds an intermediate image label (likelabel=value) to the intermediate image metadata. You can use it multiple times, stack 'em up. ๐ Iflabelis named but neither=nor a value is provided, then the label is set to an empty value.--layersโ cache intermediate images during the build process (default is true, so like, it's already slaying). โจ
Note: you can also override the default value of layers by setting theBUILDAH_LAYERSenvironment variable.export BUILDAH_LAYERS=trueโ that's it, that's the whole vibe.
--logfile=filenameโ logs the output that's sent to standard output and standard error into the specified file instead of to standard output and standard error. Very "I journal instead of trauma-dumping" energy. ๐ This option is not supported on the remote client, including Mac and Windows (excluding WSL2) machines. Sorry bestie.--logsplit=bool-valueโ if--logfileand--platformare specified, the--logsplitoption lets end-users split the log file for each platform into different files, in this exact format:${logfile}_${platform-os}_${platform-arch}. One log per platform, organized queen behavior. ๐ This option is also not supported on the remote client, including Mac and Windows (excluding WSL2) machines.--manifest=manifestโ name of the manifest list to which the image is added. Creates the manifest list if it doesn't exist. This option is useful for building multi architecture images, iykyk. ๐--memory,-m=number[unit]โ memory limit. A unit can beb(bytes),k(kibibytes),m(mebibytes), org(gibibytes).
This lets you constrain the memory available to a container. If the host supports swap memory, then the --memory setting can be larger than physical RAM. If a limit of 0 is specified (not using --memory), 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 is very large, that's millions of trillions ๐ญ).
This option is not supported on cgroups V1 rootless systems.
--memory-swap=number[unit]โ a limit value equal to memory plus swap. A unit can beb(bytes),k(kibibytes),m(mebibytes), org(gibibytes).
Must be used with the -m (--memory) flag. The argument value must be larger than that of -m (--memory). By default, it is set to double the value of --memory.
Set number to -1 to enable unlimited swap. ๐
This option is not supported on cgroups V1 rootless systems either. cgroups V1 rootless stays losing.
--metadata-file=MetadataFileโ writes information about the built image to the named file. When--platformis specified more than once, attempting to use this option triggers an error. ๐
Note: this option is not supported in remote mode.
--mount=mount-specificationโ adds this mount to eachRUNcommand in a Containerfile before executing. For example:
podman build --mount=type=secret,id=mysecret โฆ
and a Containerfile entry of:
RUN cat /run/secrets/mysecret
has the same effect as:
RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret
Same energy, less typing. Obsessed. ๐ซถ
--network=mode,--netโ sets the configuration for network namespaces when handlingRUNinstructions.
Valid mode values are:
noneโ no networking. โจhostโ use the Podman host network stack. Note: the host mode gives the container full access to local system services such as D-bus and is therefore considered insecure. โ ๏ธns:pathโ path to a network namespace to join.privateโ create a new namespace for the container (default).<network name|ID>โ join the network with the given name or ID, e.g. use--network mynetto join the network with the namemynet. Only supported for rootful users.pasta[:OPTIONS,...]โ usepasta(1)to create a user-mode networking stack. This is the default for rootless containers and only supported in rootless mode. By default, IPv4 and IPv6 addresses and routes, as well as the pod interface name, are copied from the host. If port forwarding isn't configured, ports are forwarded dynamically as services are bound on either side (init namespace or container namespace). Port forwarding preserves the original source IP address. Options described inpasta(1)can be specified as comma-separated arguments.
In terms of pasta(1) options, --config-net is given by default, in order to configure networking when the container is started, and --no-map-gw is also assumed by default, to avoid direct access from container to host using the gateway address. The latter can be overridden by passing --map-gw in the pasta-specific options (despite not being an actual pasta(1) option). Sneaky but valid. ๐
Also, -t none and -u none are passed to disable automatic port forwarding based on bound ports. Similarly, -T none and -U none are given to disable the same functionality from container to host.
Some examples:
pasta:--map-gwโ allow the container to directly reach the host using the gateway address.pasta:--mtu,1500โ specify a 1500 bytes MTU for the tap interface in the container.pasta:--ipv4-only,-a,10.0.2.0,-n,24,-g,10.0.2.2,--dns-forward,10.0.2.3,-m,1500,--no-ndp,--no-dhcpv6,--no-dhcpโ disable IPv6, assign10.0.2.0/24to thetap0interface in the container, with gateway10.0.2.3, enable DNS forwarder reachable at10.0.2.3, set MTU to 1500 bytes, disable NDP, DHCPv6 and DHCP support. It's giving "I configured everything myself" ๐pasta:-I,tap0,--ipv4-only,-a,10.0.2.0,-n,24,-g,10.0.2.2,--dns-forward,10.0.2.3,--no-ndp,--no-dhcpv6,--no-dhcpโ same as above, but leave the MTU to 65520 bytes.pasta:-t,auto,-u,auto,-T,auto,-U,autoโ enable automatic port forwarding based on observed bound ports from both host and container sides.pasta:-T,5201โ enable forwarding of TCP port5201from container to host, using the loopback interface instead of the tap interface for improved performance. ๐ฅ
--no-cacheโ do not use existing cached images for the container build. Build from the start with a new set of cached layers. Fresh start, new me. ๐ธ--no-hostnameโ do not create the/etc/hostnamefile in the containers.
By default, Podman manages the /etc/hostname file, adding the container's own hostname. When the --no-hostname option is set, the image's /etc/hostname will be preserved unmodified if it exists.
--no-hostsโ do not modify the/etc/hostsfile in the container.
Podman assumes control over the container's /etc/hosts file by default and adds entries for the container's name (see --name option) and hostname (see --hostname option), the internal host.containers.internal and host.docker.internal hosts, as well as any hostname added using the --add-host option. Refer to the --add-host option for details. Passing --no-hosts disables this, so that the image's /etc/hosts file is kept unmodified. The same can be achieved globally by setting no_hosts=true in containers.conf.
This option conflicts with --add-host. Pick a lane bestie.
--omit-historyโ omit build history information in the built image (defaultfalse).
This option is useful for the cases where end users explicitly want to set --omit-history to omit the optional History from built images, or when working with images built using build tools that do not include History information in their images. Some images just don't want their past brought up, and honestly? Respect. ๐
--os=stringโ set the OS of the image to be built, and that of the base image to be pulled, if the build uses one, instead of using the current operating system of the build host. Unless overridden, subsequent lookups of the same image in the local storage matches this OS, regardless of the host.--os-feature=featureโ set the name of a required operating system feature for the image which is built. By default, if the image is not based onscratch, the base image's required OS feature list is kept, if the base image specified any. This option is typically only meaningful when the image's OS is Windows. ๐ช
If feature has a trailing -, then the feature is removed from the set of required features which is listed in the image. Subtraction but make it metadata.
--os-version=versionโ set the exact required operating system version for the image which is built. By default, if the image is not based onscratch, the base image's required OS version is kept, if the base image specified one. This option is typically only meaningful when the image's OS is Windows, and is typically set in Windows base images, so using this option is usually unnecessary. Ngl you probably won't need it. ๐ฆ--output,-o=output-optsโ output destination (format:type=local,dest=path).
The --output (or -o) option extends the default behavior of building a container image by allowing users to export the contents of the image as files on the local filesystem, which can be useful for generating local binaries, code generation, etc. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines.)
The value for --output is a comma-separated sequence of key=value pairs, defining the output type and options.
Supported keys are:
dest: destination path for exported output. Valid value is absolute or relative path,-means the standard output.type: defines the type of output to be used. Valid values are documented below.
Valid type values are:
local: write the resulting build files to a directory on the client-side.tar: write the resulting files as a single tarball (.tar).
If no type is specified, the value defaults to local. Alternatively, instead of a comma-separated sequence, the value of --output can be just a destination (in the dest format) (e.g. --output some-path, --output -) where --output some-path is treated as if type=local and --output - is treated as if type=tar. Shortcut queen. โจ
--pid=pidโ sets the configuration for PID namespaces when handlingRUNinstructions. The configured value can be""(the empty string) or"container"to indicate that a new PID namespace is created, or it can be"host"to indicate that the PID namespace in which podman itself is being run is reused, or it can be the path to a PID namespace which is already in use by another process.--platform=os/arch[/variant][,...]โ set theos/archof the built image (and its base image, when using one) to the provided value instead of using the current operating system and architecture of the host (for examplelinux/arm). Unless overridden, subsequent lookups of the same image in the local storage matches this platform, regardless of the host. Multi-arch main character energy. ๐
If --platform is set, bestie, then the values of the --arch, --os, and --variant options is overridden. ๐
The --platform option can be specified more than once, or given a comma-separated list of values as its argument. When more than one platform is specified, the --manifest option is used instead of the --tag option. โจ
Os/arch pairs are those used by the Go Programming Language. In several cases the arch value for a platform differs from one produced by other tools such as the arch command. Valid OS and architecture name combinations are listed as values for $GOOS and $GOARCH at https://golang.org/doc/install/source#environment, and can also be found by running go tool dist list. ๐ฆ
While podman build is happy to use base images and build images for any platform that exists, RUN instructions are unable to succeed without the help of emulation provided by packages like qemu-user-static. no cap, that emulation stuff is doing a lot of heavy lifting ๐ญ
--pull=policyโ Pull image policy. The default ismissing.- always: Always pull the image and throw an error if the pull fails. ๐ฅ
- missing: Only pull the image when it does not exist in the local containers storage. Throw an error if no image is found and the pull fails.
- never: Never pull the image but use the one from the local containers storage. Throw an error when no image is found.
- newer: Pull if the image on the registry is newer than the one in the local containers storage. An image is considered to be newer when the digests are different. Comparing the time stamps is prone to errors. Pull errors are suppressed if a local image was found.
--quiet,-qโ Suppress informational output messages (which indicate which instruction is being processed, and the progress of the instruction). Print only the final error message or successful completion information, such as the image or container ID. quiet mode said โless talking, more slayingโ ๐คซ--retry=attemptsโ Number of times to retry pulling or pushing images between the registry and local storage in case of failure. Default is3.--retry-delay=durationโ Duration of delay between retry attempts when pulling or pushing images between the registry and local storage in case of failure. The default is to start at two seconds and then exponentially back off. The delay is used when this value is set, and no exponential back off occurs. โณ--rewrite-timestampโ When generating new layers for the image, ensure that no newly added content bears a timestamp later than the value used by the--source-date-epochflag, if one was provided, by replacing any timestamps which are later than that value, with that value.--rmโ Remove intermediate containers after a successful build (defaulttrue).--runtime=pathโ The path to an alternate OCI-compatible runtime, which is used to run commands specified by the RUN instruction.
Note: You can also override the default runtime by setting the BUILDAH_RUNTIME environment variable.
export BUILDAH_RUNTIME=/usr/local/bin/runc
--runtime-flag=flagโ Adds global flags for the container runtime. To list the supported flags, please consult the manpages of the selected container runtime.
Default runtime flags can be added in containers.conf.
Note: Do not pass the leading -- to the flag. To pass the runc flag --log-format json to buildah build, the option given is --runtime-flag log-format=json.
--save-stagesโ Preserve intermediate stage images instead of removing them after the build completes (Default isfalse). By default, Buildah removes intermediate stage images to save space. This option keeps those images, which can be useful for debugging multi-stage builds or for reusing intermediate stages in subsequent builds. ๐
--save-stages can be used with --layers and subsequent builds with --layers can use the preserved intermediate layers as cache.
When combined with --stage-labels, all stage images (including the final image) will include metadata labels for easier identification and management.
--sbom=presetโ Generate SBOMs (Software Bills Of Materials) for the output image by scanning the working container and build contexts using the named combination of scanner image, scanner commands, and merge strategy. Must be specified with one or more of--sbom-image-output,--sbom-image-purl-output,--sbom-output, and--sbom-purl-output. Recognized presets, and the set of options which they equate to:"syft","syft-cyclonedx":
--sbom-scanner-image=ghcr.io/anchore/syft
--sbom-scanner-command="/syft scan -q dir:{ROOTFS} --output cyclonedx-json={OUTPUT}"
--sbom-scanner-command="/syft scan -q dir:{CONTEXT} --output cyclonedx-json={OUTPUT}"
--sbom-merge-strategy=merge-cyclonedx-by-component-name-and-version
"syft-spdx":
--sbom-scanner-image=ghcr.io/anchore/syft
--sbom-scanner-command="/syft scan -q dir:{ROOTFS} --output spdx-json={OUTPUT}"
--sbom-scanner-command="/syft scan -q dir:{CONTEXT} --output spdx-json={OUTPUT}"
--sbom-merge-strategy=merge-spdx-by-package-name-and-versioninfo
"trivy","trivy-cyclonedx":
--sbom-scanner-image=ghcr.io/aquasecurity/trivy
--sbom-scanner-command="trivy filesystem -q {ROOTFS} --format cyclonedx --output {OUTPUT}"
--sbom-scanner-command="trivy filesystem -q {CONTEXT} --format cyclonedx --output {OUTPUT}"
--sbom-merge-strategy=merge-cyclonedx-by-component-name-and-version
"trivy-spdx":
--sbom-scanner-image=ghcr.io/aquasecurity/trivy
--sbom-scanner-command="trivy filesystem -q {ROOTFS} --format spdx-json --output {OUTPUT}"
--sbom-scanner-command="trivy filesystem -q {CONTEXT} --format spdx-json --output {OUTPUT}"
--sbom-merge-strategy=merge-spdx-by-package-name-and-versioninfo
--sbom-image-output=pathโ When generating SBOMs, store the generated SBOM in the specified path in the output image. There is no default.--sbom-image-purl-output=pathโ When generating SBOMs, scan them for PURL (package URL โจhttps://github.com/package-url/purl-spec/blob/master/PURL-SPECIFICATION.rstโฉ) information, and save a list of found PURLs to the specified path in the output image. There is no default.--sbom-merge-strategy=methodโ If more than one--sbom-scanner-commandvalue is being used, use the specified method to merge the output from later commands with output from earlier commands. Recognized values include:catโ Concatenate the files.merge-cyclonedx-by-component-name-and-versionโ Merge the"component"fields of JSON documents, ignoring values from documents when the combination of their"name"and"version"values is already present. Documents are processed in the order in which they are generated, which is the order in which the commands that generate them were specified.merge-spdx-by-package-name-and-versioninfoโ Merge the"package"fields of JSON documents, ignoring values from documents when the combination of their"name"and"versionInfo"values is already present. Documents are processed in the order in which they are generated, which is the order in which the commands that generate them were specified.
--sbom-output=fileโ When generating SBOMs, store the generated SBOM in the named file on the local filesystem. There is no default.--sbom-purl-output=fileโ When generating SBOMs, scan them for PURL (package URL โจhttps://github.com/package-url/purl-spec/blob/master/PURL-SPECIFICATION.rstโฉ) information, and save a list of found PURLs to the named file in the local filesystem. There is no default.--sbom-scanner-command=imageโ Generate SBOMs by running the specified command from the scanner image. If multiple commands are specified, they are run in the order in which they are specified. These text substitutions are performed:{ROOTFS}โ The root of the built image's filesystem, bind mounted.{CONTEXT}โ The build context and additional build contexts, bind mounted.{OUTPUT}โ The name of a temporary output file, to be read and merged with others or copied elsewhere.
--sbom-scanner-image=imageโ Generate SBOMs using the specified scanner image.--secret=id=id[,src=envOrFile][,env=ENV][,type=file | env]โ Pass secret information to be used in the Containerfile for building images in a safe way that will not end up stored in the final image, or be seen in other stages. The value of the secret will be read from an environment variable or file named by the"id"option, or named by the"src"option if it is specified, or from an environment variable specified by the"env"option. See EXAMPLES โจ#examplesโฉ. The secret will be mounted in the container at/run/secrets/idby default. ๐ซถ
To later use the secret, use the --mount flag in a RUN instruction within a Containerfile:
RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret
The location of the secret in the container can be overridden using the "target", "dst", or "destination" option of the RUN --mount flag.
RUN --mount=type=secret,id=mysecret,target=/run/secrets/myothersecret cat /run/secrets/myothersecret
Note: changing the contents of secret files will not trigger a rebuild of layers that use said secrets.
--security-opt=optionโ Security Options ๐apparmor=unconfined: Turn off apparmor confinement for the containerapparmor=alternate-profile: Set the apparmor confinement profile for the containerlabel=user:USER: Set the label user for the container processeslabel=role:ROLE: Set the label role for the container processeslabel=type:TYPE: Set the label process type for the container processeslabel=level:LEVEL: Set the label level for the container processeslabel=filetype:TYPE: Set the label file type for the container fileslabel=disable: Turn off label separation for the containerno-new-privileges: Disable container processes from gaining additional privilegesseccomp=unconfined: Turn off seccomp confinement for the containerseccomp=profile.json: JSON file to be used as the seccomp filter for the container.
--shm-size=number[unit]โ Size of/dev/shm. A unit can beb(bytes),k(kibibytes),m(mebibytes), org(gibibytes). If the unit is omitted, the system uses bytes. If the size is omitted, the default is64m. When size is0, there is no limit on the amount of memory used for IPC by the container. This option conflicts with--ipc=host. shm-size math is real, bestie ๐งฎ--sign-by=fingerprintโ Sign the image using a GPG key with the specified FINGERPRINT. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines,)--skip-unused-stagesโ Skip stages in multi-stage builds which don't affect the target stage. (Default:true).--source-date-epoch=secondsโ sets the"created"timestamp on the built image to this many seconds since the epoch (that's Unix time0, aka00:00:00 UTC on 1 January 1970). Default? It uses whatever's in theSOURCE_DATE_EPOCHenvironment variable, or the current time if that's not set.
Okay so here's why this slaps ๐
โ the "created" timestamp gets written into the image's config and manifest when the image is committed, so running the exact same build twice normally gives you two images with different sha256 hashes even when nothing about the Containerfile or build context changed. Rude.
When this flag is set, a SOURCE_DATE_EPOCH build arg will provide its value for a stage in which it's declared.
When this flag is set, the image configuration's "created" timestamp is always set to the time you specified, which should let you build identical images at different times from the same set of inputs. Reproducibility queen ๐.
When this flag is set, output written as specified to the --output flag will bear exactly the specified timestamp.
Conflicts with the similar --timestamp flag, which also sets its specified time on the contents of new layers. Pick one, bestie, they're not friends.
--source-policy-file=pathnameโ points to a BuildKit-compatible source policy JSON file. When you give it one, source references (like base images inFROMinstructions) get evaluated against the policy rules before anything uses them.
Source policies let you control which images are allowed as base images, and optionally convert image references (say, pinning tags to specific digests) without touching your Containerfiles. Super useful for enforcing organizational policies and keeping builds reproducible. Very "corporate compliance but make it fashion" of it.
The policy file is a JSON document containing an array of rules. Each rule has:
action: the action to take when the rule matches. Valid actions are:ALLOW: explicitly allow the source (no transformation).DENY: block the source and fail the build.CONVERT: transform the source to a different reference specified inupdates.
selector: specifies which sources the rule applies to.identifier: the source identifier to match (e.g.,docker-image://docker.io/library/alpine:latest).matchType: how to match the identifier. Valid types areEXACTandWILDCARD(supports*and?glob patterns). Defaults toWILDCARDif not specified.
updates: forCONVERTactions, specifies the replacement identifier.
Rules are evaluated in order; the first matching rule wins. If no rule matches, the source is allowed by default.
Note: Source policyCONVERTrules are processed after--build-contextsubstitutions but before any substitutions specified incontainers-registries.conf(5). So you've got multiple ways to override which base image is used for a particular stage, in order of precedence:--build-context, then source policy, thenregistries.conf.
Example policy file that pins alpine:latest to a specific digest:
{
"rules": [
{
"action": "CONVERT",
"selector": {
"identifier": "docker-image://docker.io/library/alpine:latest"
},
"updates": {
"identifier": "docker-image://docker.io/library/alpine@sha256:..."
}
}
]
}
Example policy file that denies all ubuntu images:
{
"rules": [
{
"action": "DENY",
"selector": {
"identifier": "docker-image://docker.io/library/ubuntu:*",
"matchType": "WILDCARD"
}
}
]
}
--squashโ squashes all of the image's new layers into a single new layer. Any preexisting layers? Not squashed, they stay exactly as they are. ๐ซถ--squash-allโ squashes all of the new image's layers (including the ones inherited from a base image) into a single new layer. Everything. One layer. Gone. Iconic.--ssh=default | id[=socket>โ SSH agent socket or keys to expose to the build. You can leave the socket path empty to use the value ofdefault=$SSH_AUTH_SOCK.
To actually use the ssh agent later, hit the --mount option in a RUN instruction inside a Containerfile:
RUN --mount=type=ssh,id=id mycmd
--stage-labelsโ adds metadata labels to all intermediate stage images of the multistage build, including the final image (default isfalse). This option requires--save-stagesto be enabled. No--save-stages, no labels, that's the deal ๐
When enabled, all intermediate stage images and final image get labeled with:
io.buildah.stage.name: the stage alias (fromFROM ... AS alias), or stage position if no alias is specifiedio.buildah.stage.base: the base image used by this stage (pullspec or image ID when stage uses another stage as base)
These labels make it easier to identify, query, and manage images from multi-stage builds. Lowkey a lifesaver when you've got like nine stages and no idea which is which ๐ญ
--stdinโ passes stdin into theRUNcontainers. Sometimes commands beingRUNwithin a Containerfile want to request info from the user โ thinkaptasking for a confirmation for install. Use--stdinso you can actually interact from the terminal during the build. It's giving "let me in, I promise I'll answer" ๐--tag,-t=imageNameโ specifies the name assigned to the resulting image if the build process completes successfully. If imageName doesn't include a registry name, the registry namelocalhostis prepended to the image name. Considerate of it โจ--target=stageNameโ sets the target build stage to build. When you're building a Containerfile with multiple build stages,--targetlets you specify an intermediate build stage by name as the final stage for the resulting image. Commands after the target stage are skipped. Bye bestie, we stop here ๐--timestamp=secondsโ sets the create timestamp to seconds since epoch, which allows for deterministic builds (defaults to current time). By default the created timestamp gets changed and written into the image manifest with every commit, which makes the image's sha256 hash different even if the sources are exactly the same otherwise. When--timestampis set, the created timestamp is always set to the time specified and therefore doesn't change, so the image's sha256 hash stays the same. All files committed to the layers of the image are created with the timestamp.
If the only instruction in a Containerfile is FROM, this flag has no effect. Nothing to timestamp, nothing to do ๐ซ
--tls-verifyโ requires HTTPS and verifies certificates when contacting registries (default:true). If explicitly set totrue, TLS verification is used. If set tofalse, TLS verification is not used. If not specified, TLS verification is used unless the target registry is listed as an insecure registry incontainers-registries.conf(5). Stay safe out there ๐ฅ--ulimit=type=soft-limit[:hard-limit]โ specifies resource limits to apply to processes launched when processingRUNinstructions. Can be specified multiple times. Recognized resource types include:"core": maximum core dump size (ulimit -c)"cpu": maximum CPU time (ulimit -t)"data": maximum size of a process's data segment (ulimit -d)"fsize": maximum size of new files (ulimit -f)"locks": maximum number of file locks (ulimit -x)"memlock": maximum amount of locked memory (ulimit -l)"msgqueue": maximum amount of data in message queues (ulimit -q)"nice": niceness adjustment (nice -n,ulimit -e)"nofile": maximum number of open files (ulimit -n)"nproc": maximum number of processes (ulimit -u)"rss": maximum size of a process's (ulimit -m)"rtprio": maximum real-time scheduling priority (ulimit -r)"rttime": maximum amount of real-time execution between blocking syscalls"sigpending": maximum number of pending signals (ulimit -i)"stack": maximum stack size (ulimit -s)
--unsetannotation=annotationโ unsets the image annotation, which means the annotation doesn't get inherited from the base image. Not on my watch ๐ โโ๏ธ--unsetenv=envโ unsets environment variables from the final image.--unsetlabel=labelโ unsets the image label, so the label doesn't get inherited from the base image.--userns=howโ sets the configuration for user namespaces when handlingRUNinstructions. The value can be""(the empty string) or"container"to indicate a new user namespace is created; it can be"host"to indicate that the user namespace podman itself is running in gets reused; or it can be the path to a user namespace that's already in use by another process. Choose your fighter ๐--userns-gid-map=mappingโ directly specifies a GID mapping used to set ownership, at the filesystem level, on the working container's contents. Commands run when handlingRUNinstructions default to running in their own user namespaces, configured using the UID and GID maps.
Entries in this map take the form of one or more triples: a starting in-container GID, a corresponding starting host-level GID, and the number of consecutive IDs the map entry represents.
This option overrides the remap-gids setting in the options section of /etc/containers/storage.conf.
If this option isn't specified but a global --userns-gid-map setting is supplied, the settings from the global option are used.
If none of --userns-uid-map-user, --userns-gid-map-group, or --userns-gid-map are specified, but --userns-uid-map is specified, the GID map is set to use the same numeric values as the UID map. Matching, cute ๐
--userns-gid-map-group=groupโ specifies that a GID mapping used to set ownership, at the filesystem level, on the working container's contents, can be found in entries in the/etc/subgidfile corresponding to the specified group. Commands run when handlingRUNinstructions default to running in their own user namespaces, configured using the UID and GID maps. If--userns-uid-map-useris specified but--userns-gid-map-groupisn't, podman assumes the specified user name is also a suitable group name to use as the default setting for this option.
NOTE: when this option is specified by a rootless user, the specified mappings are relative to the rootless user namespace in the container, rather than being relative to the host as it is when run rootful. Different frame of reference, bestie โ don't get it twisted ๐ซถ
--userns-uid-map=mappingโ directly specifies a UID mapping used to set ownership, at the filesystem level, on the working container's contents. Commands run when handlingRUNinstructions default to running in their own user namespaces, configured using the UID and GID maps.
Entries in this map take the form of one or more triples: a starting in-container UID, a corresponding starting host-level UID, and the number of consecutive IDs the map entry represents.
This option overrides the remap-uids setting in the options section of /etc/containers/storage.conf.
If this option isn't specified but a global --userns-uid-map setting is supplied, the settings from the global option are used.
If none of --userns-uid-map-user, --userns-gid-map-group, or --userns-uid-map are specified, but --userns-gid-map is specified, the UID map is set to use the same numeric values as the GID map. Symmetry slay โจ
--userns-uid-map-user=userโ okay so this one is saying: the UID mapping we use to set ownership (at the filesystem level, bestie, on the working container's contents) can be found in entries in the/etc/subuidfile that correspond to the user you name here. Commands that run when handlingRUNinstructions default to running in their own user namespaces, configured using the UID and GID maps. And here's a cute little default for you: if--userns-gid-map-groupis specified but--userns-uid-map-useris not, podman just assumes that the group name you gave is also a suitable user name to use as the default setting for this option. Efficiency! ๐
NOTE: if a rootless user specifies this option, the mappings you give are relative to the rootless user namespace in the container โ not relative to the host like it is when you run rootful. Big difference, don't get it twisted fr fr.
--uts=howโ sets the config for UTS namespaces when handlingRUNinstructions. The value can be""(the empty string) or"container"to say "make a new UTS namespace", or"host"to say "reuse the UTS namespace podman itself is running in", or it can be the path to a UTS namespace that's already in use by another process. Three vibes, one flag โจ--variant=VARIANTโ sets the architecture variant of the image being built (and of the base image being pulled, if the build uses one) to whatever value you give here, instead of using the architecture variant of the build host. You're the main character, not your machine ๐ซถ--volume,-v=[HOST-DIR:CONTAINER-DIR[:OPTIONS]]โ mounts a host directory into containers when executingRUNinstructions during the build.
The OPTIONS are a comma-separated list, and can be one or more of:
[rw|ro][z|Z|O][U][[r]shared|[r]slave|[r]private][1]โจ#Footnote1โฉ
The CONTAINER-DIR must be an absolute path like /src/docs. The HOST-DIR must be an absolute path too, no exceptions. Podman bind-mounts the HOST-DIR to the specified path when it's processing RUN instructions.
You can specify multiple -v options to mount one or more mounts. Stack 'em up ๐
You can tack on the :ro or :rw suffix to a volume to mount it read-only or read-write respectively. By default, volumes are mounted read-write. See examples below.
๐ Chowning Volume Mounts
By default, Podman does not change the owner and group of source volume directories that get mounted. But when you're running with user namespaces, the UID and GID inside the namespace may correspond to a totally different UID and GID on the host. Sneaky!
The :U suffix tells Podman to use the correct host UID and GID based on the UID and GID within the namespace, and to recursively change the owner and group of the source volume.
Warning: use with caution, bestie, because this modifies the host filesystem. Like, actually changes it. ๐ญ
๐ธ Labeling Volume Mounts
Labeling systems like SELinux require proper labels on volume content that gets mounted into a container. Without a label, the security system might straight-up prevent the processes running inside the container from using that content. By default, Podman doesn't change the labels set by the OS.
To change a label in the container context, add one of these two suffixes, :z or :Z, to the volume mount. These suffixes tell Podman to relabel file objects on the shared volumes. The z option tells Podman that two containers share the volume content โ so Podman labels the content with a shared content label, and shared volume labels allow all containers to read/write the content. The Z option tells Podman to label the content with a private unshared label, and only the current container can use a private volume. iykyk ๐
Note: do not relabel system files and directories. Relabeling system content might cause other confined services on the host machine to fail, and that's giving chaos. For these types of containers, disabling SELinux separation is recommended โ the option --security-opt label=disable disables SELinux separation for the container. For example, if a user wanted to volume mount their entire home directory into the build containers, they need to disable SELinux separation:
$ podman build --security-opt label=disable -v $HOME:/home/user .
๐ฆ Overlay Volume Mounts
The :O flag tells Podman to mount the directory from the host as temporary storage using the Overlay file system. The RUN command containers are allowed to modify contents within the mountpoint, and those are stored in the container storage in a separate directory. In Overlay FS terms, the source directory is the lower, and the container storage directory is the upper. Modifications to the mount point get destroyed when the RUN command finishes executing โ similar to a tmpfs mount point. Poof, gone โจ
Any subsequent execution of RUN commands sees the original source directory content, and any changes from previous RUN commands no longer exist. Fresh start every time, honestly iconic.
One use case of the overlay mount is sharing the package cache from the host into the container to allow speeding up builds. Speed queen behavior ๐ฅ
Note:
- Overlay mounts are not currently supported in rootless mode.
- The
Oflag is not allowed to be specified with theZorzflags. Content mounted into the container is labeled with the private label. On SELinux systems, labels in the source directory need to be readable by the container label. If not, SELinux container separation must be disabled for the container to work. - Modification of the directory volume mounted into the container with an overlay mount can cause unexpected failures. Do not modify the directory until the container finishes running. Hands off until it's done ๐
By default bind mounted volumes are private. That means any mounts done inside containers are not visible on the host, and vice versa. This behavior can be changed by specifying a volume mount propagation property.
When the mount propagation policy is set to shared, any mounts completed inside the container on that volume are visible to both the host and container. When the mount propagation policy is set to slave, one-way mount propagation is enabled and any mounts completed on the host for that volume are visible only inside the container. To control the mount propagation property of a volume, use the :[r]shared, :[r]slave or :[r]private propagation flag. For mount propagation to work, the source mount point (the mount point where the source dir is mounted on) has to have the right propagation properties. For shared volumes, the source mount point has to be shared. And for slave volumes, the source mount has to be either shared or slave. [1] โจ#Footnote1โฉ
Use df <source-dir> to determine the source mount, and then use findmnt -o TARGET,PROPAGATION <source-mount-dir> to determine the propagation properties of the source mount. If the findmnt utility isn't available, the source mount point can be determined by looking at the mount entry in /proc/self/mountinfo โ look at the optional fields and see if any propagation properties are specified. shared:X means the mount is shared, master:X means the mount is slave, and if nothing's there, that means the mount is private. [1] โจ#Footnote1โฉ
To change the propagation properties of a mount point, use the mount command. For example, to bind mount the source directory /foo, do mount --bind /foo /foo and mount --make-private --make-shared /foo. That converts /foo into a shared mount point. The propagation properties of the source mount can be changed directly โ for instance, if / is the source mount for /foo, then use mount --make-shared / to convert / into a shared mount. Slay ๐
โจ EXAMPLES โจ
Okay bestie, this is the fun part โ actual commands. ๐
๐ง Build an image using local Containerfiles ๐ง
Build image using Containerfile with content from current directory:
$ podman build .
Build image using specified Containerfile with content from current directory:
$ podman build -f Containerfile.simple .
Build image using Containerfile from stdin with content from current directory:
$ cat $HOME/Containerfile | podman build -f - .
Build image using multiple Containerfiles with content from current directory:
$ podman build -f Containerfile.simple -f Containerfile.notsosimple .
Build image with specified Containerfile with content from $HOME directory. Note cpp is applied to Containerfile.in before processing as Containerfile:
$ podman build -f Containerfile.in $HOME
Build image with the specified tag with Containerfile and content from current directory:
$ podman build -t imageName .
Build image ignoring registry verification for any images pulled via the Containerfile:
$ podman build --tls-verify=false -t imageName .
Build image with the specified logging format:
$ podman build --runtime-flag log-format=json .
Build image using debug mode for logging:
$ podman build --runtime-flag debug .
Build image using specified registry attributes when pulling images from the selected Containerfile:
$ podman build --authfile /tmp/auths/myauths.json --cert-dir $HOME/auth --tls-verify=true --creds=username:password -t imageName -f Containerfile.simple .
Build image using specified resource controls when running containers during the build:
$ podman build --memory 40m --cpu-period 10000 --cpu-quota 50000 --ulimit nofile=1024:1028 -t imageName .
Build image using specified SELinux labels and cgroup config running containers during the build:
$ podman build --security-opt label=level:s0:c100,c200 --cgroup-parent /path/to/cgroup/parent -t imageName .
Build image with read-only and SELinux relabeled volume mounted from the host into running containers during the build:
$ podman build --volume /home/test:/myvol:ro,Z -t imageName .
Build image with overlay volume mounted from the host into running containers during the build:
$ podman build -v /var/lib/yum:/var/lib/yum:O -t imageName .
Build image using layers and then removing intermediate containers even if the build fails.
$ podman build --layers --force-rm -t imageName .
Build image ignoring cache and not removing intermediate containers even if the build succeeds:
$ podman build --no-cache --rm=false -t imageName .
Build image using the specified network when running containers during the build:
$ podman build --network mynet .
Build an image using a secret stored in an environment variable or file named mysecret to be used with the instruction RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret:
$ podman build --secret=id=mysecret .
Build an image using a secret stored in an environment variable named MYSECRET to be used with the instruction RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret:
$ podman build --secret=id=mysecret,env=MYSECRET .
$ podman build --secret=id=mysecret,src=MYSECRET,type=env .
Build an image using a secret stored in a file named .mysecret to be used with the instruction RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret:
$ podman build --secret=id=mysecret,src=.mysecret .
$ podman build --secret=id=mysecret,src=.mysecret,type=file .
๐ง Building a multi-architecture image using the --manifest option (requires emulation software) ๐ง
Build image using the specified architectures and link to a single manifest on successful completion:
$ podman build --arch arm --manifest myimage /tmp/mysrc
$ podman build --arch amd64 --manifest myimage /tmp/mysrc
$ podman build --arch s390x --manifest myimage /tmp/mysrc
Similarly build using a single command
$ podman build --platform linux/s390x,linux/ppc64le,linux/amd64 --manifest myimage /tmp/mysrc
Build image using multiple specified architectures and link to single manifest on successful completion:
$ podman build --platform linux/arm64 --platform linux/amd64 --manifest myimage /tmp/mysrc
๐ง Building an image using a URL, Git repo, or archive ๐ง
The build context directory can be specified as a URL to a Containerfile, a Git repository, or URL to an archive. If the URL is a Containerfile, it is downloaded to a temporary location and used as the context. When a Git repository is set as the URL, the repository is cloned locally to a temporary location and then used as the context. Lastly, if the URL is an archive, it is downloaded to a temporary location and extracted before being used as the context. ๐ฆ
๐ Building an image using a URL to a Containerfile ๐
Build image from Containerfile downloaded into temporary location used as the build context:
$ podman build https://10.10.10.1/podman/Containerfile
๐ Building an image using a Git repository ๐
Podman clones the specified GitHub repository to a temporary location and uses it as the context. The Containerfile at the root of the repository is used and it only works if the GitHub repository is a dedicated repository.
Build image from specified git repository downloaded into temporary location used as the build context:
$ podman build -t hello https://github.com/containers/PodmanHello.git
$ podman run hello
Note: GitHub does not support usinggit://for performing clone operation due to recent changes in their security guidance (https://github.blog/2021-09-01-improving-git-protocol-security-github/). Use anhttps://URL if the source repository is hosted on GitHub.
๐ Building an image using a URL to an archive ๐
Podman fetches the archive file, decompresses it, and uses its contents as the build context. The Containerfile at the root of the archive and the rest of the archive are used as the context of the build. Passing the -f PATH/Containerfile option as well tells the system to look for that file inside the contents of the archive.
$ podman build -f dev/Containerfile https://10.10.10.1/podman/context.tar.gz
Note: supported compression formats are 'xz', 'bzip2', 'gzip' and 'identity' (no compression).
๐ Files ๐
๐ .containerignore/.dockerignore ๐
If the file .containerignore or .dockerignore exists in the context directory, podman build reads its contents. Use the --ignorefile option to override the .containerignore path location. Podman uses the content to exclude files and directories from the context directory, when executing COPY and ADD directives in the Containerfile/Dockerfile
The .containerignore and .dockerignore files use the same syntax; if both are in the context directory, podman build only uses .containerignore.
Users can specify a series of Unix shell globs in a .containerignore file to identify files/directories to exclude.
Podman supports a special wildcard string ** which matches any number of directories (including zero). For example, */.go excludes all files that end with .go that are found in all directories.
Example .containerignore file:
# exclude this content for image
*/*.c
**/output*
src
*/*.c Excludes files and directories whose names ends with .c in any top level subdirectory. For example, the source file include/rootless.c.
**/output* Excludes files and directories starting with output from any directory.
src Excludes files named src and the directory src as well as any content in it.
Lines starting with ! (exclamation mark) can be used to make exceptions to exclusions. The following is an example .containerignore file that uses this mechanism:
*.doc
!Help.doc
Exclude all doc files except Help.doc from the image.
This functionality is compatible with the handling of .containerignore files described here: containerignore(5)
๐ registries.conf (/etc/containers/registries.conf) ๐
registries.conf is the configuration file which specifies which container registries is consulted when completing image names which do not include a registry or domain portion. See containers-registries.conf(5)
๐ญ Troubleshooting ๐ญ
๐ซถ lastlog sparse file ๐ซถ
Using a useradd command within a Containerfile with a large UID/GID creates a large sparse file /var/log/lastlog. This can cause the build to hang forever. Go language does not support sparse files correctly, which can lead to some huge files being created in the container image.
When using the useradd command within the build script, pass the --no-log-init or -l option to the useradd command. This option tells useradd to stop creating the lastlog file.
๐ฅ SEE ALSO ๐ฅ
podman(1)buildah(1)containers-certs.d(5)containers-registries.conf(5)crun(1)runc(8)useradd(8)podman-ps(1)podman-rm(1)Containerfile(5)containerignore(5)
๐ซถ Troubleshooting ๐ซถ
See podman-troubleshooting(7) for solutions to common issues.
See podman-rootless(7) for rootless issues.
๐ HISTORY ๐
Aug 2020, Additional options and .containerignore added by Dan Walsh <dwalsh@redhat.com>
May 2018, Minor revisions added by Joe Doss <joe@solidadmin.com>
December 2017, Originally compiled by Tom Sweeney <tsweeney@redhat.com>
๐ FOOTNOTES ๐
1: The Podman project is committed to inclusivity, a core value of open source. The master and slave mount propagation terminology used here is problematic and divisive, and needs to be changed. However, these terms are currently used within the Linux kernel and must be used as-is at this time. When the kernel maintainers rectify this usage, Podman will follow suit immediately.
Cute footer sign-off: this page is podman-build(1) โ that's the source/version stamp in the footer โ and the date? This footer snippet doesn't give one, so I'm not inventing it, periodt. ๐
โจ
๐ฆ where this page comes from
- arch rolling: podman 6.1.4-1 ยท Apache-2.0
- centos-stream 10: podman 7:6.1.0-2.el10 ยท Apache-2.0 AND BSD-2-Clause AND BSD-3-Clause AND ISC AND MIT AND MPL-2.0
- nixpkgs unstable: podman 6.1.4
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms