.\" Man page generated from reStructuredText. . .TH "CH-IMAGE" "1" "2020-12-20 14:44 Coordinated Universal Time" "0.21" "Charliecloud" .SH NAME ch-image \- Build and manage images; completely unprivileged . .nr rst2man-indent-level 0 . .de1 rstReportMargin \\$1 \\n[an-margin] level \\n[rst2man-indent-level] level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] - \\n[rst2man-indent0] \\n[rst2man-indent1] \\n[rst2man-indent2] .. .de1 INDENT .\" .rstReportMargin pre: . RS \\$1 . nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] . nr rst2man-indent-level +1 .\" .rstReportMargin post: .. .de UNINDENT . RE .\" indent \\n[an-margin] .\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] .nr rst2man-indent-level -1 .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. .SH SYNOPSIS .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ ch\-image [...] build [\-t TAG] [\-f DOCKERFILE] [...] CONTEXT $ ch\-image [...] list $ ch\-image [...] pull [...] IMAGE_REF [IMAGE_DIR] $ ch\-image [...] storage\-path $ ch\-image { \-\-help | \-\-version | \-\-dependencies } .ft P .fi .UNINDENT .UNINDENT .SH DESCRIPTION .sp \fBch\-image\fP is a tool for building and manipulating container images, but not running them (for that you want \fBch\-run\fP). It is completely unprivileged, with no setuid/setgid/setcap helpers. .sp Options that print brief information and then exit: .INDENT 0.0 .INDENT 3.5 .INDENT 0.0 .TP .B \fB\-h\fP, \fB\-\-help\fP Print help and exit successfully. .TP .B \fB\-\-dependencies\fP Report dependency problems on standard output, if any, and exit. If all is well, there is no output and the exit is successful; in case of problems, the exit is unsuccessful. .TP .B \fB\-\-version\fP Print version number and exit successfully. .UNINDENT .UNINDENT .UNINDENT .sp Common options placed before the sub\-command: .INDENT 0.0 .INDENT 3.5 .INDENT 0.0 .TP .B \fB\-\-no\-cache\fP Download everything needed, ignoring the cache. .TP .B \fB\-s\fP, \fB\-\-storage DIR\fP Set the storage directory (see below for important details). .TP .B \fB\-\-tls\-no\-verify\fP Don’t verify TLS certificates of the repository. (Do not use this option unless you understand the risks.) .TP .B \fB\-v\fP, \fB\-\-verbose\fP Print extra chatter; can be repeated. .UNINDENT .UNINDENT .UNINDENT .SH STORAGE DIRECTORY .sp \fBch\-image\fP maintains state using normal files and directories, including unpacked container images, located in its \fIstorage directory\fP\&. There is no notion of storage drivers, graph drivers, etc., to select and/or configure. In descending order of priority, this directory is located at: .INDENT 0.0 .INDENT 3.5 .INDENT 0.0 .TP .B \fB\-s\fP, \fB\-\-storage DIR\fP Command line option. .TP .B \fB$CH_IMAGE_STORAGE\fP Environment variable. .TP .B \fB/var/tmp/$USER/ch\-image\fP Default. .UNINDENT .UNINDENT .UNINDENT .sp The storage directory can reside on any filesystem. However, it contains lots of small files and metadata traffic can be intense. For example, the Charliecloud test suite uses approximately 400,000 files and directories in the storage directory as of this writing. Place it on a filesystem appropriate for this; tmpfs’es such as \fB/var/tmp\fP are a good choice if you have enough RAM (\fB/tmp\fP is not recommended because \fBch\-run\fP bind\-mounts it into containers by default). .sp While you can currently poke around in the storage directory and find unpacked images runnable with \fBch\-run\fP, this is not a supported use case. The supported workflow uses \fBch\-builder2tar\fP or \fBch\-builder2squash\fP to obtain a packed image; see the tutorial for details. .sp \fBWARNING:\fP .INDENT 0.0 .INDENT 3.5 Network filesystems, especially Lustre, are typically bad choices for the storage directory. This is a site\-specific question and your local support will likely have strong opinions. .UNINDENT .UNINDENT .SH SUBCOMMANDS .SS \fBbuild\fP .sp Build an image from a Dockerfile and put it in the storage directory. Use \fBch\-run(1)\fP to execute \fBRUN\fP instructions. .sp Required argument: .INDENT 0.0 .INDENT 3.5 .INDENT 0.0 .TP .B \fBCONTEXT\fP Path to context directory; this is the root of \fBCOPY\fP and \fBADD\fP instructions in the Dockerfile. .UNINDENT .UNINDENT .UNINDENT .sp Options: .INDENT 0.0 .INDENT 3.5 .INDENT 0.0 .TP .B \fB\-b\fP, \fB\-\-bind SRC[:DST]\fP Bind\-mount host directory \fBSRC\fP at container directory \fBDST\fP during \fBRUN\fP instructions. Can be repeated; the default destination if \fBDST\fP is omitted is \fB/mnt/0\fP, \fB/mnt/1\fP, etc. .sp \fBNote:\fP This applies only to \fBRUN\fP instructions. Other instructions that modify the image filesystem, e.g. \fBCOPY\fP, can only access host files from the context directory. .TP .B \fB\-\-build\-arg KEY[=VALUE]\fP Set build\-time variable \fBKEY\fP defined by \fBARG\fP instruction to \fBVALUE\fP\&. If \fBVALUE\fP not specified, use the value of environment variable \fBKEY\fP\&. .TP .B \fB\-f\fP, \fB\-\-file DOCKERFILE\fP Use \fBDOCKERFILE\fP instead of \fBCONTEXT/Dockerfile\fP\&. Specify a single hyphen (\fB\-\fP) to use standard input; note that in this case, the context directory is still provided, which matches \fBdocker build \-f \-\fP behavior. .TP .B \fB\-\-force\fP Inject the unprivileged build workarounds; see discussion later in this section for details on what this does and when you might need it. If a build fails and \fBch\-image\fP thinks \fB\-\-force\fP would help, it will suggest it. .TP .B \fB\-n\fP, \fB\-\-dry\-run\fP Don’t actually execute any Dockerfile instructions. .TP .B \fB\-\-no\-force\-detect\fP Don’t try to detect if the workarounds in \fB\-\-force\fP would help. .TP .B \fB\-\-parse\-only\fP Stop after parsing the Dockerfile. .TP .B \fB\-t\fP, \fB\-tag TAG\fP Name of image to create. If not specified, use the final component of path \fBCONTEXT\fP\&. Append \fB:latest\fP if no colon present. .UNINDENT .UNINDENT .UNINDENT .sp \fBch\-image\fP is a \fIfully\fP unprivileged image builder. It does not use any setuid or setcap helper programs, and it does not use configuration files \fB/etc/subuid\fP or \fB/etc/subgid\fP\&. This contrasts with the “rootless” or “\fI\%fakeroot\fP” modes of some competing builders, which do require privileged supporting code or utilities. .sp This approach does yield some quirks. We provide built\-in workarounds that should mostly work (i.e., \fB\-\-force\fP), but it can be helpful to understand what is going on. .sp \fBch\-image\fP executes all instructions as the normal user who invokes it. For \fIRUN\fP, this is accomplished with \fBch\-run \-w \-\-uid=0 \-\-gid=0\fP (and some other arguments), i.e., your host EUID and EGID both mapped to zero inside the container, and only one UID (zero) and GID (zero) are available inside the container. Under this arrangement, processes running in the container for each \fBRUN\fP \fIappear\fP to be running as root, but many privileged system calls will fail without the workarounds described below. \fBThis affects any fully unprivileged container build, not just Charliecloud.\fP .sp The most common time to see this is installing packages. For example, here is RPM failing to \fBchown(2)\fP a file, which makes the package update fail: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C Updating : 1:dbus\-1.10.24\-13.el7_6.x86_64 2/4 Error unpacking rpm package 1:dbus\-1.10.24\-13.el7_6.x86_64 error: unpacking of archive failed on file /usr/libexec/dbus\-1/dbus\-daemon\-launch\-helper;5cffd726: cpio: chown Cleanup : 1:dbus\-libs\-1.10.24\-12.el7.x86_64 3/4 error: dbus\-1:1.10.24\-13.el7_6.x86_64: install failed .ft P .fi .UNINDENT .UNINDENT .sp This one is (ironically) \fBapt\-get\fP failing to drop privileges: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C E: setgroups 65534 failed \- setgroups (1: Operation not permitted) E: setegid 65534 failed \- setegid (22: Invalid argument) E: seteuid 100 failed \- seteuid (22: Invalid argument) E: setgroups 0 failed \- setgroups (1: Operation not permitted) .ft P .fi .UNINDENT .UNINDENT .sp By default, nothing is done to avoid these problems, though \fBch\-image\fP does try to detect if the workarounds could help. \fB\-\-force\fP activates the workarounds: \fBch\-image\fP injects extra commands to intercept these system calls and fake a successful result, using \fBfakeroot(1)\fP\&. There are three basic steps: .INDENT 0.0 .INDENT 3.5 .INDENT 0.0 .IP 1. 3 After \fBFROM\fP, analyze the image to see what distribution it contains, which determines the specific workarounds. .IP 2. 3 Before the user command in the first \fBRUN\fP instruction where the injection seems needed, install \fBfakeroot(1)\fP in the image, if one is not already installed, as well as any other necessary initialization commands. For example, we turn off the \fBapt\fP sandbox (for Debian Buster) and configure EPEL but leave it disabled (for CentOS/RHEL). .IP 3. 3 Prepend \fBfakeroot\fP to \fBRUN\fP instructions that seem to need it, e.g. ones that contain \fBapt\fP, \fBapt\-get\fP, \fBdpkg\fP for Debian derivatives and \fBdnf\fP, \fBrpm\fP, or \fByum\fP for RPM\-based distributions. .UNINDENT .UNINDENT .UNINDENT .sp The details are specific to each distribution. \fBch\-image\fP analyzes image content (e.g., grepping \fB/etc/debian_version\fP) to select a configuration; see \fBlib/fakeroot.py\fP for details. \fBch\-image\fP prints exactly what it is doing. .SS \fBstorage\-path\fP .sp Print the storage directory path and exit. .SS \fBpull\fP .sp Pull the image described by the image reference \fBIMAGE_REF\fP from a repository by HTTPS. See the FAQ for the gory details on specifying image references. .sp This script does a fair amount of validation and fixing of the layer tarballs before flattening in order to support unprivileged use despite image problems we frequently see in the wild. For example, device files are ignored, and file and directory permissions are increased to a minimum of \fBrwx\-\-\-\-\-\-\fP and \fBrw\-\-\-\-\-\-\-\fP respectively. Note, however, that symlinks pointing outside the image are permitted, because they are not resolved until runtime within a container. .sp Destination argument: .INDENT 0.0 .INDENT 3.5 .INDENT 0.0 .TP .B \fBIMAGE_DIR\fP If specified, place the unpacked image at this path; it is then ready for use by \fBch\-run\fP or other tools. The storage directory will not contain a copy of the image, i.e., it is only unpacked once. .UNINDENT .UNINDENT .UNINDENT .sp Options: .INDENT 0.0 .INDENT 3.5 .INDENT 0.0 .TP .B \fB\-\-last\-layer N\fP Unpack only \fBN\fP layers, leaving an incomplete image. This option is intended for debugging. .TP .B \fB\-\-parse\-only\fP Parse \fBIMAGE_REF\fP, print a parse report, and exit successfully without talking to the internet or touching the storage directory. .UNINDENT .UNINDENT .UNINDENT .SH COMPATIBILITY WITH OTHER DOCKERFILE INTERPRETERS .sp \fBch\-image\fP is an independent implementation and shares no code with other Dockerfile interpreters. It uses a formal Dockerfile parsing grammar developed from the \fI\%Dockerfile reference documentation\fP and miscellaneous other sources, which you can examine in the source code. .sp We believe this independence is valuable for several reasons. First, it helps the community examine Dockerfile syntax and semantics critically, think rigorously about what is really needed, and build a more robust standard. Second, it yields disjoint sets of bugs (note that Podman, Buildah, and Docker all share the same Dockerfile parser). Third, because it is a much smaller code base, it illustrates how Dockerfiles work more clearly. Finally, it allows straightforward extensions if needed to support scientific computing. .sp \fBch\-image\fP tries hard to be compatible with Docker and other interpreters, though as an independent implementation, it is not bug\-compatible. .sp This section describes differences from the Dockerfile reference that we expect to be approximately permanent. For an overview of features we have not yet implemented and our plans, see our \fI\%road map\fP on GitHub. Plain old bugs are in our \fI\%GitHub issues\fP\&. .sp None of these are set in stone. We are very interested in feedback on our assessments and open questions. This helps us prioritize new features and revise our thinking about what is needed for HPC containers. .SS Context directory .sp The context directory is bind\-mounted into the build, rather than copied like Docker. Thus, the size of the context is immaterial, and the build reads directly from storage like any other local process would. However, you still can’t access anything outside the context directory. .SS Authentication .sp \fBch\-image\fP can authenticate using one\-time passwords, e.g. those provided by a security token. Unlike \fBdocker login\fP, it does not assume passwords are persistent. .SS Environment variables .sp Variable substitution happens for \fIall\fP instructions, not just the ones listed in the Dockerfile reference. .sp \fBARG\fP and \fBENV\fP cause cache misses upon \fIdefinition\fP, in contrast with Docker where these variables miss upon \fIuse\fP, except for certain cache\-excluded variables that never cause misses, listed below. .sp Like Docker, \fBch\-image\fP pre\-defines the following proxy variables, which do not require an \fBARG\fP instruction. However, they are available if the same\-named environment variable is defined; \fB\-\-build\-arg\fP is not required. Changes to these variables do not cause a cache miss. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C HTTP_PROXY http_proxy HTTPS_PROXY https_proxy FTP_PROXY ftp_proxy NO_PROXY no_proxy .ft P .fi .UNINDENT .UNINDENT .sp The following variables are also pre\-defined: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C PATH=/ch/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin TAR_OPTIONS=\-\-no\-same\-owner .ft P .fi .UNINDENT .UNINDENT .sp Note that \fBARG\fP and \fBENV\fP have different syntax despite very similar semantics. .SS \fBCOPY\fP .sp Especially for people used to UNIX \fBcp(1)\fP, the semantics of the Dockerfile \fBCOPY\fP instruction can be confusing. .sp Most notably, when a source of the copy is a directory, the \fIcontents\fP of that directory, not the directory itself, are copied. This is documented, but it’s a real gotcha because that’s not what \fBcp(1)\fP does, and it means that many things you can do in one \fBcp(1)\fP command require multiple \fBCOPY\fP instructions. .sp Also, the reference documentation is incomplete. In our experience, Docker also behaves as follows; \fBch\-image\fP does the same in an attempt to be bug\-compatible. .INDENT 0.0 .IP 1. 3 You can use absolute paths in the source; the root is the context directory. .IP 2. 3 Destination directories are created if they don’t exist in the following situations: .INDENT 3.0 .IP 1. 3 If the destination path ends in slash. (Documented.) .IP 2. 3 If the number of sources is greater than 1, either by wildcard or explicitly, regardless of whether the destination ends in slash. (Not documented.) .IP 3. 3 If there is a single source and it is a directory. (Not documented.) .UNINDENT .IP 3. 3 Symbolic links behave differently depending on how deep in the copied tree they are. (Not documented.) .INDENT 3.0 .IP 1. 3 Symlinks at the top level — i.e., named as the destination or the source, either explicitly or by wildcards —\ are dereferenced. They are followed, and whatever they point to is used as the destination or source, respectively. .IP 2. 3 Symlinks at deeper levels are not dereferenced, i.e., the symlink itself is copied. .UNINDENT .IP 4. 3 If a directory appears at the same path in source and destination, and is at the 2nd level or deeper, the source directory’s metadata (e.g., permissions) are copied to the destination directory. (Not documented.) .IP 5. 3 If an object appears in both the source and destination, and is at the 2nd level or deeper, and is of different types in the source and destination, then the source object will overwrite the destination object. (Not documented.) For example, if \fB/tmp/foo/bar\fP is a regular file, and \fB/tmp\fP is the context directory, then the following Dockerfile snippet will result in a \fIfile\fP in the container at \fB/foo/bar\fP (copied from \fB/tmp/foo/bar\fP); the directory and all its contents will be lost. .INDENT 3.0 .INDENT 3.5 .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C RUN mkdir \-p /foo/bar && touch /foo/bar/baz COPY foo /foo .ft P .fi .UNINDENT .UNINDENT .UNINDENT .UNINDENT .UNINDENT .sp We expect the following differences to be permanent: .INDENT 0.0 .IP \(bu 2 Wildcards use Python glob semantics, not the Go semantics. .IP \(bu 2 \fBCOPY \-\-chown\fP is ignored, because it doesn’t make sense in an unprivileged build. .UNINDENT .SS Features we do not plan to support .INDENT 0.0 .IP \(bu 2 Parser directives are not supported. We have not identified a need for any of them. .IP \(bu 2 \fBEXPOSE\fP: Charliecloud does not use the network namespace, so containerized processes can simply listen on a host port like other unprivileged processes. .IP \(bu 2 \fBHEALTHCHECK\fP: This instruction’s main use case is monitoring server processes rather than applications. Also, implementing it requires a container supervisor daemon, which we have no plans to add. .IP \(bu 2 \fBMAINTAINER\fP is deprecated. .IP \(bu 2 \fBSTOPSIGNAL\fP requires a container supervisor daemon process, which we have no plans to add. .IP \(bu 2 \fBUSER\fP does not make sense for unprivileged builds. .IP \(bu 2 \fBVOLUME\fP: This instruction is not currently supported. Charliecloud has good support for bind mounts; we anticipate that it will continue to focus on that and will not introduce the volume management features that Docker has. .UNINDENT .SH ENVIRONMENT VARIABLES .sp \fBCH_LOG_FILE\fP .INDENT 0.0 .INDENT 3.5 If set, append log chatter to this file, rather than standard error. This is useful for debugging situations where standard error is consumed or lost. .sp Also sets verbose mode if not already set (equivalent to \fB\-\-verbose\fP). .UNINDENT .UNINDENT .sp \fBCH_LOG_FESTOON\fP .INDENT 0.0 .INDENT 3.5 If set, prepend PID and timestamp to logged chatter. .UNINDENT .UNINDENT .SH EXAMPLES .SS \fBbuild\fP .sp Build image \fBbar\fP using \fB\&./foo/bar/Dockerfile\fP and context directory \fB\&./foo/bar\fP: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ ch\-image build \-t bar \-f ./foo/bar/Dockerfile ./foo/bar [...] grown in 4 instructions: bar .ft P .fi .UNINDENT .UNINDENT .sp Same, but infer the image name and Dockerfile from the context directory path: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ ch\-image build ./foo/bar [...] grown in 4 instructions: bar .ft P .fi .UNINDENT .UNINDENT .sp Build using humongous vendor compilers you want to bind\-mount instead of installing into a layer: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ ch\-image build \-\-bind /opt/bigvendor:/opt . $ cat Dockerfile FROM centos:7 RUN /opt/bin/cc hello.c #COPY /opt/lib/*.so /usr/local/lib # fail: COPY doesn\(aqt bind mount RUN cp /opt/lib/*.so /usr/local/lib # possible workaround RUN ldconfig .ft P .fi .UNINDENT .UNINDENT .SS \fBpull\fP .sp Download the Debian Buster image and place it in the storage directory: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ ch\-image pull debian:buster pulling image: debian:buster manifest: downloading layer 1/1: d6ff36c: downloading layer 1/1: d6ff36c: listing validating tarball members resolving whiteouts flattening image layer 1/1: d6ff36c: extracting done .ft P .fi .UNINDENT .UNINDENT .sp Same, except place the image in \fB/tmp/buster\fP: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ ch\-image pull debian:buster /tmp/buster [...] $ ls /tmp/buster bin dev home lib64 mnt proc run srv tmp var boot etc lib media opt root sbin sys usr .ft P .fi .UNINDENT .UNINDENT .SH REPORTING BUGS .sp If Charliecloud was obtained from your Linux distribution, use your distribution’s bug reporting procedures. .sp Otherwise, report bugs to: <\fI\%https://github.com/hpc/charliecloud/issues\fP> .SH SEE ALSO .sp charliecloud(7) .sp Full documentation at: <\fI\%https://hpc.github.io/charliecloud\fP> .SH COPYRIGHT 2014–2020, Triad National Security, LLC .\" Generated by docutils manpage writer. .