Provided by: charliecloud-builders_0.26-1_amd64 bug

NAME

       ch-image - Build and manage images; completely unprivileged

SYNOPSIS

          $ ch-image [...] build [-t TAG] [-f DOCKERFILE] [...] CONTEXT
          $ ch-image [...] delete IMAGE_REF
          $ ch-image [...] import PATH IMAGE_REF
          $ ch-image [...] list [IMAGE_REF]
          $ ch-image [...] pull [...] IMAGE_REF [IMAGE_DIR]
          $ ch-image [...] push [--image DIR] IMAGE_REF [DEST_REF]
          $ ch-image [...] reset
          $ ch-image [...] storage-path
          $ ch-image { --help | --version | --dependencies }

DESCRIPTION

       ch-image  is  a  tool  for building and manipulating container images, but not running them (for that you
       want ch-run). It is completely unprivileged, with no setuid/setgid/setcap helpers. The action to take  is
       specified by a sub-command.

       Options that print brief information and then exit:

          -h, --help
                 Print  help  and exit successfully. If specified before the sub-command, print general help and
                 list of sub-commands; if after the sub-command, print help specific to that sub-command.

          --dependencies
                 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.

          --version
                 Print version number and exit successfully.

       Common options placed before the sub-command:

          -a, --arch ARCH
                 Use  ARCH  for  architecture-aware  registry  operations,  currently pull and pulls done within
                 build. ARCH can be: (1) yolo, to bypass architecture-aware code and use the registry’s  default
                 architecture;  (2)  host, to use the host’s architecture, obtained with the equivalent of uname
                 -m (default  if  --arch  not  specified);  or  (3)  an  architecture  name.  If  the  specified
                 architecture is not available, the error message will list which ones are.

                 Notes:

                 1. ch-image  is  limited  to  one  image  per  image  reference  in  builder storage at a time,
                    regardless of architecture. For example, if you say ch-image pull --arch=foo  baz  and  then
                    ch-image  pull  --arch=bar  baz,  builder  storage will contain one image called “baz”, with
                    architecture “bar”.

                 2. Images’ default architecture is usually  amd64,  so  this  is  usually  what  you  get  with
                    --arch=yolo. Similarly, if a registry image is architecture-unaware, it will still be pulled
                    with --arch=amd64 and --arch=host on x86-64 hosts (other  host  architectures  must  specify
                    --arch=yolo to pull architecture-unaware images).

                 3. uname  -m  and  image  registries  often  use different names for the same architecture. For
                    example, what uname -m reports as “x86_64” is known to registries  as  “amd64”.  --arch=host
                    should  translate  if needed, but it’s useful to know this is happening.  Directly specified
                    architecture names are passed to the registry without translation.

                 4. Registries treat architecture as a pair of items, architecture and sometimes variant  (e.g.,
                    “arm”  and  “v7”).  Charliecloud treats architecture as a simple string and converts to/from
                    the registry view transparently.

          --no-cache
                 Download everything needed, ignoring the cache.

          --password-many
                 Re-prompt the user every time a registry password is needed.

          -s, --storage DIR
                 Set the storage directory (see below for important details).

          --tls-no-verify
                 Don’t verify TLS certificates of the repository. (Do not use this option unless you  understand
                 the risks.)

          -v, --verbose
                 Print extra chatter; can be repeated.

AUTHENTICATION

       If  the remote repository needs authentication, Charliecloud will prompt you for a username and password.
       Note that some repositories call the secret something other than “password”;  e.g.,  GitLab  calls  it  a
       “personal access token (PAT)”.

       These  values  are  remembered  for  the  life  of the process and silently re-offered to the registry if
       needed. One case when this happens is on push to a private registry: many registries will first  offer  a
       read-only  token  when ch-image checks if something exists, then re-authenticate when upgrading the token
       to read-write for upload. If your site uses one-time passwords such as provided by a security device, you
       can specify --password-many to provide a new secret each time.

       These  values are not saved persistently, e.g. in a file. Note that we do use normal Python variables for
       this information, without pinning them into physical RAM with mlock(2) or any other special treatment, so
       we cannot guarantee they will never reach non-volatile storage.

       There  is  no  separate  login  subcommand  like  Docker. For non-interactive authentication, you can use
       environment variables CH_IMAGE_USERNAME and CH_IMAGE_PASSWORD. Only do this if you fully  understand  the
       implications for your specific use case, because it is difficult to securely store secrets in environment
       variables.

