diff --git a/components/cli/cli/command/stack/swarm/deploy_composefile.go b/components/cli/cli/command/stack/swarm/deploy_composefile.go index c9d5a3c158..08ea1ef6aa 100644 --- a/components/cli/cli/command/stack/swarm/deploy_composefile.go +++ b/components/cli/cli/command/stack/swarm/deploy_composefile.go @@ -248,6 +248,12 @@ func deployServices( // service update. serviceSpec.TaskTemplate.ContainerSpec.Image = service.Spec.TaskTemplate.ContainerSpec.Image } + + // Stack deploy does not have a `--force` option. Preserve existing ForceUpdate + // value so that tasks are not re-deployed if not updated. + // TODO move this to API client? + serviceSpec.TaskTemplate.ForceUpdate = service.Spec.TaskTemplate.ForceUpdate + response, err := apiClient.ServiceUpdate( ctx, service.ID, diff --git a/components/cli/cli/command/stack/swarm/deploy_test.go b/components/cli/cli/command/stack/swarm/deploy_test.go index 3fdbbdbee7..99800b4ae2 100644 --- a/components/cli/cli/command/stack/swarm/deploy_test.go +++ b/components/cli/cli/command/stack/swarm/deploy_test.go @@ -27,7 +27,8 @@ func TestPruneServices(t *testing.T) { } // TestServiceUpdateResolveImageChanged tests that the service's -// image digest is preserved if the image did not change in the compose file +// image digest, and "ForceUpdate" is preserved if the image did not change in +// the compose file func TestServiceUpdateResolveImageChanged(t *testing.T) { namespace := convert.NewNamespace("mystack") @@ -49,6 +50,7 @@ func TestServiceUpdateResolveImageChanged(t *testing.T) { ContainerSpec: &swarm.ContainerSpec{ Image: "foobar:1.2.3@sha256:deadbeef", }, + ForceUpdate: 123, }, }, }, @@ -65,18 +67,21 @@ func TestServiceUpdateResolveImageChanged(t *testing.T) { image string expectedQueryRegistry bool expectedImage string + expectedForceUpdate uint64 }{ // Image not changed { image: "foobar:1.2.3", expectedQueryRegistry: false, expectedImage: "foobar:1.2.3@sha256:deadbeef", + expectedForceUpdate: 123, }, // Image changed { image: "foobar:1.2.4", expectedQueryRegistry: true, expectedImage: "foobar:1.2.4", + expectedForceUpdate: 123, }, } @@ -95,8 +100,9 @@ func TestServiceUpdateResolveImageChanged(t *testing.T) { } err := deployServices(ctx, client, spec, namespace, false, ResolveImageChanged) assert.NilError(t, err) - assert.Check(t, is.Equal(testcase.expectedQueryRegistry, receivedOptions.QueryRegistry)) - assert.Check(t, is.Equal(testcase.expectedImage, receivedService.TaskTemplate.ContainerSpec.Image)) + assert.Check(t, is.Equal(receivedOptions.QueryRegistry, testcase.expectedQueryRegistry)) + assert.Check(t, is.Equal(receivedService.TaskTemplate.ContainerSpec.Image, testcase.expectedImage)) + assert.Check(t, is.Equal(receivedService.TaskTemplate.ForceUpdate, testcase.expectedForceUpdate)) receivedService = swarm.ServiceSpec{} receivedOptions = types.ServiceUpdateOptions{} diff --git a/components/cli/docs/reference/commandline/build.md b/components/cli/docs/reference/commandline/build.md index 01ab913eca..77c6f4519d 100644 --- a/components/cli/docs/reference/commandline/build.md +++ b/components/cli/docs/reference/commandline/build.md @@ -411,13 +411,13 @@ files. The `ARG` instruction lets Dockerfile authors define values that users can set at build-time using the `--build-arg` flag: ```bash -$ docker build --build-arg HTTP_PROXY=http://10.20.30.2:1234 . +$ docker build --build-arg HTTP_PROXY=http://10.20.30.2:1234 --build-arg FTP_PROXY=http://40.50.60.5:4567 . ``` This flag allows you to pass the build-time variables that are accessed like regular environment variables in the `RUN` instruction of the Dockerfile. Also, these values don't persist in the intermediate or final images -like `ENV` values do. +like `ENV` values do. You must add `--build-arg` for each build argument. Using this flag will not alter the output you see when the `ARG` lines from the Dockerfile are echoed during the build process.