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),
removeCommand(&opts, dockerCli, backend),
execCommand(&opts, dockerCli, backend),
attachCommand(&opts, dockerCli, backend),
pauseCommand(&opts, dockerCli, backend),
unpauseCommand(&opts, dockerCli, backend),
topCommand(&opts, dockerCli, backend),

View File

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

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
plink: docker.yaml
cname:
- docker compose attach
- docker compose build
- docker compose config
- docker compose cp
@ -176,6 +177,7 @@ cname:
- docker compose wait
- docker compose watch
clink:
- docker_compose_attach.yaml
- docker_compose_build.yaml
- docker_compose_config.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
// Exec executes a command in a running service container
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(ctx context.Context, projectName string, options CopyOptions) error
// Pause executes the equivalent to a `compose pause`
@ -342,6 +344,16 @@ type RunOptions struct {
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
type EventsOptions struct {
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
}
// 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.
func (m *MockService) Build(ctx context.Context, project *types.Project, options api.BuildOptions) error {
m.ctrl.T.Helper()