STORAGE DIRECTORY

       ch-image maintains state using normal files and directories located in its  storage  directory;  contents
       include temporary images used for building and various caches.

       In descending order of priority, this directory is located at:

          -s, --storage DIR
                 Command line option.

          $CH_IMAGE_STORAGE
                 Environment variable.

          /var/tmp/$USER.ch
                 Default.  (Previously, the default was /var/tmp/$USER/ch-image. If a valid storage directory is
                 found at the old default path, ch-image tries to move it to the new default path.)

       Unlike many container implementations, there is no notion of storage drivers,  graph  drivers,  etc.,  to
       select and/or configure.

       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 /var/tmp are a good choice if you have enough  RAM  (/tmp  is  not  recommended  because
       ch-run bind-mounts it into containers by default).

       While  you  can  currently  poke  around  in the storage directory and find unpacked images runnable with
       ch-run, this is not a supported use case. The supported workflow  uses  ch-convert  to  obtain  a  packed
       image; see the tutorial for details.

       The  storage  directory  format  changes on no particular schedule. Often ch-image is able to upgrade the
       directory; however, downgrading is not supported and sometimes upgrade is not possible. In  these  cases,
       ch-image will refuse to run until you delete and re-initialize the directory with ch-image reset.

       WARNING:
          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.

