Merge pull request #11181 from g0t4/11153-compose-attach-override-container-attach-cmd

Implement `docker compose attach`
This commit is contained in:
Guillaume Lours 2024-01-11 11:11:10 +01:00 committed by GitHub
commit 24d34040e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 264 additions and 31 deletions

80
cmd/compose/attach.go Normal file
View File

@ -0,0 +1,80 @@
/*
Copyright 2020 Docker Compose CLI authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package compose
import (
"context"
"github.com/docker/cli/cli/command"
"github.com/docker/compose/v2/pkg/api"
"github.com/spf13/cobra"
)
type attachOpts struct {
*composeOptions
service string
index int
detachKeys string
noStdin bool
proxy bool
}
func attachCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service) *cobra.Command {
opts := attachOpts{
composeOptions: &composeOptions{
ProjectOptions: p,
},
}
runCmd := &cobra.Command{
Use: "attach [OPTIONS] SERVICE",
Short: "Attach local standard input, output, and error streams to a service's running container.",
Args: cobra.MinimumNArgs(1),
PreRunE: Adapt(func(ctx context.Context, args []string) error {
opts.service = args[0]
return nil
}),
RunE: Adapt(func(ctx context.Context, args []string) error {
return runAttach(ctx, dockerCli, backend, opts)
}),
ValidArgsFunction: completeServiceNames(dockerCli, p),
}
runCmd.Flags().IntVar(&opts.index, "index", 0, "index of the container if service has multiple replicas.")
runCmd.Flags().StringVarP(&opts.detachKeys, "detach-keys", "", "", "Override the key sequence for detaching from a container.")
runCmd.Flags().BoolVar(&opts.noStdin, "no-stdin", false, "Do not attach STDIN")
runCmd.Flags().BoolVar(&opts.proxy, "sig-proxy", true, "Proxy all received signals to the process")
return runCmd
}
func runAttach(ctx context.Context, dockerCli command.Cli, backend api.Service, opts attachOpts) error {
projectName, err := opts.toProjectName(dockerCli)
if err != nil {
return err
}
attachOpts := api.AttachOptions{
Service: opts.service,
Index: opts.index,
DetachKeys: opts.detachKeys,
NoStdin: opts.noStdin,
Proxy: opts.proxy,
}
return backend.Attach(ctx, projectName, attachOpts)
}

View File

@ -445,6 +445,7 @@ func RootCommand(dockerCli command.Cli, backend api.Service) *cobra.Command { //
runCommand(&opts, dockerCli, backend), runCommand(&opts, dockerCli, backend),
removeCommand(&opts, dockerCli, backend), removeCommand(&opts, dockerCli, backend),
execCommand(&opts, dockerCli, backend), execCommand(&opts, dockerCli, backend),
attachCommand(&opts, dockerCli, backend),
pauseCommand(&opts, dockerCli, backend), pauseCommand(&opts, dockerCli, backend),
unpauseCommand(&opts, dockerCli, backend), unpauseCommand(&opts, dockerCli, backend),
topCommand(&opts, dockerCli, backend), topCommand(&opts, dockerCli, backend),

View File

@ -5,37 +5,38 @@ Define and run multi-container applications with Docker.
### Subcommands ### Subcommands
| Name | Description | | Name | Description |
|:--------------------------------|:--------------------------------------------------------------------------------------| |:--------------------------------|:-----------------------------------------------------------------------------------------|
| [`build`](compose_build.md) | Build or rebuild services | | [`attach`](compose_attach.md) | Attach local standard input, output, and error streams to a service's running container. |
| [`config`](compose_config.md) | Parse, resolve and render compose file in canonical format | | [`build`](compose_build.md) | Build or rebuild services |
| [`cp`](compose_cp.md) | Copy files/folders between a service container and the local filesystem | | [`config`](compose_config.md) | Parse, resolve and render compose file in canonical format |
| [`create`](compose_create.md) | Creates containers for a service. | | [`cp`](compose_cp.md) | Copy files/folders between a service container and the local filesystem |
| [`down`](compose_down.md) | Stop and remove containers, networks | | [`create`](compose_create.md) | Creates containers for a service. |
| [`events`](compose_events.md) | Receive real time events from containers. | | [`down`](compose_down.md) | Stop and remove containers, networks |
| [`exec`](compose_exec.md) | Execute a command in a running container. | | [`events`](compose_events.md) | Receive real time events from containers. |
| [`images`](compose_images.md) | List images used by the created containers | | [`exec`](compose_exec.md) | Execute a command in a running container. |
| [`kill`](compose_kill.md) | Force stop service containers. | | [`images`](compose_images.md) | List images used by the created containers |
| [`logs`](compose_logs.md) | View output from containers | | [`kill`](compose_kill.md) | Force stop service containers. |
| [`ls`](compose_ls.md) | List running compose projects | | [`logs`](compose_logs.md) | View output from containers |
| [`pause`](compose_pause.md) | Pause services | | [`ls`](compose_ls.md) | List running compose projects |
| [`port`](compose_port.md) | Print the public port for a port binding. | | [`pause`](compose_pause.md) | Pause services |
| [`ps`](compose_ps.md) | List containers | | [`port`](compose_port.md) | Print the public port for a port binding. |
| [`pull`](compose_pull.md) | Pull service images | | [`ps`](compose_ps.md) | List containers |
| [`push`](compose_push.md) | Push service images | | [`pull`](compose_pull.md) | Pull service images |
| [`restart`](compose_restart.md) | Restart service containers | | [`push`](compose_push.md) | Push service images |
| [`rm`](compose_rm.md) | Removes stopped service containers | | [`restart`](compose_restart.md) | Restart service containers |
| [`run`](compose_run.md) | Run a one-off command on a service. | | [`rm`](compose_rm.md) | Removes stopped service containers |
| [`scale`](compose_scale.md) | Scale services | | [`run`](compose_run.md) | Run a one-off command on a service. |
| [`start`](compose_start.md) | Start services | | [`scale`](compose_scale.md) | Scale services |
| [`stats`](compose_stats.md) | Display a live stream of container(s) resource usage statistics | | [`start`](compose_start.md) | Start services |
| [`stop`](compose_stop.md) | Stop services | | [`stats`](compose_stats.md) | Display a live stream of container(s) resource usage statistics |
| [`top`](compose_top.md) | Display the running processes | | [`stop`](compose_stop.md) | Stop services |
| [`unpause`](compose_unpause.md) | Unpause services | | [`top`](compose_top.md) | Display the running processes |
| [`up`](compose_up.md) | Create and start containers | | [`unpause`](compose_unpause.md) | Unpause services |
| [`version`](compose_version.md) | Show the Docker Compose version information | | [`up`](compose_up.md) | Create and start containers |
| [`wait`](compose_wait.md) | Block until the first service container stops | | [`version`](compose_version.md) | Show the Docker Compose version information |
| [`watch`](compose_watch.md) | Watch build context for service and rebuild/refresh containers when files are updated | | [`wait`](compose_wait.md) | Block until the first service container stops |
| [`watch`](compose_watch.md) | Watch build context for service and rebuild/refresh containers when files are updated |
### Options ### Options

View File

@ -0,0 +1,18 @@
# docker compose attach
<!---MARKER_GEN_START-->
Attach local standard input, output, and error streams to a service's running container.
### Options
| Name | Type | Default | Description |
|:----------------|:---------|:--------|:----------------------------------------------------------|
| `--detach-keys` | `string` | | Override the key sequence for detaching from a container. |
| `--dry-run` | | | Execute command in dry run mode |
| `--index` | `int` | `0` | index of the container if service has multiple replicas. |
| `--no-stdin` | | | Do not attach STDIN |
| `--sig-proxy` | | | Proxy all received signals to the process |
<!---MARKER_GEN_END-->

View File

@ -146,6 +146,7 @@ usage: docker compose
pname: docker pname: docker
plink: docker.yaml plink: docker.yaml
cname: cname:
- docker compose attach
- docker compose build - docker compose build
- docker compose config - docker compose config
- docker compose cp - docker compose cp
@ -176,6 +177,7 @@ cname:
- docker compose wait - docker compose wait
- docker compose watch - docker compose watch
clink: clink:
- docker_compose_attach.yaml
- docker_compose_build.yaml - docker_compose_build.yaml
- docker_compose_config.yaml - docker_compose_config.yaml
- docker_compose_cp.yaml - docker_compose_cp.yaml

View File

@ -0,0 +1,66 @@
command: docker compose attach
short: |
Attach local standard input, output, and error streams to a service's running container.
long: |
Attach local standard input, output, and error streams to a service's running container.
usage: docker compose attach [OPTIONS] SERVICE
pname: docker compose
plink: docker_compose.yaml
options:
- option: detach-keys
value_type: string
description: Override the key sequence for detaching from a container.
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: index
value_type: int
default_value: "0"
description: index of the container if service has multiple replicas.
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: no-stdin
value_type: bool
default_value: "false"
description: Do not attach STDIN
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: sig-proxy
value_type: bool
default_value: "true"
description: Proxy all received signals to the process
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
inherited_options:
- option: dry-run
value_type: bool
default_value: "false"
description: Execute command in dry run mode
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false

View File

@ -62,6 +62,8 @@ type Service interface {
Remove(ctx context.Context, projectName string, options RemoveOptions) error Remove(ctx context.Context, projectName string, options RemoveOptions) error
// Exec executes a command in a running service container // Exec executes a command in a running service container
Exec(ctx context.Context, projectName string, options RunOptions) (int, error) Exec(ctx context.Context, projectName string, options RunOptions) (int, error)
// Attach STDIN,STDOUT,STDERR to a running service container
Attach(ctx context.Context, projectName string, options AttachOptions) error
// Copy copies a file/folder between a service container and the local filesystem // Copy copies a file/folder between a service container and the local filesystem
Copy(ctx context.Context, projectName string, options CopyOptions) error Copy(ctx context.Context, projectName string, options CopyOptions) error
// Pause executes the equivalent to a `compose pause` // Pause executes the equivalent to a `compose pause`
@ -342,6 +344,16 @@ type RunOptions struct {
Index int Index int
} }
// AttachOptions group options of the Attach API
type AttachOptions struct {
Project *types.Project
Service string
Index int
DetachKeys string
NoStdin bool
Proxy bool
}
// EventsOptions group options of the Events API // EventsOptions group options of the Events API
type EventsOptions struct { type EventsOptions struct {
Services []string Services []string

View File

@ -0,0 +1,39 @@
/*
Copyright 2020 Docker Compose CLI authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package compose
import (
"context"
"strings"
"github.com/docker/cli/cli/command/container"
"github.com/docker/compose/v2/pkg/api"
)
func (s *composeService) Attach(ctx context.Context, projectName string, options api.AttachOptions) error {
projectName = strings.ToLower(projectName)
target, err := s.getSpecifiedContainer(ctx, projectName, oneOffInclude, false, options.Service, options.Index)
if err != nil {
return err
}
var attach container.AttachOptions
attach.DetachKeys = options.DetachKeys
attach.NoStdin = options.NoStdin
attach.Proxy = options.Proxy
return container.RunAttach(ctx, s.dockerCli, target.ID, &attach)
}

View File

@ -40,6 +40,20 @@ func (m *MockService) EXPECT() *MockServiceMockRecorder {
return m.recorder return m.recorder
} }
// Attach mocks base method.
func (m *MockService) Attach(ctx context.Context, projectName string, options api.AttachOptions) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Attach", ctx, projectName, options)
ret0, _ := ret[0].(error)
return ret0
}
// Attach indicates an expected call of Attach.
func (mr *MockServiceMockRecorder) Attach(ctx, projectName, options any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Attach", reflect.TypeOf((*MockService)(nil).Attach), ctx, projectName, options)
}
// Build mocks base method. // Build mocks base method.
func (m *MockService) Build(ctx context.Context, project *types.Project, options api.BuildOptions) error { func (m *MockService) Build(ctx context.Context, project *types.Project, options api.BuildOptions) error {
m.ctrl.T.Helper() m.ctrl.T.Helper()