Skip to content

Commit 350e90f

Browse files
committed
image rm: add --platform option
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
1 parent f567263 commit 350e90f

File tree

3 files changed

+105
-16
lines changed

3 files changed

+105
-16
lines changed

cli/command/image/remove.go

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"fmt"
77

88
cerrdefs "github.com/containerd/errdefs"
9+
"github.com/containerd/platforms"
910
"github.com/docker/cli/cli"
1011
"github.com/docker/cli/cli/command"
1112
"github.com/docker/cli/cli/command/completion"
@@ -14,32 +15,38 @@ import (
1415
)
1516

1617
type removeOptions struct {
17-
force bool
18-
noPrune bool
18+
force bool
19+
noPrune bool
20+
platforms []string
1921
}
2022

2123
// NewRemoveCommand creates a new `docker remove` command
22-
func NewRemoveCommand(dockerCli command.Cli) *cobra.Command {
23-
var opts removeOptions
24+
func NewRemoveCommand(dockerCLI command.Cli) *cobra.Command {
25+
var options removeOptions
2426

2527
cmd := &cobra.Command{
2628
Use: "rmi [OPTIONS] IMAGE [IMAGE...]",
2729
Short: "Remove one or more images",
2830
Args: cli.RequiresMinArgs(1),
2931
RunE: func(cmd *cobra.Command, args []string) error {
30-
return runRemove(cmd.Context(), dockerCli, opts, args)
32+
return runRemove(cmd.Context(), dockerCLI, options, args)
3133
},
32-
ValidArgsFunction: completion.ImageNames(dockerCli, -1),
34+
ValidArgsFunction: completion.ImageNames(dockerCLI, -1),
3335
Annotations: map[string]string{
3436
"aliases": "docker image rm, docker image remove, docker rmi",
3537
},
3638
}
3739

3840
flags := cmd.Flags()
3941

40-
flags.BoolVarP(&opts.force, "force", "f", false, "Force removal of the image")
41-
flags.BoolVar(&opts.noPrune, "no-prune", false, "Do not delete untagged parents")
42+
flags.BoolVarP(&options.force, "force", "f", false, "Force removal of the image")
43+
flags.BoolVar(&options.noPrune, "no-prune", false, "Do not delete untagged parents")
4244

45+
// TODO(thaJeztah): create a "platforms" option for this (including validation / parsing).
46+
flags.StringSliceVar(&options.platforms, "platform", nil, `Remove only the given platform variant. Formatted as "os[/arch[/variant]]" (e.g., "linux/amd64")`)
47+
_ = flags.SetAnnotation("platform", "version", []string{"1.50"})
48+
49+
_ = cmd.RegisterFlagCompletionFunc("platform", completion.Platforms)
4350
return cmd
4451
}
4552

@@ -58,6 +65,14 @@ func runRemove(ctx context.Context, dockerCLI command.Cli, opts removeOptions, i
5865
PruneChildren: !opts.noPrune,
5966
}
6067

68+
for _, v := range opts.platforms {
69+
p, err := platforms.Parse(v)
70+
if err != nil {
71+
return err
72+
}
73+
options.Platforms = append(options.Platforms, p)
74+
}
75+
6176
// TODO(thaJeztah): this logic can likely be simplified: do we want to print "not found" errors at all when using "force"?
6277
fatalErr := false
6378
var errs []error

docs/reference/commandline/image_rm.md

Lines changed: 77 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ Remove one or more images
99

1010
### Options
1111

12-
| Name | Type | Default | Description |
13-
|:----------------|:-------|:--------|:-------------------------------|
14-
| `-f`, `--force` | `bool` | | Force removal of the image |
15-
| `--no-prune` | `bool` | | Do not delete untagged parents |
12+
| Name | Type | Default | Description |
13+
|:--------------------------|:--------------|:--------|:-------------------------------------------------------------------------------------------------|
14+
| `-f`, `--force` | `bool` | | Force removal of the image |
15+
| `--no-prune` | `bool` | | Do not delete untagged parents |
16+
| [`--platform`](#platform) | `stringSlice` | | Remove only the given platform variant. Formatted as `os[/arch[/variant]]` (e.g., `linux/amd64`) |
1617

1718

1819
<!---MARKER_GEN_END-->
@@ -105,3 +106,75 @@ Deleted: 4986bf8c15363d1c5d15512d5266f8777bfba4974ac56e3270e7760f6f0a8125
105106
Deleted: ea13149945cb6b1e746bf28032f02e9b5a793523481a0a18645fc77ad53c4ea2
106107
Deleted: df7546f9f060a2268024c8a230d8639878585defcc1bc6f79d2728a13957871b
107108
```
109+
110+
111+
### <a name="platform"></a> Remove a specific platform (`--platform`)
112+
113+
The `--platform` option allows you to specify which platform variants of the
114+
image to remove. By default, `docker image remove` removes all platform variants
115+
that are present. Use the `--platform` option to specify which platform variant
116+
of the image to remove.
117+
118+
Removing a specific platform removes the image from all images that reference
119+
the same content, and requires the `--force` option to be used. Omitting the
120+
`--force` option produces a warning, and the remove is canceled:
121+
122+
```console
123+
$ docker image rm --platform=linux/amd64 alpine
124+
Error response from daemon: Content will be removed from all images referencing this variant. Use —-force to force delete.
125+
```
126+
127+
128+
The platform option takes the `os[/arch[/variant]]` format; for example,
129+
`linux/amd64` or `linux/arm64/v8`. Architecture and variant are optional,
130+
and default to the daemon's native architecture if omitted.
131+
132+
You can pass multiple platforms either by passing the `--platform` flag
133+
multiple times, or by passing a comma-separated list of platforms to remove.
134+
The following uses of this option are equivalent;
135+
136+
```console
137+
$ docker image rm --plaform linux/amd64 --platform linux/ppc64le myimage
138+
$ docker image rm --plaform linux/amd64,linux/ppc64le myimage
139+
```
140+
141+
The following example removes the `linux/amd64` and `linux/ppc64le` variants
142+
of an `alpine` image that contains multiple platform variants in the image
143+
cache:
144+
145+
```console
146+
$ docker image ls --tree alpine
147+
148+
IMAGE ID DISK USAGE CONTENT SIZE EXTRA
149+
alpine:latest a8560b36e8b8 37.8MB 11.2MB U
150+
├─ linux/amd64 1c4eef651f65 12.1MB 3.64MB U
151+
├─ linux/arm/v6 903bfe2ae994 0B 0B
152+
├─ linux/arm/v7 9c2d245b3c01 0B 0B
153+
├─ linux/arm64/v8 757d680068d7 12.8MB 3.99MB
154+
├─ linux/386 2436f2b3b7d2 0B 0B
155+
├─ linux/ppc64le 9ed53fd3b831 12.8MB 3.58MB
156+
├─ linux/riscv64 1de5eb4a9a67 0B 0B
157+
└─ linux/s390x fe0dcdd1f783 0B 0B
158+
159+
$ docker image --platform=linux/amd64,linux/ppc64le --force alpine
160+
Deleted: sha256:1c4eef651f65e2f7daee7ee785882ac164b02b78fb74503052a26dc061c90474
161+
Deleted: sha256:9ed53fd3b83120f78b33685d930ce9bf5aa481f6e2d165c42cbbddbeaa196f6f
162+
```
163+
164+
After the command completes, the given variants of the `alpine` image are removed
165+
from the image cache:
166+
167+
```console
168+
$ docker image ls --tree alpine
169+
170+
IMAGE ID DISK USAGE CONTENT SIZE EXTRA
171+
alpine:latest a8560b36e8b8 12.8MB 3.99MB
172+
├─ linux/amd64 1c4eef651f65 0B 0B
173+
├─ linux/arm/v6 903bfe2ae994 0B 0B
174+
├─ linux/arm/v7 9c2d245b3c01 0B 0B
175+
├─ linux/arm64/v8 757d680068d7 12.8MB 3.99MB
176+
├─ linux/386 2436f2b3b7d2 0B 0B
177+
├─ linux/ppc64le 9ed53fd3b831 0B 0B
178+
├─ linux/riscv64 1de5eb4a9a67 0B 0B
179+
└─ linux/s390x fe0dcdd1f783 0B 0B
180+
```

docs/reference/commandline/rmi.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ Remove one or more images
99

1010
### Options
1111

12-
| Name | Type | Default | Description |
13-
|:----------------|:-------|:--------|:-------------------------------|
14-
| `-f`, `--force` | `bool` | | Force removal of the image |
15-
| `--no-prune` | `bool` | | Do not delete untagged parents |
12+
| Name | Type | Default | Description |
13+
|:----------------|:--------------|:--------|:-------------------------------------------------------------------------------------------------|
14+
| `-f`, `--force` | `bool` | | Force removal of the image |
15+
| `--no-prune` | `bool` | | Do not delete untagged parents |
16+
| `--platform` | `stringSlice` | | Remove only the given platform variant. Formatted as `os[/arch[/variant]]` (e.g., `linux/amd64`) |
1617

1718

1819
<!---MARKER_GEN_END-->

0 commit comments

Comments
 (0)