@@ -22,10 +22,18 @@ import (
2222 "github.com/spf13/pflag"
2323)
2424
25+ // Pull constants
26+ const (
27+ PullImageAlways = "always"
28+ PullImageMissing = "missing" // Default (matches previous bahevior)
29+ PullImageNever = "never"
30+ )
31+
2532type createOptions struct {
2633 name string
2734 platform string
2835 untrusted bool
36+ pull string // alway, missing, never
2937}
3038
3139// NewCreateCommand creates a new cobra.Command for `docker create`
@@ -50,6 +58,8 @@ func NewCreateCommand(dockerCli command.Cli) *cobra.Command {
5058 flags .SetInterspersed (false )
5159
5260 flags .StringVar (& opts .name , "name" , "" , "Assign a name to the container" )
61+ flags .StringVar (& opts .pull , "pull" , PullImageMissing ,
62+ `Pull image before creating ("` + PullImageAlways + `"|"` + PullImageMissing + `"|"` + PullImageNever + `")` )
5363
5464 // Add an explicit help that doesn't have a `-h` to prevent the conflict
5565 // with hostname
@@ -175,6 +185,7 @@ func newCIDFile(path string) (*cidFile, error) {
175185 return & cidFile {path : path , file : f }, nil
176186}
177187
188+ // nolint: gocyclo
178189func createContainer (ctx context.Context , dockerCli command.Cli , containerConfig * containerConfig , opts * createOptions ) (* container.ContainerCreateCreatedBody , error ) {
179190 config := containerConfig .Config
180191 hostConfig := containerConfig .HostConfig
@@ -213,31 +224,59 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerConfig
213224 }
214225
215226 //create the container
216- response , err := dockerCli .Client ().ContainerCreate (ctx , config , hostConfig , networkingConfig , opts .name )
227+ var response container.ContainerCreateCreatedBody
228+ if opts .pull == PullImageMissing { // Pull image only if it does not exist locally. Default.
229+ response , err = dockerCli .Client ().ContainerCreate (ctx , config , hostConfig , networkingConfig , opts .name )
217230
218- //if image not found try to pull it
219- if err != nil {
220- if apiclient .IsErrNotFound (err ) && namedRef != nil {
221- fmt .Fprintf (stderr , "Unable to find image '%s' locally\n " , reference .FamiliarString (namedRef ))
231+ //if image not found try to pull it
232+ if err != nil {
233+ if apiclient .IsErrNotFound (err ) && namedRef != nil {
234+ fmt .Fprintf (stderr , "Unable to find image '%s' locally\n " , reference .FamiliarString (namedRef ))
222235
223- // we don't want to write to stdout anything apart from container.ID
224- if err := pullImage (ctx , dockerCli , config .Image , opts .platform , stderr ); err != nil {
225- return nil , err
226- }
227- if taggedRef , ok := namedRef .(reference.NamedTagged ); ok && trustedRef != nil {
228- if err := image .TagTrusted (ctx , dockerCli , trustedRef , taggedRef ); err != nil {
236+ // we don't want to write to stdout anything apart from container.ID
237+ if err := pullImage (ctx , dockerCli , config .Image , opts .platform , stderr ); err != nil {
229238 return nil , err
230239 }
240+ if taggedRef , ok := namedRef .(reference.NamedTagged ); ok && trustedRef != nil {
241+ if err := image .TagTrusted (ctx , dockerCli , trustedRef , taggedRef ); err != nil {
242+ return nil , err
243+ }
244+ }
245+ // Retry
246+ var retryErr error
247+ response , retryErr = dockerCli .Client ().ContainerCreate (ctx , config , hostConfig , networkingConfig , opts .name )
248+ if retryErr != nil {
249+ return nil , retryErr
250+ }
251+ } else {
252+ return nil , err
231253 }
232- // Retry
233- var retryErr error
234- response , retryErr = dockerCli .Client ().ContainerCreate (ctx , config , hostConfig , networkingConfig , opts .name )
235- if retryErr != nil {
236- return nil , retryErr
254+ }
255+
256+ } else if opts .pull == PullImageAlways { // Always try and pull the image.
257+ if err := pullImage (ctx , dockerCli , config .Image , opts .platform , stderr ); err != nil {
258+ return nil , err
259+ }
260+ if taggedRef , ok := namedRef .(reference.NamedTagged ); ok && trustedRef != nil {
261+ if err := image .TagTrusted (ctx , dockerCli , trustedRef , taggedRef ); err != nil {
262+ return nil , err
237263 }
238- } else {
264+ }
265+ response , err = dockerCli .Client ().ContainerCreate (ctx , config , hostConfig , networkingConfig , opts .name )
266+ if err != nil {
239267 return nil , err
240268 }
269+
270+ } else if opts .pull == PullImageNever { // Never try and pull the image
271+ response , err = dockerCli .Client ().ContainerCreate (ctx , config , hostConfig , networkingConfig , opts .name )
272+
273+ if err != nil {
274+ if apiclient .IsErrNotFound (err ) && namedRef != nil {
275+ fmt .Fprintf (stderr , "Unable to find image '%s' locally\n Will not pull due to '%s'" , reference .FamiliarString (namedRef ), opts .pull )
276+ }
277+ }
278+ } else { // We got something weird
279+ return nil , errors .Errorf ("Unknown pull option : %s" , opts .pull )
241280 }
242281
243282 for _ , warning := range response .Warnings {
0 commit comments