BUILD

       Build an image from a Dockerfile and put it in the storage directory.

   Synopsis
          $ ch-image [...] build [-t TAG] [-f DOCKERFILE] [...] CONTEXT

   Description
       Uses ch-run -w -u0 -g0 --no-home --no-passwd to execute RUN instructions. Note that FROM implicitly pulls
       the base image if needed, so you may want to read about the pull subcommand below as well.

       Required argument:

          CONTEXT
                 Path to context directory. This is the root of COPY instructions in the Dockerfile. If a single
                 hyphen (-) is specified: (a) read the Dockerfile from standard input, (b) specifying --file  is
                 an  error,  and  (c) there is no context, so COPY will fail. (See --file for how to provide the
                 Dockerfile on standard input while also having a context.)

       Options:

          -b, --bind SRC[:DST]
                 For RUN instructions only, bind-mount  SRC  at  guest  DST.  The  default  destination  if  not
                 specified  is  to  use  the  same  path  as  the  host;  i.e.,  the  default  is  equivalent to
                 --bind=SRC:SRC. If DST does not exist, try to create it as an empty directory, though images do
                 have ten directories /mnt/[0-9] already available as mount points. Can be repeated.

                 Note: See documentation for ch-run --bind for important caveats and gotchas.

                 Note:  Other  instructions  that  modify the image filesystem, e.g.  COPY, can only access host
                 files from the context directory, regardless of this option.

          --build-arg KEY[=VALUE]
                 Set build-time variable KEY defined by ARG instruction to VALUE. If VALUE  not  specified,  use
                 the value of environment variable KEY.

          -f, --file DOCKERFILE
                 Use  DOCKERFILE  instead  of  CONTEXT/Dockerfile. If a single hyphen (-) is specified, read the
                 Dockerfile from standard input; like docker build, the context directory is still available  in
                 this case.

          --force
                 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 ch-image thinks  --force  would
                 help, it will suggest it.

          -n, --dry-run
                 Don’t actually execute any Dockerfile instructions.

          --no-force-detect
                 Don’t try to detect if the workarounds in --force would help.

          --parse-only
                 Stop after parsing the Dockerfile.

          -t, --tag TAG
                 Name of image to create. If not specified, infer the name:

                 1. If  Dockerfile named Dockerfile with an extension: use the extension with invalid characters
                    stripped, e.g.  Dockerfile.@FOO.barfoo.bar.

                 2. If Dockerfile has extension dockerfile: use the basename with the same transformation,  e.g.
                    baz.@QUX.dockerfile -> baz.qux.

                 3. If context directory is not /: use its name, i.e. the last component of the absolute path to
                    the context directory, with the same transformation,

                 4. Otherwise (context directory is /): use root.

                 If no colon present in the name, append :latest.

   Privilege model
       ch-image is a fully unprivileged image builder. It does not use any setuid or setcap helper programs, and
       it  does not use configuration files /etc/subuid or /etc/subgid. This contrasts with the “rootless” or “‐
       fakeroot” modes of some competing builders, which do require privileged supporting code or utilities.

       This approach does yield some quirks. We provide built-in workarounds  that  should  mostly  work  (i.e.,
       --force), but it can be helpful to understand what is going on.

       ch-image executes all instructions as the normal user who invokes it.  For RUN, this is accomplished with
       ch-run -w --uid=0 --gid=0 (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 RUN appear to be running as root, but  many
       privileged  system  calls  will  fail  without  the  workarounds described below.  This affects any fully
       unprivileged container build, not just Charliecloud.

       The most common time to see this is installing packages. For example, here is RPM failing to  chown(2)  a
       file, which makes the package update fail:

            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

       This one is (ironically) apt-get failing to drop privileges:

          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)

       By  default,  nothing  is  done  to  avoid  these  problems,  though  ch-image  does try to detect if the
       workarounds could help. --force activates the workarounds: ch-image injects extra commands  to  intercept
       these system calls and fake a successful result, using fakeroot(1). There are three basic steps:

          1. After  FROM,  analyze the image to see what distribution it contains, which determines the specific
             workarounds.

          2. Before the user command in the first RUN instruction where  the  injection  seems  needed,  install
             fakeroot(1)  in  the  image,  if  one  is  not  already  installed,  as well as any other necessary
             initialization commands. For example, we turn off the apt sandbox (for Debian Buster) and configure
             EPEL but leave it disabled (for CentOS/RHEL).

          3. Prepend  fakeroot  to  RUN  instructions that seem to need it, e.g. ones that contain apt, apt-get,
             dpkg for Debian derivatives and dnf, rpm, or yum for RPM-based distributions.

       The details  are  specific  to  each  distribution.  ch-image  analyzes  image  content  (e.g.,  grepping
       /etc/debian_version)  to select a configuration; see lib/fakeroot.py for details. ch-image prints exactly
       what it is doing.

   Compatibility with other Dockerfile interpreters
       ch-image is an independent implementation and shares no code with other Dockerfile interpreters. It  uses
       a   formal  Dockerfile  parsing  grammar  developed  from  the  Dockerfile  reference  documentation  and
       miscellaneous other sources, which you can examine in the source code.

       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.

       ch-image  tries  hard  to  be  compatible  with  Docker  and other interpreters, though as an independent
       implementation, it is not bug-compatible.

       The following subsections describe differences from  the  Dockerfile  reference  that  we  expect  to  be
       approximately  permanent.  For  not-yet-implemented features and bugs in this area, see related issues on
       GitHub.

       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.

   Context directory
       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.

   Variable substitution
       Variable substitution happens for all instructions, not just the ones listed in the Dockerfile reference.

       ARG  and  ENV cause cache misses upon definition, in contrast with Docker where these variables miss upon
       use, except for certain cache-excluded variables that never cause misses, listed below.

       ch-image passes the following proxy environment variables in to the build. Changes to these variables  do
       not  cause  a  cache  miss.  They  do  not  require  an  ARG instruction, as documented in the Dockerfile
       reference. Unlike Docker,  they  are  available  if  the  same-named  environment  variable  is  defined;
       --build-arg is not required.

          HTTP_PROXY
          http_proxy
          HTTPS_PROXY
          https_proxy
          FTP_PROXY
          ftp_proxy
          NO_PROXY
          no_proxy

       In  addition  to those listed in the Dockerfile reference, these environment variables are passed through
       in the same way:

          SSH_AUTH_SOCK
          USER

       Finally, these variables are also pre-defined but are unrelated to the host environment:

          PATH=/ch/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
          TAR_OPTIONS=--no-same-owner

       Note that ARG and ENV have different syntax despite very similar semantics.

   COPY
       Especially for people used to UNIX cp(1), the  semantics  of  the  Dockerfile  COPY  instruction  can  be
       confusing.

       Most notably, when a source of the copy is a directory, the contents of that directory, not the directory
       itself, are copied. This is documented, but it’s a real gotcha because that’s not what cp(1) does, and it
       means that many things you can do in one cp(1) command require multiple COPY instructions.

       Also,  the  reference  documentation  is  incomplete.  In our experience, Docker also behaves as follows;
       ch-image does the same in an attempt to be bug-compatible.

       1. You can use absolute paths in the source; the root is the context directory.

       2. Destination directories are created if they don’t exist in the following situations:

          1. If the destination path ends in slash. (Documented.)

          2. If the number of sources is greater than 1, either by wildcard or explicitly, regardless of whether
             the destination ends in slash. (Not documented.)

          3. If there is a single source and it is a directory. (Not documented.)

       3. Symbolic links behave differently depending on how deep in the copied tree they are. (Not documented.)

          1. 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.

          2. Symlinks at deeper levels are not dereferenced, i.e., the symlink itself is copied.

       4. 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.)

       5. 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 /tmp/foo/bar is a regular file, and /tmp is the context
          directory, then the following Dockerfile snippet will result in a file in the  container  at  /foo/bar
          (copied from /tmp/foo/bar); the directory and all its contents will be lost.

                 RUN mkdir -p /foo/bar && touch /foo/bar/baz
                 COPY foo /foo

       We expect the following differences to be permanent:

       • Wildcards use Python glob semantics, not the Go semantics.

       • COPY --chown is ignored, because it doesn’t make sense in an unprivileged build.

   Features we do not plan to support
       • Parser directives are not supported. We have not identified a need for any of them.

       • EXPOSE:  Charliecloud  does not use the network namespace, so containerized processes can simply listen
         on a host port like other unprivileged processes.

       • HEALTHCHECK: 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.

       • MAINTAINER is deprecated.

       • STOPSIGNAL requires a container supervisor daemon process, which we have no plans to add.

       • USER does not make sense for unprivileged builds.

       • VOLUME:  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.

   Examples
       Build image bar using ./foo/bar/Dockerfile and context directory ./foo/bar:

          $ ch-image build -t bar -f ./foo/bar/Dockerfile ./foo/bar
          [...]
          grown in 4 instructions: bar

       Same, but infer the image name and Dockerfile from the context directory path:

          $ ch-image build ./foo/bar
          [...]
          grown in 4 instructions: bar

       Build using humongous vendor compilers you want to bind-mount instead of installing into the image:

          $ 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't bind mount
          RUN cp /opt/lib/*.so /usr/local/lib  # possible workaround
          RUN ldconfig

DELETE

          $ ch-image [...] delete IMAGE_REF

       Delete the image described by the image reference IMAGE_REF from the storage directory.

LIST

       Print information about images. If no argument given, list the images in builder storage.

   Synopsis
          $ ch-image [...] list [IMAGE_REF]

   Description
       Optional argument:

          IMAGE_REF
                 Print details of what’s known about IMAGE_REF, both locally and in the remote registry, if any.

   Examples
       List images in builder storage:

          $ ch-image list
          alpine:3.9 (amd64)
          alpine:latest (amd64)
          debian:buster (amd64)

       Print details about Debian Buster image:

          $ ch-image list debian:buster
          details of image:    debian:buster
          in local storage:    no
          full remote ref:     registry-1.docker.io:443/library/debian:buster
          available remotely:  yes
          remote arch-aware:   yes
          host architecture:   amd64
          archs available:     386 amd64 arm/v5 arm/v7 arm64/v8 mips64le ppc64le s390x

IMPORT

          $ ch-image [...] import PATH IMAGE_REF

       Copy the image at PATH into builder storage with name IMAGE_REF. PATH can be:

       • an image directory

       • a tarball with no top-level directory (a.k.a. a “tarbomb”)

       • a standard tarball with one top-level directory

       If  the  imported  image  contains  Charliecloud  metadata, that will be imported unchanged, i.e., images
       exported from ch-image builder storage will be functionally identical when re-imported.

PULL

       Pull the image described by the image reference IMAGE_REF from a repository to the local filesystem.

   Synopsis
          $ ch-image [...] pull [...] IMAGE_REF [IMAGE_DIR]

       See the FAQ for the gory details on specifying image references.

   Description
       Destination:

          IMAGE_DIR
                 If specified, place the unpacked image at this path; it is then ready  for  use  by  ch-run  or
                 other  tools.  The  storage  directory  will  not contain a copy of the image, i.e., it is only
                 unpacked once.

       Options:

          --last-layer N
                 Unpack only N layers, leaving an incomplete image. This option is intended for debugging.

          --parse-only
                 Parse IMAGE_REF, print a parse report, and exit successfully without talking to the internet or
                 touching the storage directory.

       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 rwx------ and
       rw------- respectively. Note, however, that symlinks pointing outside the image  are  permitted,  because
       they are not resolved until runtime within a container.

       The  following metadata in the pulled image is retained; all other metadata is currently ignored. (If you
       have a need for additional metadata, please let us know!)

          • Current working directory set with WORKDIR is effective in downstream Dockerfiles.

          • Environment variables set with ENV are effective in  downstream  Dockerfiles  and  also  written  to
            /ch/environment for use in ch-run --set-env.

          • Mount  point  directories specified with VOLUME are created in the image if they don’t exist, but no
            other action is taken.

       Note that some images (e.g., those with a “version 1 manifest”) do not contain  metadata.  A  warning  is
       printed in this case.

   Examples
       Download the Debian Buster image matching the host’s architecture and place it in the storage directory:

          $ uname -m
          aarch32
          pulling image:    debian:buster
          requesting arch:  arm64/v8
          manifest list: downloading
          manifest: downloading
          config: downloading
          layer 1/1: c54d940: downloading
          flattening image
          layer 1/1: c54d940: listing
          validating tarball members
          resolving whiteouts
          layer 1/1: c54d940: extracting
          image arch: arm64
          done

       Same, specifying the architecture explicitly:

          $ ch-image --arch=arm/v7 pull debian:buster
          pulling image:    debian:buster
          requesting arch:  arm/v7
          manifest list: downloading
          manifest: downloading
          config: downloading
          layer 1/1: 8947560: downloading
          flattening image
          layer 1/1: 8947560: listing
          validating tarball members
          resolving whiteouts
          layer 1/1: 8947560: extracting
          image arch: arm (may not match host arm64/v8)

       Download the same image and place it in /tmp/buster:

          $ 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

PUSH

       Push the image described by the image reference IMAGE_REF from the local filesystem to a repository.

   Synopsis
          $ ch-image [...] push [--image DIR] IMAGE_REF [DEST_REF]

       See the FAQ for the gory details on specifying image references.

   Description
       Destination:

          DEST_REF
                 If specified, use this as the destination image reference, rather than IMAGE_REF. This lets you
                 push to a repository without permanently adding a tag to the image.

       Options:

          --image DIR
                 Use the unpacked image located at DIR rather than an  image  in  the  storage  directory  named
                 IMAGE_REF.

       Because Charliecloud is fully unprivileged, the owner and group of files in its images are not meaningful
       in the broader ecosystem. Thus,  when  pushed,  everything  in  the  image  is  flattened  to  user:group
       root:root.  Also,  setuid/setgid  bits  are  removed,  to  avoid  surprises  if  the image is pulled by a
       privileged container implementation.

   Examples
       Push a local image to the registry example.com:5000 at path /foo/bar with tag latest. Note that  in  this
       form, the local image must be named to match that remote reference.

          $ ch-image push example.com:5000/foo/bar:latest
          pushing image:   example.com:5000/foo/bar:latest
          layer 1/1: gathering
          layer 1/1: preparing
          preparing metadata
          starting upload
          layer 1/1: a1664c4: checking if already in repository
          layer 1/1: a1664c4: not present, uploading
          config: 89315a2: checking if already in repository
          config: 89315a2: not present, uploading
          manifest: uploading
          cleaning up
          done

       Same,  except  use  local image alpine:3.9. In this form, the local image name does not have to match the
       destination reference.

          $ ch-image push alpine:3.9 example.com:5000/foo/bar:latest
          pushing image:   alpine:3.9
          destination:     example.com:5000/foo/bar:latest
          layer 1/1: gathering
          layer 1/1: preparing
          preparing metadata
          starting upload
          layer 1/1: a1664c4: checking if already in repository
          layer 1/1: a1664c4: not present, uploading
          config: 89315a2: checking if already in repository
          config: 89315a2: not present, uploading
          manifest: uploading
          cleaning up
          done

       Same, except use unpacked image located at /var/tmp/image rather  than  an  image  in  ch-image  storage.
       (Also, the sole layer is already present in the remote registry, so we don’t upload it again.)

          $ ch-image push --image /var/tmp/image example.com:5000/foo/bar:latest
          pushing image:   example.com:5000/foo/bar:latest
          image path:      /var/tmp/image
          layer 1/1: gathering
          layer 1/1: preparing
          preparing metadata
          starting upload
          layer 1/1: 892e38d: checking if already in repository
          layer 1/1: 892e38d: already present
          config: 546f447: checking if already in repository
          config: 546f447: not present, uploading
          manifest: uploading
          cleaning up
          done

RESET

          $ ch-image [...] reset

       Delete all images and cache from ch-image builder storage.

STORAGE-PATH

          $ ch-image [...] storage-path

       Print the storage directory path and exit.

ENVIRONMENT VARIABLES

       CH_IMAGE_USERNAME, CH_IMAGE_PASSWORD
              Username   and   password   for   registry   authentication.  See  important  caveats  in  section
              “Authentication” above.

       CH_LOG_FILE
              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.

              Also sets verbose mode if not already set (equivalent to --verbose).

       CH_LOG_FESTOON
              If set, prepend PID and timestamp to logged chatter.

REPORTING BUGS

       If  Charliecloud  was  obtained  from  your  Linux  distribution,  use  your distribution’s bug reporting
       procedures.

       Otherwise, report bugs to: https://github.com/hpc/charliecloud/issues

SEE ALSO

       charliecloud(7)

       Full documentation at: <https://hpc.github.io/charliecloud>

COPYRIGHT

       2014–2021, Triad National Security, LLC