summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/images/pull.go28
-rw-r--r--docs/source/markdown/podman-pull.1.md131
-rw-r--r--test/e2e/pull_test.go18
3 files changed, 111 insertions, 66 deletions
diff --git a/cmd/podman/images/pull.go b/cmd/podman/images/pull.go
index a831ea848..a4e3515db 100644
--- a/cmd/podman/images/pull.go
+++ b/cmd/podman/images/pull.go
@@ -10,6 +10,7 @@ import (
"github.com/containers/image/v5/types"
"github.com/containers/podman/v3/cmd/podman/common"
"github.com/containers/podman/v3/cmd/podman/registry"
+ "github.com/containers/podman/v3/cmd/podman/utils"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/util"
"github.com/pkg/errors"
@@ -32,8 +33,8 @@ var (
// Command: podman pull
pullCmd = &cobra.Command{
- Use: "pull [options] IMAGE",
- Args: cobra.ExactArgs(1),
+ Use: "pull [options] IMAGE [IMAGE...]",
+ Args: cobra.MinimumNArgs(1),
Short: "Pull an image from a registry",
Long: pullDescription,
RunE: imagePull,
@@ -154,17 +155,16 @@ func imagePull(cmd *cobra.Command, args []string) error {
}
// Let's do all the remaining Yoga in the API to prevent us from
// scattering logic across (too) many parts of the code.
- pullReport, err := registry.ImageEngine().Pull(registry.GetContext(), args[0], pullOptions.ImagePullOptions)
- if err != nil {
- return err
- }
-
- if len(pullReport.Images) > 1 {
- fmt.Println("Pulled Images:")
- }
- for _, img := range pullReport.Images {
- fmt.Println(img)
+ var errs utils.OutputErrors
+ for _, arg := range args {
+ pullReport, err := registry.ImageEngine().Pull(registry.GetContext(), arg, pullOptions.ImagePullOptions)
+ if err != nil {
+ errs = append(errs, err)
+ continue
+ }
+ for _, img := range pullReport.Images {
+ fmt.Println(img)
+ }
}
-
- return nil
+ return errs.PrintErrors()
}
diff --git a/docs/source/markdown/podman-pull.1.md b/docs/source/markdown/podman-pull.1.md
index 084327efd..10661e16e 100644
--- a/docs/source/markdown/podman-pull.1.md
+++ b/docs/source/markdown/podman-pull.1.md
@@ -4,24 +4,20 @@
podman\-pull - Pull an image from a registry
## SYNOPSIS
-**podman pull** [*options*] *source*
+**podman pull** [*options*] *source* [*source*...]
-**podman image pull** [*options*] *source*
+**podman image pull** [*options*] *source* [*source*...]
**podman pull** [*options*] [*transport*]*name*[:*tag*|@*digest*]
**podman image pull** [*options*] [*transport*]*name*[:*tag*|@*digest*]
## DESCRIPTION
-Copies an image from a registry onto the local machine. The **podman pull** command pulls an
-image. If the image reference in the command line argument does not contain a registry, it is referred to as a`short-name` reference. If the image is a 'short-name' reference, Podman will prompt the user for the specific container registry to pull the image from, if an alias for the short-name has not been specified in the short-name-aliases.conf. If an image tag is not specified, **podman pull** defaults to the image with the **latest** tag (if it exists) and pulls it. After the image is pulled, podman will print the full image ID. **podman pull** can also pull an image using its digest **podman pull** *image*@*digest*. **podman pull** can be used to pull images from archives and local storage using different transports.
-
-## Image storage
-Images are stored in local image storage.
+podman pull copies an image from a registry onto the local machine. The command can pull one or more images. If the image reference in the command line argument does not contain a registry, it is referred to as a`short-name` reference. If the image is a 'short-name' reference, Podman will prompt the user for the specific container registry to pull the image from, if an alias for the short-name has not been specified in the `short-name-aliases.conf`. If an image tag is not specified, **podman pull** defaults to the image with the **latest** tag (if it exists) and pulls it. After the image is pulled, podman will print the full image ID. **podman pull** can also pull images using a digest **podman pull** *image*@*digest* and can also be used to pull images from archives and local storage using different transports.
+*IMPORTANT: Images are stored in local image storage.*
## SOURCE
-
- SOURCE is the location from the container image is pulled from. It supports all transports from `containers-transports(5)`. If no transport is specified, the input is subject to short-name resolution and the `docker` (i.e., container registry) transport is used. For remote clients, `docker` is the only supported transport.
+SOURCE is the location from the container image is pulled from. It supports all transports from **[containers-transports(5)](https://github.com/containers/image/blob/main/docs/containers-transports.5.md)**. If no transport is specified, the input is subject to short-name resolution and the `docker` (i.e., container registry) transport is used. For remote clients, `docker` is the only supported transport.
```
# Pull from a container registry
@@ -47,28 +43,27 @@ $ podman pull oci-archive:/tmp/myimage
```
## OPTIONS
-
#### **--all-tags**, **a**
All tagged images in the repository will be pulled.
-Note: When using the all-tags flag, Podman will not iterate over the search registries in the containers-registries.conf(5) but will always use docker.io for unqualified image names.
+*IMPORTANT: When using the all-tags flag, Podman will not iterate over the search registries in the **[containers-registries.conf(5)](https://github.com/containers/image/blob/main/docs/containers-registries.conf.5.md)** but will always use docker.io for unqualified image names.*
#### **--arch**=*ARCH*
Override the architecture, defaults to hosts, of the image to be pulled. For example, `arm`.
#### **--authfile**=*path*
-Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json, which is set using `podman login`.
-If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`.
+Path of the authentication file. If the authorization state is not found there, `$HOME/.docker/config.json` is checked, which is set using `docker login`.
-Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE
-environment variable. `export REGISTRY_AUTH_FILE=path`
+Default is `${XDG\_RUNTIME\_DIR}/containers/auth.json`, which is set using `podman login`.
+
+*IMPORTANT: The default path of the authentication file can be overwritten by setting the `REGISTRY\_AUTH\_FILE` environment variable. `export REGISTRY_AUTH_FILE=path`*
#### **--cert-dir**=*path*
Use certificates at *path* (\*.crt, \*.cert, \*.key) to connect to the registry.
-Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client)
+Please refer to **[containers-certs.d(5)](https://github.com/containers/image/blob/main/docs/containers-certs.d.5.md)** for details. (This option is not available with the remote Podman client)
#### **--creds**=*[username[:password]]*
@@ -84,15 +79,17 @@ solely for scripting compatibility.
#### **--help**, **-h**
-Print usage statement
+Print the usage statement.
#### **--os**=*OS*
+
Override the OS, defaults to hosts, of the image to be pulled. For example, `windows`.
#### **--platform**=*OS/ARCH*
-Specify the platform for selecting the image. (Conflicts with --arch and --os)
-The `--platform` option can be used to override the current architecture and operating system.
+Specify the platform for selecting the image. The `--platform` option can be used to override the current architecture and operating system.
+
+*IMPORTANT: Conflicts with --arch and --os*
#### **--quiet**, **-q**
@@ -108,22 +105,72 @@ TLS verification will be used unless the target registry is listed as an insecur
Use _VARIANT_ instead of the default architecture variant of the container image. Some images can use multiple variants of the arm architectures, such as arm/v5 and arm/v7.
-## EXAMPLES
+## FILES
+
+**short-name-aliases.conf** (`/var/cache/containers/short-name-aliases.conf`, `$HOME/.cache/containers/short-name-aliases.conf`)
+
+When users specify images that do not include the container registry where the
+image is stored, this is called a short name. The use of unqualified-search registries entails an ambiguity as it is unclear from which registry a given image, referenced by a short name, may be pulled from.
+
+Using short names is subject to the risk of hitting squatted registry namespaces. If the unqualified-search registries are set to ["public-registry.com", "my-private-registry.com"] an attacker may take over a namespace of `public-registry.com` such that an image may be pulled from `public-registry.com` instead of the intended source `my-private-registry.com`.
+
+While it is highly recommended to always use fully-qualified image references, existing deployments using short names may not be easily changed. To circumvent the aforementioned ambiguity, so called short-name aliases can be configured that point to a fully-qualified image reference. Distributions often ship a default shortnames.conf expansion file in /etc/containers/registries.conf.d/ directory. Administrators can use this directory to add their own local short-name expansion files.
+When pulling an image, if the user does not specify the complete registry, container engines attempt to expand the short-name into a full name. If the command is executed with a tty, the user will be prompted to select a registry from the
+default list unqualified registries defined in registries.conf. The user's selection is then stored in a cache file to be used in all future short-name expansions. Rootfull short-names are stored in /var/cache/containers/short-name-aliases.conf. Rootless short-names are stored in the $HOME/.cache/containers/short-name-aliases.conf file.
+
+For more information on short-names, see `containers-registries.conf(5)`
+
+**registries.conf** (`/etc/containers/registries.conf`)
+
+registries.conf is the configuration file which specifies which container registries should be consulted when completing image names which do not include a registry or domain portion.
+
+NOTE: Use the environment variable `TMPDIR` to change the temporary storage location of downloaded container images. Podman defaults to use `/var/tmp`.
+
+
+## EXAMPLES
+Pull a single image with short name resolution.
```
$ podman pull alpine:latest
-Trying to pull registry.access.redhat.com/alpine:latest... Failed
-Trying to pull registry.fedoraproject.org/alpine:latest... Failed
-Trying to pull docker.io/library/alpine:latest...Getting image source signatures
-Copying blob sha256:88286f41530e93dffd4b964e1db22ce4939fffa4a4c665dab8591fbab03d4926
- 1.90 MB / 1.90 MB [========================================================] 0s
-Copying config sha256:76da55c8019d7a47c347c0dceb7a6591144d232a7dd616242a367b8bed18ecbc
- 1.48 KB / 1.48 KB [========================================================] 0s
+Resolved "alpine" as an alias (/etc/containers/registries.conf.d/000-shortnames.conf)
+Trying to pull docker.io/library/alpine:latest...
+Getting image source signatures
+Copying blob 5843afab3874 done
+Copying config d4ff818577 done
+Writing manifest to image destination
+Storing signatures
+d4ff818577bc193b309b355b02ebc9220427090057b54a59e73b79bdfe139b83
+```
+
+Pull multiple images with/without short name resolution.
+```
+podman pull busybox:musl alpine quay.io/libpod/cirros
+Trying to pull docker.io/library/busybox:musl...
+Getting image source signatures
+Copying blob 0c52b060233b [--------------------------------------] 0.0b / 0.0b
+Copying config 9ad2c435a8 done
Writing manifest to image destination
Storing signatures
-04660052281190168dbb2362eb15bf7067a8dc642d2498055e0e72efa961a4b6
+9ad2c435a887e3f723654e09b48563de44aa3c7950246b2e9305ec85dd3422db
+Trying to pull docker.io/library/alpine:latest...
+Getting image source signatures
+Copying blob 5843afab3874 [--------------------------------------] 0.0b / 0.0b
+Copying config d4ff818577 done
+Writing manifest to image destination
+Storing signatures
+d4ff818577bc193b309b355b02ebc9220427090057b54a59e73b79bdfe139b83
+Trying to pull quay.io/libpod/cirros:latest...
+Getting image source signatures
+Copying blob 8da581cc9286 done
+Copying blob 856628d95d17 done
+Copying blob f513001ba4ab done
+Copying config 3c82e4d066 done
+Writing manifest to image destination
+Storing signatures
+3c82e4d066cf6f9e50efaead6e3ff7fddddf5527826afd68e5a969579fc4db4a
```
+Pull an image using its digest.
```
$ podman pull alpine@sha256:d7342993700f8cd7aba8496c2d0e57be0666e80b4c441925fc6f9361fa81d10e
Trying to pull docker.io/library/alpine@sha256:d7342993700f8cd7aba8496c2d0e57be0666e80b4c441925fc6f9361fa81d10e...
@@ -135,6 +182,7 @@ Storing signatures
d6e46aa2470df1d32034c6707c8041158b652f38d2a9ae3d7ad7e7532d22ebe0
```
+Pull an image by specifiying an authentication file.
```
$ podman pull --authfile temp-auths/myauths.json docker://docker.io/umohnani/finaltest
Trying to pull docker.io/umohnani/finaltest:latest...Getting image source signatures
@@ -147,6 +195,7 @@ Storing signatures
03290064078cb797f3e0a530e78c20c13dd22a3dd3adf84a5da2127b48df0438
```
+Pull an image by authenticating to a registry.
```
$ podman pull --creds testuser:testpassword docker.io/umohnani/finaltest
Trying to pull docker.io/umohnani/finaltest:latest...Getting image source signatures
@@ -159,6 +208,7 @@ Storing signatures
03290064078cb797f3e0a530e78c20c13dd22a3dd3adf84a5da2127b48df0438
```
+Pull an image using tls verification.
```
$ podman pull --tls-verify=false --cert-dir image/certs docker.io/umohnani/finaltest
Trying to pull docker.io/umohnani/finaltest:latest...Getting image source signatures
@@ -171,6 +221,7 @@ Storing signatures
03290064078cb797f3e0a530e78c20c13dd22a3dd3adf84a5da2127b48df0438
```
+Pull an image by overriding the host architecture.
```
$ podman pull --arch=arm arm32v7/debian:stretch
Trying to pull docker.io/arm32v7/debian:stretch...
@@ -182,30 +233,8 @@ Storing signatures
3cba58dad5d9b35e755b48b634acb3fdd185ab1c996ac11510cc72c17780e13c
```
-## FILES
-
-**short-name-aliases.conf** (`/var/cache/containers/short-name-aliases.conf`, `$HOME/.cache/containers/short-name-aliases.conf`)
-
-When users specify images that do not include the container registry where the
-image is stored, this is called a short name. The use of unqualified-search registries entails an ambiguity as it is unclear from which registry a given image, referenced by a short name, may be pulled from.
-
-Using short names is subject to the risk of hitting squatted registry namespaces. If the unqualified-search registries are set to ["public-registry.com", "my-private-registry.com"] an attacker may take over a namespace of `public-registry.com` such that an image may be pulled from `public-registry.com` instead of the intended source `my-private-registry.com`.
-
-While it is highly recommended to always use fully-qualified image references, existing deployments using short names may not be easily changed. To circumvent the aforementioned ambiguity, so called short-name aliases can be configured that point to a fully-qualified image reference. Distributions often ship a default shortnames.conf expansion file in /etc/containers/registries.conf.d/ directory. Administrators can use this directory to add their own local short-name expansion files.
-
-When pulling an image, if the user does not specify the complete registry, container engines attempt to expand the short-name into a full name. If the command is executed with a tty, the user will be prompted to select a registry from the
-default list unqualified registries defined in registries.conf. The user's selection is then stored in a cache file to be used in all future short-name expansions. Rootfull short-names are stored in /var/cache/containers/short-name-aliases.conf. Rootless short-names are stored in the $HOME/.cache/containers/short-name-aliases.conf file.
-
-For more information on short-names, see `containers-registries.conf(5)`
-
-**registries.conf** (`/etc/containers/registries.conf`)
-
-registries.conf is the configuration file which specifies which container registries should be consulted when completing image names which do not include a registry or domain portion.
-
-NOTE: Use the environment variable `TMPDIR` to change the temporary storage location of downloaded container images. Podman defaults to use `/var/tmp`.
-
## SEE ALSO
-podman(1), podman-push(1), podman-login(1), containers-certs.d(5), containers-registries.conf(5), containers-transports(5)
+**[podman(1)](podman.1.md)**, **[podman-push(1)](podman-push.1.md)**, **[podman-login(1)](podman-login.1.md)**, **[containers-certs.d(5](https://github.com/containers/image/blob/main/docs/containers-certs.d.5.md)**, **[containers-registries.conf(5)](https://github.com/containers/image/blob/main/docs/containers-registries.d.5.md)**, **[containers-transports(5)](https://github.com/containers/image/blob/main/docs/containers-transports.5.md)**
## HISTORY
July 2017, Originally compiled by Urvashi Mohnani <umohnani@redhat.com>
diff --git a/test/e2e/pull_test.go b/test/e2e/pull_test.go
index c60ad9487..048f19b1e 100644
--- a/test/e2e/pull_test.go
+++ b/test/e2e/pull_test.go
@@ -35,6 +35,23 @@ var _ = Describe("Podman pull", func() {
})
+ It("podman pull multiple images with/without tag/digest", func() {
+ session := podmanTest.Podman([]string{"pull", "busybox:musl", "alpine", "alpine:latest", "quay.io/libpod/cirros", "quay.io/libpod/testdigest_v2s2@sha256:755f4d90b3716e2bf57060d249e2cd61c9ac089b1233465c5c2cb2d7ee550fdb"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ session = podmanTest.Podman([]string{"pull", "busybox:latest", "docker.io/library/ibetthisdoesnotexistfr:random", "alpine"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(125))
+ expectedError := "Error initializing source docker://ibetthisdoesnotexistfr:random"
+ found, _ := session.ErrorGrepString(expectedError)
+ Expect(found).To(Equal(true))
+
+ session = podmanTest.Podman([]string{"rmi", "busybox", "alpine", "testdigest_v2s2", "quay.io/libpod/cirros"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ })
+
It("podman pull from docker a not existing image", func() {
session := podmanTest.Podman([]string{"pull", "ibetthisdoesntexistthere:foo"})
session.WaitWithDefaultTimeout()
@@ -385,7 +402,6 @@ var _ = Describe("Podman pull", func() {
session := podmanTest.Podman([]string{"pull", "--all-tags", "k8s.gcr.io/pause"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- Expect(session.LineInOutputStartsWith("Pulled Images:")).To(BeTrue())
session = podmanTest.Podman([]string{"images"})
session.WaitWithDefaultTimeout()