mirror of
https://github.com/docker/compose.git
synced 2026-02-10 10:39:23 +08:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
42710b7c43 | ||
|
|
b9b3a3d91f | ||
|
|
1d06741032 | ||
|
|
35b790dcdf | ||
|
|
7036cda306 | ||
|
|
540ad83a6d | ||
|
|
92be1e7112 | ||
|
|
a97576e844 | ||
|
|
d8775c7a28 | ||
|
|
158b5ff6a3 | ||
|
|
ce944520ff | ||
|
|
57e8e8ef29 | ||
|
|
22b8c731c7 | ||
|
|
f86f252a66 |
@@ -29,16 +29,17 @@ import (
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
dockercli "github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli-plugins/manager"
|
||||
"github.com/docker/compose/v2/cmd/formatter"
|
||||
"github.com/docker/compose/v2/pkg/utils"
|
||||
"github.com/morikuni/aec"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"github.com/docker/compose/v2/cmd/formatter"
|
||||
"github.com/docker/compose/v2/pkg/api"
|
||||
"github.com/docker/compose/v2/pkg/compose"
|
||||
"github.com/docker/compose/v2/pkg/progress"
|
||||
"github.com/docker/compose/v2/pkg/utils"
|
||||
)
|
||||
|
||||
// Command defines a compose CLI command as a func with args
|
||||
@@ -271,6 +272,12 @@ func RootCommand(backend api.Service) *cobra.Command {
|
||||
logrus.SetLevel(logrus.TraceLevel)
|
||||
}
|
||||
formatter.SetANSIMode(ansi)
|
||||
switch ansi {
|
||||
case "never":
|
||||
progress.Mode = progress.ModePlain
|
||||
case "tty":
|
||||
progress.Mode = progress.ModeTTY
|
||||
}
|
||||
if opts.WorkDir != "" {
|
||||
if opts.ProjectDir != "" {
|
||||
return errors.New(`cannot specify DEPRECATED "--workdir" and "--project-directory". Please use only "--project-directory" instead`)
|
||||
|
||||
@@ -18,11 +18,8 @@ package compose
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/containerd/console"
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/compose/v2/pkg/api"
|
||||
"github.com/docker/compose/v2/pkg/compose"
|
||||
@@ -105,27 +102,8 @@ func runExec(ctx context.Context, backend api.Service, opts execOpts) error {
|
||||
Index: opts.index,
|
||||
Detach: opts.detach,
|
||||
WorkingDir: opts.workingDir,
|
||||
|
||||
Stdin: os.Stdin,
|
||||
Stdout: os.Stdout,
|
||||
Stderr: os.Stderr,
|
||||
}
|
||||
|
||||
if execOpts.Tty {
|
||||
con := console.Current()
|
||||
if err := con.SetRaw(); err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err := con.Reset(); err != nil {
|
||||
fmt.Println("Unable to close the console")
|
||||
}
|
||||
}()
|
||||
|
||||
execOpts.Stdin = con
|
||||
execOpts.Stdout = con
|
||||
execOpts.Stderr = con
|
||||
}
|
||||
exitCode, err := backend.Exec(ctx, projectName, execOpts)
|
||||
if exitCode != 0 {
|
||||
errMsg := ""
|
||||
|
||||
@@ -59,13 +59,13 @@ Any data which is not in a volume will be lost.`,
|
||||
}
|
||||
|
||||
func runRemove(ctx context.Context, backend api.Service, opts removeOptions, services []string) error {
|
||||
project, err := opts.toProject(services)
|
||||
project, err := opts.toProjectName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if opts.stop {
|
||||
err := backend.Stop(ctx, project.Name, api.StopOptions{
|
||||
err := backend.Stop(ctx, project, api.StopOptions{
|
||||
Services: services,
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@@ -19,7 +19,6 @@ package compose
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
cgo "github.com/compose-spec/compose-go/cli"
|
||||
@@ -207,9 +206,6 @@ func runRun(ctx context.Context, backend api.Service, project *types.Project, op
|
||||
Command: opts.Command,
|
||||
Detach: opts.Detach,
|
||||
AutoRemove: opts.Remove,
|
||||
Stdin: os.Stdin,
|
||||
Stdout: os.Stdout,
|
||||
Stderr: os.Stderr,
|
||||
Tty: !opts.noTty,
|
||||
WorkingDir: opts.workdir,
|
||||
User: opts.user,
|
||||
|
||||
@@ -46,7 +46,7 @@ func pluginMain() {
|
||||
if err := plugin.PersistentPreRunE(cmd, args); err != nil {
|
||||
return err
|
||||
}
|
||||
lazyInit.WithService(compose.NewComposeService(dockerCli.Client(), dockerCli.ConfigFile()))
|
||||
lazyInit.WithService(compose.NewComposeService(dockerCli))
|
||||
if originalPreRun != nil {
|
||||
return originalPreRun(cmd, args)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,54 @@
|
||||
# docker compose
|
||||
|
||||
<!---MARKER_GEN_START-->
|
||||
Docker Compose
|
||||
|
||||
### Subcommands
|
||||
|
||||
| Name | Description |
|
||||
| --- | --- |
|
||||
| [`build`](compose_build.md) | Build or rebuild services |
|
||||
| [`convert`](compose_convert.md) | Converts the compose file to platform's 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 containers |
|
||||
| [`rm`](compose_rm.md) | Removes stopped service containers |
|
||||
| [`run`](compose_run.md) | Run a one-off command on a service. |
|
||||
| [`start`](compose_start.md) | Start services |
|
||||
| [`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 |
|
||||
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `--ansi` | `string` | `auto` | Control when to print ANSI control characters ("never"\|"always"\|"auto") |
|
||||
| `--compatibility` | | | Run compose in backward compatibility mode |
|
||||
| `--env-file` | `string` | | Specify an alternate environment file. |
|
||||
| `-f`, `--file` | `stringArray` | | Compose configuration files |
|
||||
| `--profile` | `stringArray` | | Specify a profile to enable |
|
||||
| `--project-directory` | `string` | | Specify an alternate working directory
|
||||
(default: the path of the Compose file) |
|
||||
| `-p`, `--project-name` | `string` | | Project name |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
## Description
|
||||
|
||||
@@ -9,8 +59,8 @@ multiple services in Docker containers.
|
||||
Use the `-f` flag to specify the location of a Compose configuration file.
|
||||
|
||||
#### Specifying multiple Compose files
|
||||
You can supply multiple `-f` configuration files. When you supply multiple files, Compose combines them into a single
|
||||
configuration. Compose builds the configuration in the order you supply the files. Subsequent files override and add
|
||||
You can supply multiple `-f` configuration files. When you supply multiple files, Compose combines them into a single
|
||||
configuration. Compose builds the configuration in the order you supply the files. Subsequent files override and add
|
||||
to their predecessors.
|
||||
|
||||
For example, consider this command line:
|
||||
@@ -30,7 +80,7 @@ services:
|
||||
volumes:
|
||||
- "/data"
|
||||
```
|
||||
If the `docker-compose.admin.yml` also specifies this same service, any matching fields override the previous file.
|
||||
If the `docker-compose.admin.yml` also specifies this same service, any matching fields override the previous file.
|
||||
New values, add to the `webapp` service configuration.
|
||||
|
||||
```yaml
|
||||
@@ -41,22 +91,22 @@ services:
|
||||
- DEBUG=1
|
||||
```
|
||||
|
||||
When you use multiple Compose files, all paths in the files are relative to the first configuration file specified
|
||||
When you use multiple Compose files, all paths in the files are relative to the first configuration file specified
|
||||
with `-f`. You can use the `--project-directory` option to override this base path.
|
||||
|
||||
Use a `-f` with `-` (dash) as the filename to read the configuration from stdin. When stdin is used all paths in the
|
||||
Use a `-f` with `-` (dash) as the filename to read the configuration from stdin. When stdin is used all paths in the
|
||||
configuration are relative to the current working directory.
|
||||
|
||||
The `-f` flag is optional. If you don’t provide this flag on the command line, Compose traverses the working directory
|
||||
The `-f` flag is optional. If you don’t provide this flag on the command line, Compose traverses the working directory
|
||||
and its parent directories looking for a `compose.yaml` or `docker-compose.yaml` file.
|
||||
|
||||
#### Specifying a path to a single Compose file
|
||||
You can use the `-f` flag to specify a path to a Compose file that is not located in the current directory, either
|
||||
You can use the `-f` flag to specify a path to a Compose file that is not located in the current directory, either
|
||||
from the command line or by setting up a `COMPOSE_FILE` environment variable in your shell or in an environment file.
|
||||
|
||||
For an example of using the `-f` option at the command line, suppose you are running the Compose Rails sample, and
|
||||
have a `compose.yaml` file in a directory called `sandbox/rails`. You can use a command like `docker compose pull` to
|
||||
get the postgres image for the db service from anywhere by using the `-f` flag as follows:
|
||||
For an example of using the `-f` option at the command line, suppose you are running the Compose Rails sample, and
|
||||
have a `compose.yaml` file in a directory called `sandbox/rails`. You can use a command like `docker compose pull` to
|
||||
get the postgres image for the db service from anywhere by using the `-f` flag as follows:
|
||||
|
||||
```console
|
||||
$ docker compose -f ~/sandbox/rails/compose.yaml pull db
|
||||
@@ -64,17 +114,17 @@ $ docker compose -f ~/sandbox/rails/compose.yaml pull db
|
||||
|
||||
### Use `-p` to specify a project name
|
||||
|
||||
Each configuration has a project name. If you supply a `-p` flag, you can specify a project name. If you don’t
|
||||
specify the flag, Compose uses the current directory name.
|
||||
Each configuration has a project name. If you supply a `-p` flag, you can specify a project name. If you don’t
|
||||
specify the flag, Compose uses the current directory name.
|
||||
Project name can also be set by `COMPOSE_PROJECT_NAME` environment variable.
|
||||
|
||||
Most compose subcommand can be ran without a compose file, just passing
|
||||
Most compose subcommand can be ran without a compose file, just passing
|
||||
project name to retrieve the relevant resources.
|
||||
|
||||
```console
|
||||
$ docker compose -p my_project ps -a
|
||||
NAME SERVICE STATUS PORTS
|
||||
my_project_demo_1 demo running
|
||||
my_project_demo_1 demo running
|
||||
|
||||
$ docker compose -p my_project logs
|
||||
demo_1 | PING localhost (127.0.0.1): 56 data bytes
|
||||
@@ -84,8 +134,8 @@ demo_1 | 64 bytes from 127.0.0.1: seq=0 ttl=64 time=0.095 ms
|
||||
### Use profiles to enable optional services
|
||||
|
||||
Use `--profile` to specify one or more active profiles
|
||||
Calling `docker compose --profile frontend up` will start the services with the profile `frontend` and services
|
||||
without any specified profiles.
|
||||
Calling `docker compose --profile frontend up` will start the services with the profile `frontend` and services
|
||||
without any specified profiles.
|
||||
You can also enable multiple profiles, e.g. with `docker compose --profile frontend --profile debug up` the profiles `frontend` and `debug` will be enabled.
|
||||
|
||||
Profiles can also be set by `COMPOSE_PROFILES` environment variable.
|
||||
@@ -100,5 +150,5 @@ and so does `COMPOSE_PROFILES` environment variable for to the `--profiles` flag
|
||||
|
||||
If flags are explicitly set on command line, associated environment variable is ignored
|
||||
|
||||
Setting the `COMPOSE_IGNORE_ORPHANS` environment variable to `true` will stop docker compose from detecting orphaned
|
||||
Setting the `COMPOSE_IGNORE_ORPHANS` environment variable to `true` will stop docker compose from detecting orphaned
|
||||
containers for the project.
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
# docker compose build
|
||||
|
||||
<!---MARKER_GEN_START-->
|
||||
Build or rebuild services
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `--build-arg` | `stringArray` | | Set build-time variables for services. |
|
||||
| `--no-cache` | | | Do not use cache when building the image |
|
||||
| `--progress` | `string` | `auto` | Set type of progress output (auto, tty, plain, quiet) |
|
||||
| `--pull` | | | Always attempt to pull a newer version of the image. |
|
||||
| `-q`, `--quiet` | | | Don't print anything to STDOUT |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
## Description
|
||||
|
||||
Services are built once and then tagged, by default as `project_service`.
|
||||
Services are built once and then tagged, by default as `project_service`.
|
||||
|
||||
If the Compose file specifies an
|
||||
[image](https://github.com/compose-spec/compose-spec/blob/master/spec.md#image) name,
|
||||
[image](https://github.com/compose-spec/compose-spec/blob/master/spec.md#image) name,
|
||||
the image is tagged with that name, substituting any variables beforehand. See
|
||||
[variable interpolation](https://github.com/compose-spec/compose-spec/blob/master/spec.md#interpolation).
|
||||
|
||||
If you change a service's `Dockerfile` or the contents of its build directory,
|
||||
If you change a service's `Dockerfile` or the contents of its build directory,
|
||||
run `docker compose build` to rebuild it.
|
||||
|
||||
@@ -1,9 +1,35 @@
|
||||
# docker compose convert
|
||||
|
||||
<!---MARKER_GEN_START-->
|
||||
Converts the compose file to platform's canonical format
|
||||
|
||||
### Aliases
|
||||
|
||||
`convert`, `config`
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `--format` | `string` | `yaml` | Format the output. Values: [yaml \| json] |
|
||||
| `--hash` | `string` | | Print the service config hash, one per line. |
|
||||
| `--images` | | | Print the image names, one per line. |
|
||||
| `--no-interpolate` | | | Don't interpolate environment variables. |
|
||||
| `--no-normalize` | | | Don't normalize compose model. |
|
||||
| `-o`, `--output` | `string` | | Save to file (default to stdout) |
|
||||
| `--profiles` | | | Print the profile names, one per line. |
|
||||
| `-q`, `--quiet` | | | Only validate the configuration, don't print anything. |
|
||||
| `--resolve-image-digests` | | | Pin image tags to digests. |
|
||||
| `--services` | | | Print the service names, one per line. |
|
||||
| `--volumes` | | | Print the volume names, one per line. |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
## Description
|
||||
|
||||
`docker compose convert` render the actual data model to be applied on target platform. When used with Docker engine,
|
||||
it merges the Compose files set by `-f` flags, resolves variables in Compose file, and expands short-notation into
|
||||
fully defined Compose model.
|
||||
it merges the Compose files set by `-f` flags, resolves variables in Compose file, and expands short-notation into
|
||||
fully defined Compose model.
|
||||
|
||||
To allow smooth migration from docker-compose, this subcommand declares alias `docker compose config`
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
# docker compose cp
|
||||
|
||||
<!---MARKER_GEN_START-->
|
||||
Copy files/folders between a service container and the local filesystem
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `--all` | | | Copy to all the containers of the service. |
|
||||
| `-a`, `--archive` | | | Archive mode (copy all uid/gid information) |
|
||||
| `-L`, `--follow-link` | | | Always follow symbol link in SRC_PATH |
|
||||
| `--index` | `int` | `1` | Index of the container if there are multiple instances of a service [default: 1]. |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
# docker compose create
|
||||
|
||||
<!---MARKER_GEN_START-->
|
||||
Creates containers for a service.
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `--build` | | | Build images before starting containers. |
|
||||
| `--force-recreate` | | | Recreate containers even if their configuration and image haven't changed. |
|
||||
| `--no-build` | | | Don't build an image, even if it's missing. |
|
||||
| `--no-recreate` | | | If containers already exist, don't recreate them. Incompatible with --force-recreate. |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
|
||||
@@ -1,4 +1,19 @@
|
||||
# docker compose down
|
||||
|
||||
<!---MARKER_GEN_START-->
|
||||
Stop and remove containers, networks
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `--remove-orphans` | | | Remove containers for services not defined in the Compose file. |
|
||||
| `--rmi` | `string` | | Remove images used by services. "local" remove only images that don't have a custom tag ("local"\|"all") |
|
||||
| `-t`, `--timeout` | `int` | `10` | Specify a shutdown timeout in seconds |
|
||||
| `-v`, `--volumes` | | | Remove named volumes declared in the `volumes` section of the Compose file and anonymous volumes attached to containers. |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
## Description
|
||||
|
||||
|
||||
@@ -1,3 +1,16 @@
|
||||
# docker compose events
|
||||
|
||||
<!---MARKER_GEN_START-->
|
||||
Receive real time events from containers.
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `--json` | | | Output events as a stream of json objects |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
## Description
|
||||
|
||||
|
||||
@@ -1,7 +1,26 @@
|
||||
# docker compose exec
|
||||
|
||||
<!---MARKER_GEN_START-->
|
||||
Execute a command in a running container.
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `-d`, `--detach` | | | Detached mode: Run command in the background. |
|
||||
| `-e`, `--env` | `stringArray` | | Set environment variables |
|
||||
| `--index` | `int` | `1` | index of the container if there are multiple instances of a service [default: 1]. |
|
||||
| `-T`, `--no-TTY` | | | Disable pseudo-TTY allocation. By default `docker compose exec` allocates a TTY. |
|
||||
| `--privileged` | | | Give extended privileges to the process. |
|
||||
| `-u`, `--user` | `string` | | Run the command as this user. |
|
||||
| `-w`, `--workdir` | `string` | | Path to workdir directory for this command. |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
## Description
|
||||
|
||||
This is the equivalent of `docker exec` targeting a Compose service.
|
||||
This is the equivalent of `docker exec` targeting a Compose service.
|
||||
|
||||
With this subcommand you can run arbitrary commands in your services. Commands are by default allocating a TTY, so
|
||||
With this subcommand you can run arbitrary commands in your services. Commands are by default allocating a TTY, so
|
||||
you can use a command such as `docker compose exec web sh` to get an interactive prompt.
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
# docker compose images
|
||||
|
||||
<!---MARKER_GEN_START-->
|
||||
List images used by the created containers
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `-q`, `--quiet` | | | Only display IDs |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
|
||||
@@ -1,3 +1,16 @@
|
||||
# docker compose kill
|
||||
|
||||
<!---MARKER_GEN_START-->
|
||||
Force stop service containers.
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `-s`, `--signal` | `string` | `SIGKILL` | SIGNAL to send to the container. |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
## Description
|
||||
|
||||
|
||||
@@ -1,3 +1,22 @@
|
||||
# docker compose logs
|
||||
|
||||
<!---MARKER_GEN_START-->
|
||||
View output from containers
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `-f`, `--follow` | | | Follow log output. |
|
||||
| `--no-color` | | | Produce monochrome output. |
|
||||
| `--no-log-prefix` | | | Don't print prefix in logs. |
|
||||
| `--since` | `string` | | Show logs since timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes) |
|
||||
| `--tail` | `string` | `all` | Number of lines to show from the end of the logs for each container. |
|
||||
| `-t`, `--timestamps` | | | Show timestamps. |
|
||||
| `--until` | `string` | | Show logs before a timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes) |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
## Description
|
||||
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# docker compose ls
|
||||
|
||||
<!---MARKER_GEN_START-->
|
||||
List running compose projects
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `-a`, `--all` | | | Show all stopped Compose projects |
|
||||
| `--filter` | `filter` | | Filter output based on conditions provided. |
|
||||
| `--format` | `string` | `pretty` | Format the output. Values: [pretty \| json]. |
|
||||
| `-q`, `--quiet` | | | Only display IDs. |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
## Description
|
||||
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
# docker compose pause
|
||||
|
||||
<!---MARKER_GEN_START-->
|
||||
Pause services
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
## Description
|
||||
|
||||
|
||||
@@ -1,3 +1,17 @@
|
||||
# docker compose port
|
||||
|
||||
<!---MARKER_GEN_START-->
|
||||
Print the public port for a port binding.
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `--index` | `int` | `1` | index of the container if service has multiple replicas |
|
||||
| `--protocol` | `string` | `tcp` | tcp or udp |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
## Description
|
||||
|
||||
|
||||
@@ -1,3 +1,20 @@
|
||||
# docker compose ps
|
||||
|
||||
<!---MARKER_GEN_START-->
|
||||
List containers
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `-a`, `--all` | | | Show all stopped containers (including those created by the run command) |
|
||||
| `--format` | `string` | `pretty` | Format the output. Values: [pretty \| json] |
|
||||
| `-q`, `--quiet` | | | Only display IDs |
|
||||
| `--services` | | | Display services |
|
||||
| `--status` | `stringArray` | | Filter services by status. Values: [paused \| restarting \| removing \| running \| dead \| created \| exited] |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
## Description
|
||||
|
||||
@@ -7,5 +24,5 @@ Lists containers for a Compose project, with current status and exposed ports.
|
||||
$ docker compose ps
|
||||
NAME SERVICE STATUS PORTS
|
||||
example_foo_1 foo running (healthy) 0.0.0.0:8000->80/tcp
|
||||
example_bar_1 bar exited (1)
|
||||
example_bar_1 bar exited (1)
|
||||
```
|
||||
|
||||
@@ -1,11 +1,26 @@
|
||||
# docker compose pull
|
||||
|
||||
<!---MARKER_GEN_START-->
|
||||
Pull service images
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `--ignore-pull-failures` | | | Pull what it can and ignores images with pull failures |
|
||||
| `--include-deps` | | | Also pull services declared as dependencies |
|
||||
| `-q`, `--quiet` | | | Pull without printing progress information |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
## Description
|
||||
|
||||
Pulls an image associated with a service defined in a `compose.yaml` file, but does not start containers based on
|
||||
Pulls an image associated with a service defined in a `compose.yaml` file, but does not start containers based on
|
||||
those images.
|
||||
|
||||
|
||||
## Examples
|
||||
## Examples
|
||||
|
||||
suppose you have this `compose.yaml`:
|
||||
|
||||
@@ -24,8 +39,8 @@ services:
|
||||
- db
|
||||
```
|
||||
|
||||
If you run `docker compose pull ServiceName` in the same directory as the `compose.yaml` file that defines the service,
|
||||
Docker pulls the associated image. For example, to call the postgres image configured as the db service in our example,
|
||||
If you run `docker compose pull ServiceName` in the same directory as the `compose.yaml` file that defines the service,
|
||||
Docker pulls the associated image. For example, to call the postgres image configured as the db service in our example,
|
||||
you would run `docker compose pull db`.
|
||||
|
||||
```console
|
||||
@@ -46,4 +61,4 @@ $ docker compose pull db
|
||||
⠹ f63c47038e66 Waiting 9.3s
|
||||
⠹ 77a0c198cde5 Waiting 9.3s
|
||||
⠹ c8752d5b785c Waiting 9.3s
|
||||
``̀
|
||||
``̀`
|
||||
|
||||
@@ -1,3 +1,16 @@
|
||||
# docker compose push
|
||||
|
||||
<!---MARKER_GEN_START-->
|
||||
Push service images
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `--ignore-push-failures` | | | Push what it can and ignores images with push failures |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
## Description
|
||||
|
||||
|
||||
@@ -1,8 +1,24 @@
|
||||
# docker compose restart
|
||||
|
||||
<!---MARKER_GEN_START-->
|
||||
Restart containers
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `-t`, `--timeout` | `int` | `10` | Specify a shutdown timeout in seconds |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
## Description
|
||||
|
||||
Restarts all stopped and running services.
|
||||
|
||||
If you make changes to your `compose.yml` configuration, these changes are not reflected
|
||||
after running this command. For example, changes to environment variables (which are added
|
||||
after a container is built, but before the container's command is executed) are not updated
|
||||
If you make changes to your `compose.yml` configuration, these changes are not reflected
|
||||
after running this command. For example, changes to environment variables (which are added
|
||||
after a container is built, but before the container's command is executed) are not updated
|
||||
after restarting.
|
||||
|
||||
If you are looking to configure a service's restart policy, please refer to
|
||||
|
||||
@@ -1,3 +1,23 @@
|
||||
# docker compose rm
|
||||
|
||||
<!---MARKER_GEN_START-->
|
||||
Removes stopped service containers
|
||||
|
||||
By default, anonymous volumes attached to containers will not be removed. You
|
||||
can override this with -v. To list all volumes, use "docker volume ls".
|
||||
|
||||
Any data which is not in a volume will be lost.
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `-f`, `--force` | | | Don't ask to confirm removal |
|
||||
| `-s`, `--stop` | | | Stop the containers, if required, before removing |
|
||||
| `-v`, `--volumes` | | | Remove any anonymous volumes attached to containers |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
## Description
|
||||
|
||||
|
||||
@@ -1,7 +1,35 @@
|
||||
# docker compose run
|
||||
|
||||
<!---MARKER_GEN_START-->
|
||||
Run a one-off command on a service.
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `-d`, `--detach` | | | Run container in background and print container ID |
|
||||
| `--entrypoint` | `string` | | Override the entrypoint of the image |
|
||||
| `-e`, `--env` | `stringArray` | | Set environment variables |
|
||||
| `-i`, `--interactive` | | | Keep STDIN open even if not attached. |
|
||||
| `-l`, `--label` | `stringArray` | | Add or override a label |
|
||||
| `--name` | `string` | | Assign a name to the container |
|
||||
| `-T`, `--no-TTY` | | | Disable pseudo-noTty allocation. By default docker compose run allocates a TTY |
|
||||
| `--no-deps` | | | Don't start linked services. |
|
||||
| `-p`, `--publish` | `stringArray` | | Publish a container's port(s) to the host. |
|
||||
| `--quiet-pull` | | | Pull without printing progress information. |
|
||||
| `--rm` | | | Automatically remove the container when it exits |
|
||||
| `--service-ports` | | | Run command with the service's ports enabled and mapped to the host. |
|
||||
| `--use-aliases` | | | Use the service's network useAliases in the network(s) the container connects to. |
|
||||
| `-u`, `--user` | `string` | | Run as specified username or uid |
|
||||
| `-v`, `--volume` | `stringArray` | | Bind mount a volume. |
|
||||
| `-w`, `--workdir` | `string` | | Working directory inside the container |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
## Description
|
||||
|
||||
Runs a one-time command against a service.
|
||||
Runs a one-time command against a service.
|
||||
|
||||
the following command starts the `web` service and runs `bash` as its command:
|
||||
|
||||
@@ -12,12 +40,12 @@ $ docker compose run web bash
|
||||
Commands you use with run start in new containers with configuration defined by that of the service,
|
||||
including volumes, links, and other details. However, there are two important differences:
|
||||
|
||||
First, the command passed by `run` overrides the command defined in the service configuration. For example, if the
|
||||
`web` service configuration is started with `bash`, then `docker compose run web python app.py` overrides it with
|
||||
First, the command passed by `run` overrides the command defined in the service configuration. For example, if the
|
||||
`web` service configuration is started with `bash`, then `docker compose run web python app.py` overrides it with
|
||||
`python app.py`.
|
||||
|
||||
The second difference is that the `docker compose run` command does not create any of the ports specified in the
|
||||
service configuration. This prevents port collisions with already-open ports. If you do want the service’s ports
|
||||
The second difference is that the `docker compose run` command does not create any of the ports specified in the
|
||||
service configuration. This prevents port collisions with already-open ports. If you do want the service’s ports
|
||||
to be created and mapped to the host, specify the `--service-ports`
|
||||
|
||||
```console
|
||||
@@ -30,8 +58,8 @@ Alternatively, manual port mapping can be specified with the `--publish` or `-p`
|
||||
$ docker compose run --publish 8080:80 -p 2022:22 -p 127.0.0.1:2021:21 web python manage.py shell
|
||||
```
|
||||
|
||||
If you start a service configured with links, the run command first checks to see if the linked service is running
|
||||
and starts the service if it is stopped. Once all the linked services are running, the run executes the command you
|
||||
If you start a service configured with links, the run command first checks to see if the linked service is running
|
||||
and starts the service if it is stopped. Once all the linked services are running, the run executes the command you
|
||||
passed it. For example, you could run:
|
||||
|
||||
```console
|
||||
@@ -52,5 +80,5 @@ If you want to remove the container after running while overriding the container
|
||||
$ docker compose run --rm web python manage.py db upgrade
|
||||
```
|
||||
|
||||
This runs a database upgrade script, and removes the container when finished running, even if a restart policy is
|
||||
This runs a database upgrade script, and removes the container when finished running, even if a restart policy is
|
||||
specified in the service configuration.
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
# docker compose start
|
||||
|
||||
<!---MARKER_GEN_START-->
|
||||
Start services
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
## Description
|
||||
|
||||
|
||||
@@ -1,3 +1,16 @@
|
||||
# docker compose stop
|
||||
|
||||
<!---MARKER_GEN_START-->
|
||||
Stop services
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `-t`, `--timeout` | `int` | `10` | Specify a shutdown timeout in seconds |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
## Description
|
||||
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
# docker compose top
|
||||
|
||||
<!---MARKER_GEN_START-->
|
||||
Display the running processes
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
## Description
|
||||
|
||||
@@ -9,5 +16,5 @@ Displays the running processes.
|
||||
$ docker compose top
|
||||
example_foo_1
|
||||
UID PID PPID C STIME TTY TIME CMD
|
||||
root 142353 142331 2 15:33 ? 00:00:00 ping localhost -c 5
|
||||
root 142353 142331 2 15:33 ? 00:00:00 ping localhost -c 5
|
||||
```
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
# docker compose unpause
|
||||
|
||||
<!---MARKER_GEN_START-->
|
||||
Unpause services
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
## Description
|
||||
|
||||
|
||||
@@ -1,3 +1,35 @@
|
||||
# docker compose up
|
||||
|
||||
<!---MARKER_GEN_START-->
|
||||
Create and start containers
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `--abort-on-container-exit` | | | Stops all containers if any container was stopped. Incompatible with -d |
|
||||
| `--always-recreate-deps` | | | Recreate dependent containers. Incompatible with --no-recreate. |
|
||||
| `--attach` | `stringArray` | | Attach to service output. |
|
||||
| `--attach-dependencies` | | | Attach to dependent containers. |
|
||||
| `--build` | | | Build images before starting containers. |
|
||||
| `-d`, `--detach` | | | Detached mode: Run containers in the background |
|
||||
| `--exit-code-from` | `string` | | Return the exit code of the selected service container. Implies --abort-on-container-exit |
|
||||
| `--force-recreate` | | | Recreate containers even if their configuration and image haven't changed. |
|
||||
| `--no-build` | | | Don't build an image, even if it's missing. |
|
||||
| `--no-color` | | | Produce monochrome output. |
|
||||
| `--no-deps` | | | Don't start linked services. |
|
||||
| `--no-log-prefix` | | | Don't print prefix in logs. |
|
||||
| `--no-recreate` | | | If containers already exist, don't recreate them. Incompatible with --force-recreate. |
|
||||
| `--no-start` | | | Don't start the services after creating them. |
|
||||
| `--quiet-pull` | | | Pull without printing progress information. |
|
||||
| `--remove-orphans` | | | Remove containers for services not defined in the Compose file. |
|
||||
| `-V`, `--renew-anon-volumes` | | | Recreate anonymous volumes instead of retrieving data from the previous containers. |
|
||||
| `--scale` | `stringArray` | | Scale SERVICE to NUM instances. Overrides the `scale` setting in the Compose file if present. |
|
||||
| `-t`, `--timeout` | `int` | `10` | Use this timeout in seconds for container shutdown when attached or when containers are already running. |
|
||||
| `--wait` | | | Wait for services to be running\|healthy. Implies detached mode. |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
## Description
|
||||
|
||||
@@ -5,12 +37,12 @@ Builds, (re)creates, starts, and attaches to containers for a service.
|
||||
|
||||
Unless they are already running, this command also starts any linked services.
|
||||
|
||||
The `docker compose up` command aggregates the output of each container (like `docker compose logs --follow` does).
|
||||
When the command exits, all containers are stopped. Running `docker compose up --detach` starts the containers in the
|
||||
The `docker compose up` command aggregates the output of each container (like `docker compose logs --follow` does).
|
||||
When the command exits, all containers are stopped. Running `docker compose up --detach` starts the containers in the
|
||||
background and leaves them running.
|
||||
|
||||
If there are existing containers for a service, and the service’s configuration or image was changed after the
|
||||
container’s creation, `docker compose up` picks up the changes by stopping and recreating the containers
|
||||
If there are existing containers for a service, and the service’s configuration or image was changed after the
|
||||
container’s creation, `docker compose up` picks up the changes by stopping and recreating the containers
|
||||
(preserving mounted volumes). To prevent Compose from picking up changes, use the `--no-recreate` flag.
|
||||
|
||||
If you want to force Compose to stop and recreate all containers, use the `--force-recreate` flag.
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
# docker compose version
|
||||
|
||||
<!---MARKER_GEN_START-->
|
||||
Show the Docker Compose version information
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `-f`, `--format` | `string` | | Format the output. Values: [pretty \| json]. (Default: pretty) |
|
||||
| `--short` | | | Shows only Compose's version number. |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
@@ -98,7 +98,7 @@ long: |-
|
||||
and so does `COMPOSE_PROFILES` environment variable for to the `--profiles` flag.
|
||||
|
||||
If flags are explicitly set on command line, associated environment variable is ignored
|
||||
|
||||
|
||||
Setting the `COMPOSE_IGNORE_ORPHANS` environment variable to `true` will stop docker compose from detecting orphaned
|
||||
containers for the project.
|
||||
usage: docker compose
|
||||
@@ -129,6 +129,7 @@ cname:
|
||||
- docker compose top
|
||||
- docker compose unpause
|
||||
- docker compose up
|
||||
- docker compose version
|
||||
clink:
|
||||
- docker_compose_build.yaml
|
||||
- docker_compose_convert.yaml
|
||||
@@ -154,6 +155,7 @@ clink:
|
||||
- docker_compose_top.yaml
|
||||
- docker_compose_unpause.yaml
|
||||
- docker_compose_up.yaml
|
||||
- docker_compose_version.yaml
|
||||
options:
|
||||
- option: ansi
|
||||
value_type: string
|
||||
@@ -161,6 +163,17 @@ options:
|
||||
description: |
|
||||
Control when to print ANSI control characters ("never"|"always"|"auto")
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: compatibility
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: Run compose in backward compatibility mode
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -169,6 +182,7 @@ options:
|
||||
value_type: string
|
||||
description: Specify an alternate environment file.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -179,6 +193,7 @@ options:
|
||||
default_value: '[]'
|
||||
description: Compose configuration files
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -188,6 +203,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Do not print ANSI control characters (DEPRECATED)
|
||||
deprecated: false
|
||||
hidden: true
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -197,6 +213,7 @@ options:
|
||||
default_value: '[]'
|
||||
description: Specify a profile to enable
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -207,6 +224,7 @@ options:
|
||||
Specify an alternate working directory
|
||||
(default: the path of the Compose file)
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -216,6 +234,7 @@ options:
|
||||
value_type: string
|
||||
description: Project name
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -225,6 +244,18 @@ options:
|
||||
default_value: "false"
|
||||
description: Show more output
|
||||
deprecated: false
|
||||
hidden: true
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: version
|
||||
shorthand: v
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: Show the Docker Compose version information
|
||||
deprecated: false
|
||||
hidden: true
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -236,6 +267,7 @@ options:
|
||||
Specify an alternate working directory
|
||||
(default: the path of the Compose file)
|
||||
deprecated: false
|
||||
hidden: true
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
|
||||
@@ -19,6 +19,7 @@ options:
|
||||
default_value: '[]'
|
||||
description: Set build-time variables for services.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -28,6 +29,7 @@ options:
|
||||
default_value: "true"
|
||||
description: Compress the build context using gzip. DEPRECATED
|
||||
deprecated: false
|
||||
hidden: true
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -37,6 +39,7 @@ options:
|
||||
default_value: "true"
|
||||
description: Always remove intermediate containers. DEPRECATED
|
||||
deprecated: false
|
||||
hidden: true
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -47,6 +50,7 @@ options:
|
||||
description: |
|
||||
Set memory limit for the build container. Not supported on buildkit yet.
|
||||
deprecated: false
|
||||
hidden: true
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -56,6 +60,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Do not use cache when building the image
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -66,6 +71,7 @@ options:
|
||||
description: |
|
||||
Do not remove intermediate containers after a successful build. DEPRECATED
|
||||
deprecated: false
|
||||
hidden: true
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -75,6 +81,7 @@ options:
|
||||
default_value: "true"
|
||||
description: Build images in parallel. DEPRECATED
|
||||
deprecated: false
|
||||
hidden: true
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -82,8 +89,9 @@ options:
|
||||
- option: progress
|
||||
value_type: string
|
||||
default_value: auto
|
||||
description: Set type of progress output ("auto", "plain", "noTty")
|
||||
description: Set type of progress output (auto, tty, plain, quiet)
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -93,6 +101,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Always attempt to pull a newer version of the image.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -103,6 +112,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Don't print anything to STDOUT
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
|
||||
@@ -16,6 +16,7 @@ options:
|
||||
default_value: yaml
|
||||
description: 'Format the output. Values: [yaml | json]'
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -24,6 +25,17 @@ options:
|
||||
value_type: string
|
||||
description: Print the service config hash, one per line.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: images
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: Print the image names, one per line.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -33,6 +45,27 @@ options:
|
||||
default_value: "false"
|
||||
description: Don't interpolate environment variables.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: no-normalize
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: Don't normalize compose model.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: output
|
||||
shorthand: o
|
||||
value_type: string
|
||||
description: Save to file (default to stdout)
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -42,6 +75,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Print the profile names, one per line.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -52,6 +86,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Only validate the configuration, don't print anything.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -61,6 +96,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Pin image tags to digests.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -70,6 +106,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Print the service names, one per line.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -79,6 +116,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Print the volume names, one per line.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
|
||||
@@ -11,6 +11,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Copy to all the containers of the service.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -21,6 +22,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Archive mode (copy all uid/gid information)
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -31,6 +33,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Always follow symbol link in SRC_PATH
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -41,6 +44,7 @@ options:
|
||||
description: |
|
||||
Index of the container if there are multiple instances of a service [default: 1].
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
|
||||
@@ -10,6 +10,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Build images before starting containers.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -20,6 +21,7 @@ options:
|
||||
description: |
|
||||
Recreate containers even if their configuration and image haven't changed.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -29,6 +31,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Don't build an image, even if it's missing.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -39,6 +42,7 @@ options:
|
||||
description: |
|
||||
If containers already exist, don't recreate them. Incompatible with --force-recreate.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
|
||||
@@ -23,6 +23,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Remove containers for services not defined in the Compose file.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -32,6 +33,7 @@ options:
|
||||
description: |
|
||||
Remove images used by services. "local" remove only images that don't have a custom tag ("local"|"all")
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -42,6 +44,7 @@ options:
|
||||
default_value: "10"
|
||||
description: Specify a shutdown timeout in seconds
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -53,6 +56,7 @@ options:
|
||||
description: |
|
||||
Remove named volumes declared in the `volumes` section of the Compose file and anonymous volumes attached to containers.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
|
||||
@@ -29,6 +29,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Output events as a stream of json objects
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
|
||||
@@ -15,6 +15,7 @@ options:
|
||||
default_value: "false"
|
||||
description: 'Detached mode: Run command in the background.'
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -25,6 +26,7 @@ options:
|
||||
default_value: '[]'
|
||||
description: Set environment variables
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -35,6 +37,18 @@ options:
|
||||
description: |
|
||||
index of the container if there are multiple instances of a service [default: 1].
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: interactive
|
||||
shorthand: i
|
||||
value_type: bool
|
||||
default_value: "true"
|
||||
description: Keep STDIN open even if not attached. DEPRECATED
|
||||
deprecated: false
|
||||
hidden: true
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -46,6 +60,7 @@ options:
|
||||
description: |
|
||||
Disable pseudo-TTY allocation. By default `docker compose exec` allocates a TTY.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -55,6 +70,18 @@ options:
|
||||
default_value: "false"
|
||||
description: Give extended privileges to the process.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: tty
|
||||
shorthand: t
|
||||
value_type: bool
|
||||
default_value: "true"
|
||||
description: Allocate a pseudo-TTY. DEPRECATED
|
||||
deprecated: false
|
||||
hidden: true
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -64,6 +91,7 @@ options:
|
||||
value_type: string
|
||||
description: Run the command as this user.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -73,6 +101,7 @@ options:
|
||||
value_type: string
|
||||
description: Path to workdir directory for this command.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
|
||||
@@ -11,6 +11,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Only display IDs
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
|
||||
@@ -16,6 +16,7 @@ options:
|
||||
default_value: SIGKILL
|
||||
description: SIGNAL to send to the container.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
|
||||
@@ -11,6 +11,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Follow log output.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -20,6 +21,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Produce monochrome output.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -29,6 +31,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Don't print prefix in logs.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -38,6 +41,7 @@ options:
|
||||
description: |
|
||||
Show logs since timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -48,6 +52,7 @@ options:
|
||||
description: |
|
||||
Number of lines to show from the end of the logs for each container.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -58,6 +63,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Show timestamps.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -67,6 +73,7 @@ options:
|
||||
description: |
|
||||
Show logs before a timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
|
||||
@@ -11,6 +11,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Show all stopped Compose projects
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -19,6 +20,7 @@ options:
|
||||
value_type: filter
|
||||
description: Filter output based on conditions provided.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -28,6 +30,7 @@ options:
|
||||
default_value: pretty
|
||||
description: 'Format the output. Values: [pretty | json].'
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -38,6 +41,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Only display IDs.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
command: docker compose pause
|
||||
short: pause services
|
||||
short: Pause services
|
||||
long: |
|
||||
Pauses running containers of a service. They can be unpaused with `docker compose unpause`.
|
||||
usage: docker compose pause [SERVICE...]
|
||||
|
||||
@@ -10,6 +10,7 @@ options:
|
||||
default_value: "1"
|
||||
description: index of the container if service has multiple replicas
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -19,6 +20,7 @@ options:
|
||||
default_value: tcp
|
||||
description: tcp or udp
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
|
||||
@@ -20,14 +20,16 @@ options:
|
||||
description: |
|
||||
Show all stopped containers (including those created by the run command)
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: filter
|
||||
value_type: string
|
||||
description: Filter services by a property
|
||||
description: Filter services by a property. Deprecated, use --status instead
|
||||
deprecated: false
|
||||
hidden: true
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -37,6 +39,7 @@ options:
|
||||
default_value: pretty
|
||||
description: 'Format the output. Values: [pretty | json]'
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -47,6 +50,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Only display IDs
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -56,14 +60,18 @@ options:
|
||||
default_value: "false"
|
||||
description: Display services
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: status
|
||||
value_type: string
|
||||
description: Filter services by status
|
||||
value_type: stringArray
|
||||
default_value: '[]'
|
||||
description: |
|
||||
Filter services by status. Values: [paused | restarting | removing | running | dead | created | exited]
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
|
||||
@@ -12,6 +12,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Pull what it can and ignores images with pull failures
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -21,6 +22,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Also pull services declared as dependencies
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -30,6 +32,7 @@ options:
|
||||
default_value: "true"
|
||||
description: DEPRECATED disable parallel pulling.
|
||||
deprecated: false
|
||||
hidden: true
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -39,6 +42,7 @@ options:
|
||||
default_value: "true"
|
||||
description: DEPRECATED pull multiple images in parallel.
|
||||
deprecated: false
|
||||
hidden: true
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -49,10 +53,52 @@ options:
|
||||
default_value: "false"
|
||||
description: Pull without printing progress information
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
examples: |-
|
||||
suppose you have this `compose.yaml`:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
db:
|
||||
image: postgres
|
||||
web:
|
||||
build: .
|
||||
command: bundle exec rails s -p 3000 -b '0.0.0.0'
|
||||
volumes:
|
||||
- .:/myapp
|
||||
ports:
|
||||
- "3000:3000"
|
||||
depends_on:
|
||||
- db
|
||||
```
|
||||
|
||||
If you run `docker compose pull ServiceName` in the same directory as the `compose.yaml` file that defines the service,
|
||||
Docker pulls the associated image. For example, to call the postgres image configured as the db service in our example,
|
||||
you would run `docker compose pull db`.
|
||||
|
||||
```console
|
||||
$ docker compose pull db
|
||||
[+] Running 1/15
|
||||
⠸ db Pulling 12.4s
|
||||
⠿ 45b42c59be33 Already exists 0.0s
|
||||
⠹ 40adec129f1a Downloading 3.374MB/4.178MB 9.3s
|
||||
⠹ b4c431d00c78 Download complete 9.3s
|
||||
⠹ 2696974e2815 Download complete 9.3s
|
||||
⠹ 564b77596399 Downloading 5.622MB/7.965MB 9.3s
|
||||
⠹ 5044045cf6f2 Downloading 216.7kB/391.1kB 9.3s
|
||||
⠹ d736e67e6ac3 Waiting 9.3s
|
||||
⠹ 390c1c9a5ae4 Waiting 9.3s
|
||||
⠹ c0e62f172284 Waiting 9.3s
|
||||
⠹ ebcdc659c5bf Waiting 9.3s
|
||||
⠹ 29be22cb3acc Waiting 9.3s
|
||||
⠹ f63c47038e66 Waiting 9.3s
|
||||
⠹ 77a0c198cde5 Waiting 9.3s
|
||||
⠹ c8752d5b785c Waiting 9.3s
|
||||
``̀`
|
||||
deprecated: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
|
||||
@@ -28,6 +28,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Push what it can and ignores images with push failures
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
|
||||
@@ -1,6 +1,16 @@
|
||||
command: docker compose restart
|
||||
short: Restart containers
|
||||
long: Restart containers
|
||||
long: |-
|
||||
Restarts all stopped and running services.
|
||||
|
||||
If you make changes to your `compose.yml` configuration, these changes are not reflected
|
||||
after running this command. For example, changes to environment variables (which are added
|
||||
after a container is built, but before the container's command is executed) are not updated
|
||||
after restarting.
|
||||
|
||||
If you are looking to configure a service's restart policy, please refer to
|
||||
[restart](https://github.com/compose-spec/compose-spec/blob/master/spec.md#restart)
|
||||
or [restart_policy](https://github.com/compose-spec/compose-spec/blob/master/deploy.md#restart_policy).
|
||||
usage: docker compose restart
|
||||
pname: docker compose
|
||||
plink: docker_compose.yaml
|
||||
@@ -11,6 +21,7 @@ options:
|
||||
default_value: "10"
|
||||
description: Specify a shutdown timeout in seconds
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
|
||||
@@ -26,6 +26,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Deprecated - no effect
|
||||
deprecated: false
|
||||
hidden: true
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -36,6 +37,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Don't ask to confirm removal
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -46,6 +48,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Stop the containers, if required, before removing
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -56,6 +59,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Remove any anonymous volumes attached to containers
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
|
||||
@@ -65,6 +65,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Run container in background and print container ID
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -73,6 +74,7 @@ options:
|
||||
value_type: string
|
||||
description: Override the entrypoint of the image
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -83,16 +85,29 @@ options:
|
||||
default_value: '[]'
|
||||
description: Set environment variables
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: labels
|
||||
- option: interactive
|
||||
shorthand: i
|
||||
value_type: bool
|
||||
default_value: "true"
|
||||
description: Keep STDIN open even if not attached.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: label
|
||||
shorthand: l
|
||||
value_type: stringArray
|
||||
default_value: '[]'
|
||||
description: Add or override a label
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -101,6 +116,7 @@ options:
|
||||
value_type: string
|
||||
description: Assign a name to the container
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -112,6 +128,7 @@ options:
|
||||
description: |
|
||||
Disable pseudo-noTty allocation. By default docker compose run allocates a TTY
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -121,6 +138,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Don't start linked services.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -131,6 +149,17 @@ options:
|
||||
default_value: '[]'
|
||||
description: Publish a container's port(s) to the host.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: quiet-pull
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: Pull without printing progress information.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -140,6 +169,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Automatically remove the container when it exits
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -150,6 +180,18 @@ options:
|
||||
description: |
|
||||
Run command with the service's ports enabled and mapped to the host.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: tty
|
||||
shorthand: t
|
||||
value_type: bool
|
||||
default_value: "true"
|
||||
description: Allocate a pseudo-TTY.
|
||||
deprecated: false
|
||||
hidden: true
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -160,6 +202,7 @@ options:
|
||||
description: |
|
||||
Use the service's network useAliases in the network(s) the container connects to.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -169,6 +212,7 @@ options:
|
||||
value_type: string
|
||||
description: Run as specified username or uid
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -179,6 +223,7 @@ options:
|
||||
default_value: '[]'
|
||||
description: Bind mount a volume.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -188,6 +233,7 @@ options:
|
||||
value_type: string
|
||||
description: Working directory inside the container
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
|
||||
@@ -12,6 +12,7 @@ options:
|
||||
default_value: "10"
|
||||
description: Specify a shutdown timeout in seconds
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
command: docker compose unpause
|
||||
short: unpause services
|
||||
short: Unpause services
|
||||
long: Unpauses paused containers of a service.
|
||||
usage: docker compose unpause [SERVICE...]
|
||||
pname: docker compose
|
||||
|
||||
@@ -27,6 +27,7 @@ options:
|
||||
description: |
|
||||
Stops all containers if any container was stopped. Incompatible with -d
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -36,6 +37,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Recreate dependent containers. Incompatible with --no-recreate.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -45,6 +47,7 @@ options:
|
||||
default_value: '[]'
|
||||
description: Attach to service output.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -54,6 +57,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Attach to dependent containers.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -63,6 +67,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Build images before starting containers.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -73,16 +78,7 @@ options:
|
||||
default_value: "false"
|
||||
description: 'Detached mode: Run containers in the background'
|
||||
deprecated: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: environment
|
||||
shorthand: e
|
||||
value_type: stringArray
|
||||
default_value: '[]'
|
||||
description: Environment variables
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -92,6 +88,7 @@ options:
|
||||
description: |
|
||||
Return the exit code of the selected service container. Implies --abort-on-container-exit
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -102,6 +99,7 @@ options:
|
||||
description: |
|
||||
Recreate containers even if their configuration and image haven't changed.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -111,6 +109,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Don't build an image, even if it's missing.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -120,6 +119,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Produce monochrome output.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -129,6 +129,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Don't start linked services.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -138,6 +139,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Don't print prefix in logs.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -148,6 +150,7 @@ options:
|
||||
description: |
|
||||
If containers already exist, don't recreate them. Incompatible with --force-recreate.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -157,6 +160,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Don't start the services after creating them.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -166,6 +170,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Pull without printing progress information.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -175,6 +180,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Remove containers for services not defined in the Compose file.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -186,6 +192,7 @@ options:
|
||||
description: |
|
||||
Recreate anonymous volumes instead of retrieving data from the previous containers.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -196,6 +203,7 @@ options:
|
||||
description: |
|
||||
Scale SERVICE to NUM instances. Overrides the `scale` setting in the Compose file if present.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -207,6 +215,17 @@ options:
|
||||
description: |
|
||||
Use this timeout in seconds for container shutdown when attached or when containers are already running.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: wait
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: Wait for services to be running|healthy. Implies detached mode.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
|
||||
@@ -10,6 +10,7 @@ options:
|
||||
value_type: string
|
||||
description: 'Format the output. Values: [pretty | json]. (Default: pretty)'
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -19,6 +20,7 @@ options:
|
||||
default_value: "false"
|
||||
description: Shows only Compose's version number.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
|
||||
@@ -26,12 +26,14 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func generateCliYaml(opts *options) error {
|
||||
cmd := &cobra.Command{Use: "docker"}
|
||||
func generateDocs(opts *options) error {
|
||||
cmd := &cobra.Command{
|
||||
Use: "docker",
|
||||
DisableAutoGenTag: true,
|
||||
}
|
||||
cmd.AddCommand(compose.RootCommand(nil))
|
||||
disableFlagsInUseLine(cmd)
|
||||
|
||||
cmd.DisableAutoGenTag = true
|
||||
tool, err := clidocstool.New(clidocstool.Options{
|
||||
Root: cmd,
|
||||
SourceDir: opts.source,
|
||||
@@ -41,7 +43,7 @@ func generateCliYaml(opts *options) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return tool.GenYamlTree(cmd)
|
||||
return tool.GenAllTree()
|
||||
}
|
||||
|
||||
func disableFlagsInUseLine(cmd *cobra.Command) {
|
||||
@@ -69,12 +71,12 @@ type options struct {
|
||||
func main() {
|
||||
cwd, _ := os.Getwd()
|
||||
opts := &options{
|
||||
source: cwd,
|
||||
source: filepath.Join(cwd, "docs", "reference"),
|
||||
target: filepath.Join(cwd, "docs", "reference"),
|
||||
}
|
||||
fmt.Printf("Project root: %s\n", opts.source)
|
||||
fmt.Printf("Generating yaml files into %s\n", opts.target)
|
||||
if err := generateCliYaml(opts); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to generate yaml files: %s\n", err.Error())
|
||||
if err := generateDocs(opts); err != nil {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "Failed to generate documentation: %s\n", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
4
go.mod
4
go.mod
@@ -12,7 +12,7 @@ require (
|
||||
github.com/distribution/distribution/v3 v3.0.0-20210316161203-a01c71e2477e
|
||||
github.com/docker/buildx v0.7.1
|
||||
github.com/docker/cli v20.10.12+incompatible
|
||||
github.com/docker/cli-docs-tool v0.2.1
|
||||
github.com/docker/cli-docs-tool v0.4.0
|
||||
github.com/docker/docker v20.10.7+incompatible
|
||||
github.com/docker/go-connections v0.4.0
|
||||
github.com/docker/go-units v0.4.0
|
||||
@@ -32,6 +32,7 @@ require (
|
||||
github.com/spf13/cobra v1.3.0
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/theupdateframework/notary v0.6.1
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||
gotest.tools v2.2.0+incompatible
|
||||
gotest.tools/v3 v3.1.0
|
||||
@@ -94,7 +95,6 @@ require (
|
||||
github.com/qri-io/jsonpointer v0.1.0 // indirect
|
||||
github.com/qri-io/jsonschema v0.1.1 // indirect
|
||||
github.com/sergi/go-diff v1.1.0 // indirect
|
||||
github.com/theupdateframework/notary v0.6.1 // indirect
|
||||
github.com/tonistiigi/fsutil v0.0.0-20210818161904-4442383b5028 // indirect
|
||||
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea // indirect
|
||||
github.com/tonistiigi/vt100 v0.0.0-20210615222946-8066bb97264f // indirect
|
||||
|
||||
3
go.sum
3
go.sum
@@ -500,8 +500,9 @@ github.com/docker/buildx v0.7.1 h1:l2DlW8YDbB3pH2bUFY5Q9pPQdhd42wqlnO5hoyWrjYM=
|
||||
github.com/docker/buildx v0.7.1/go.mod h1:PzxALHhYWPNhw/8JajPOJBkvx1w2tgOnppL4ESg0wOY=
|
||||
github.com/docker/cli v20.10.3-0.20210702143511-f782d1355eff+incompatible h1:CaaxCD/l9Dxogu6lxf7AQautlv3sHULrasPadayp0fM=
|
||||
github.com/docker/cli v20.10.3-0.20210702143511-f782d1355eff+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/cli-docs-tool v0.2.1 h1:ffZhhdws6kE+dCKHLMlYROZz8z01RtWbz+g4xz0eBIU=
|
||||
github.com/docker/cli-docs-tool v0.2.1/go.mod h1:rgW5KKdNpLMBIuH4WQ/1RNh38nH+/Ay5jgL4P0ZMPpY=
|
||||
github.com/docker/cli-docs-tool v0.4.0 h1:MdfKoErGEbFqIxQ8an9BsZ+YzKUGd58RBVkV+Q82GPo=
|
||||
github.com/docker/cli-docs-tool v0.4.0/go.mod h1:rgW5KKdNpLMBIuH4WQ/1RNh38nH+/Ay5jgL4P0ZMPpY=
|
||||
github.com/docker/compose-on-kubernetes v0.4.19-0.20190128150448-356b2919c496/go.mod h1:iT2pYfi580XlpaV4KmK0T6+4/9+XoKmk/fhoDod1emE=
|
||||
github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY=
|
||||
github.com/docker/distribution v2.6.0-rc.1.0.20180327202408-83389a148052+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
|
||||
@@ -19,7 +19,6 @@ package api
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -59,7 +58,7 @@ type Service interface {
|
||||
// RunOneOffContainer creates a service oneoff container and starts its dependencies
|
||||
RunOneOffContainer(ctx context.Context, project *types.Project, opts RunOptions) (int, error)
|
||||
// Remove executes the equivalent to a `compose rm`
|
||||
Remove(ctx context.Context, project *types.Project, options RemoveOptions) error
|
||||
Remove(ctx context.Context, project string, options RemoveOptions) error
|
||||
// Exec executes a command in a running service container
|
||||
Exec(ctx context.Context, project string, opts RunOptions) (int, error)
|
||||
// Copy copies a file/folder between a service container and the local filesystem
|
||||
@@ -216,9 +215,6 @@ type RunOptions struct {
|
||||
Entrypoint []string
|
||||
Detach bool
|
||||
AutoRemove bool
|
||||
Stdin io.ReadCloser
|
||||
Stdout io.WriteCloser
|
||||
Stderr io.WriteCloser
|
||||
Tty bool
|
||||
WorkingDir string
|
||||
User string
|
||||
|
||||
@@ -39,7 +39,7 @@ type ServiceProxy struct {
|
||||
ConvertFn func(ctx context.Context, project *types.Project, options ConvertOptions) ([]byte, error)
|
||||
KillFn func(ctx context.Context, project *types.Project, options KillOptions) error
|
||||
RunOneOffContainerFn func(ctx context.Context, project *types.Project, opts RunOptions) (int, error)
|
||||
RemoveFn func(ctx context.Context, project *types.Project, options RemoveOptions) error
|
||||
RemoveFn func(ctx context.Context, project string, options RemoveOptions) error
|
||||
ExecFn func(ctx context.Context, project string, opts RunOptions) (int, error)
|
||||
CopyFn func(ctx context.Context, project string, options CopyOptions) error
|
||||
PauseFn func(ctx context.Context, project string, options PauseOptions) error
|
||||
@@ -241,13 +241,10 @@ func (s *ServiceProxy) RunOneOffContainer(ctx context.Context, project *types.Pr
|
||||
}
|
||||
|
||||
// Remove implements Service interface
|
||||
func (s *ServiceProxy) Remove(ctx context.Context, project *types.Project, options RemoveOptions) error {
|
||||
func (s *ServiceProxy) Remove(ctx context.Context, project string, options RemoveOptions) error {
|
||||
if s.RemoveFn == nil {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
for _, i := range s.interceptors {
|
||||
i(ctx, project)
|
||||
}
|
||||
return s.RemoveFn(ctx, project, options)
|
||||
}
|
||||
|
||||
|
||||
@@ -137,7 +137,7 @@ func (s *composeService) attachContainerStreams(ctx context.Context, container s
|
||||
func (s *composeService) getContainerStreams(ctx context.Context, container string) (io.WriteCloser, io.ReadCloser, error) {
|
||||
var stdout io.ReadCloser
|
||||
var stdin io.WriteCloser
|
||||
cnx, err := s.apiClient.ContainerAttach(ctx, container, moby.ContainerAttachOptions{
|
||||
cnx, err := s.apiClient().ContainerAttach(ctx, container, moby.ContainerAttachOptions{
|
||||
Stream: true,
|
||||
Stdin: true,
|
||||
Stdout: true,
|
||||
@@ -151,7 +151,7 @@ func (s *composeService) getContainerStreams(ctx context.Context, container stri
|
||||
}
|
||||
|
||||
// Fallback to logs API
|
||||
logs, err := s.apiClient.ContainerLogs(ctx, container, moby.ContainerLogsOptions{
|
||||
logs, err := s.apiClient().ContainerLogs(ctx, container, moby.ContainerLogsOptions{
|
||||
ShowStdout: true,
|
||||
ShowStderr: true,
|
||||
Follow: true,
|
||||
|
||||
@@ -19,7 +19,6 @@ package compose
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
@@ -193,7 +192,7 @@ func (s *composeService) getLocalImagesDigests(ctx context.Context, project *typ
|
||||
}
|
||||
|
||||
func (s *composeService) serverInfo(ctx context.Context) (command.ServerInfo, error) {
|
||||
ping, err := s.apiClient.Ping(ctx)
|
||||
ping, err := s.apiClient().Ping(ctx)
|
||||
if err != nil {
|
||||
return command.ServerInfo{}, err
|
||||
}
|
||||
@@ -258,7 +257,7 @@ func (s *composeService) toBuildOptions(project *types.Project, service types.Se
|
||||
NetworkMode: service.Build.Network,
|
||||
ExtraHosts: service.Build.ExtraHosts,
|
||||
Session: []session.Attachable{
|
||||
authprovider.NewDockerAuthProvider(os.Stderr),
|
||||
authprovider.NewDockerAuthProvider(s.stderr()),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ import (
|
||||
|
||||
func (s *composeService) doBuildBuildkit(ctx context.Context, project *types.Project, opts map[string]build.Options, mode string) (map[string]string, error) {
|
||||
const drivername = "default"
|
||||
d, err := driver.GetDriver(ctx, drivername, nil, s.apiClient, s.configFile, nil, nil, nil, nil, nil, project.WorkingDir)
|
||||
d, err := driver.GetDriver(ctx, drivername, nil, s.apiClient(), s.configFile(), nil, nil, nil, nil, nil, project.WorkingDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -48,7 +48,7 @@ func (s *composeService) doBuildBuildkit(ctx context.Context, project *types.Pro
|
||||
w := xprogress.NewPrinter(progressCtx, os.Stdout, mode)
|
||||
|
||||
// We rely on buildx "docker" builder integrated in docker engine, so don't need a DockerAPI here
|
||||
response, err := build.Build(ctx, driverInfo, opts, nil, filepath.Dir(s.configFile.Filename), w)
|
||||
response, err := build.Build(ctx, driverInfo, opts, nil, filepath.Dir(s.configFile().Filename), w)
|
||||
errW := w.Wait()
|
||||
if err == nil {
|
||||
err = errW
|
||||
|
||||
@@ -69,8 +69,8 @@ func (s *composeService) doBuildClassicSimpleImage(ctx context.Context, options
|
||||
|
||||
dockerfileName := options.Inputs.DockerfilePath
|
||||
specifiedContext := options.Inputs.ContextPath
|
||||
progBuff := os.Stdout
|
||||
buildBuff := os.Stdout
|
||||
progBuff := s.stdout()
|
||||
buildBuff := s.stdout()
|
||||
if options.ImageIDFile != "" {
|
||||
// Avoid leaving a stale file if we eventually fail
|
||||
if err := os.Remove(options.ImageIDFile); err != nil && !os.IsNotExist(err) {
|
||||
@@ -155,7 +155,7 @@ func (s *composeService) doBuildClassicSimpleImage(ctx context.Context, options
|
||||
body = progress.NewProgressReader(buildCtx, progressOutput, 0, "", "Sending build context to Docker daemon")
|
||||
}
|
||||
|
||||
configFile := s.configFile
|
||||
configFile := s.configFile()
|
||||
creds, err := configFile.GetAllCredentials()
|
||||
if err != nil {
|
||||
return "", err
|
||||
@@ -171,7 +171,7 @@ func (s *composeService) doBuildClassicSimpleImage(ctx context.Context, options
|
||||
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
response, err := s.apiClient.ImageBuild(ctx, body, buildOptions)
|
||||
response, err := s.apiClient().ImageBuild(ctx, body, buildOptions)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -181,13 +181,13 @@ func (s *composeService) doBuildClassicSimpleImage(ctx context.Context, options
|
||||
aux := func(msg jsonmessage.JSONMessage) {
|
||||
var result dockertypes.BuildResult
|
||||
if err := json.Unmarshal(*msg.Aux, &result); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to parse aux message: %s", err)
|
||||
fmt.Fprintf(s.stderr(), "Failed to parse aux message: %s", err)
|
||||
} else {
|
||||
imageID = result.ID
|
||||
}
|
||||
}
|
||||
|
||||
err = jsonmessage.DisplayJSONMessagesStream(response.Body, buildBuff, progBuff.Fd(), true, aux)
|
||||
err = jsonmessage.DisplayJSONMessagesStream(response.Body, buildBuff, progBuff.FD(), true, aux)
|
||||
if err != nil {
|
||||
if jerr, ok := err.(*jsonmessage.JSONError); ok {
|
||||
// If no error code is set, default to 1
|
||||
@@ -203,7 +203,7 @@ func (s *composeService) doBuildClassicSimpleImage(ctx context.Context, options
|
||||
// daemon isn't running Windows.
|
||||
if response.OSType != "windows" && runtime.GOOS == "windows" {
|
||||
// if response.OSType != "windows" && runtime.GOOS == "windows" && !options.quiet {
|
||||
fmt.Fprintln(os.Stdout, "SECURITY WARNING: You are building a Docker "+
|
||||
fmt.Fprintln(s.stdout(), "SECURITY WARNING: You are building a Docker "+
|
||||
"image from Windows against a non-Windows Docker host. All files and "+
|
||||
"directories added to build context will have '-rwxr-xr-x' permissions. "+
|
||||
"It is recommended to double check and reset permissions for sensitive "+
|
||||
|
||||
@@ -21,13 +21,16 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/compose/v2/pkg/api"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/cli/config/configfile"
|
||||
"github.com/docker/cli/cli/streams"
|
||||
moby "github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/sanathkr/go-yaml"
|
||||
@@ -37,19 +40,41 @@ import (
|
||||
var Separator = "-"
|
||||
|
||||
// NewComposeService create a local implementation of the compose.Service API
|
||||
func NewComposeService(apiClient client.APIClient, configFile *configfile.ConfigFile) api.Service {
|
||||
func NewComposeService(dockerCli command.Cli) api.Service {
|
||||
return &composeService{
|
||||
apiClient: apiClient,
|
||||
configFile: configFile,
|
||||
dockerCli: dockerCli,
|
||||
}
|
||||
}
|
||||
|
||||
type composeService struct {
|
||||
apiClient client.APIClient
|
||||
configFile *configfile.ConfigFile
|
||||
dockerCli command.Cli
|
||||
}
|
||||
|
||||
func (s *composeService) apiClient() client.APIClient {
|
||||
return s.dockerCli.Client()
|
||||
}
|
||||
|
||||
func (s *composeService) configFile() *configfile.ConfigFile {
|
||||
return s.dockerCli.ConfigFile()
|
||||
}
|
||||
|
||||
func (s *composeService) stdout() *streams.Out {
|
||||
return s.dockerCli.Out()
|
||||
}
|
||||
|
||||
func (s *composeService) stdin() *streams.In {
|
||||
return s.dockerCli.In()
|
||||
}
|
||||
|
||||
func (s *composeService) stderr() io.Writer {
|
||||
return s.dockerCli.Err()
|
||||
}
|
||||
|
||||
func getCanonicalContainerName(c moby.Container) string {
|
||||
if len(c.Names) == 0 {
|
||||
// corner case, sometime happens on removal. return short ID as a safeguard value
|
||||
return c.ID[:12]
|
||||
}
|
||||
// Names return container canonical name /foo + link aliases /linked_by/foo
|
||||
for _, name := range c.Names {
|
||||
if strings.LastIndex(name, "/") == 0 {
|
||||
@@ -149,3 +174,23 @@ SERVICES:
|
||||
|
||||
return project, nil
|
||||
}
|
||||
|
||||
// actualState list resources labelled by projectName to rebuild compose project model
|
||||
func (s *composeService) actualState(ctx context.Context, projectName string, services []string) (Containers, *types.Project, error) {
|
||||
var containers Containers
|
||||
// don't filter containers by options.Services so projectFromName can rebuild project with all existing resources
|
||||
containers, err := s.getContainers(ctx, projectName, oneOffInclude, true)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
project, err := s.projectFromName(containers, projectName, services...)
|
||||
if err != nil && !api.IsNotFoundError(err) {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if len(services) > 0 {
|
||||
containers = containers.filter(isService(services...))
|
||||
}
|
||||
return containers, project, nil
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ func (s *composeService) getContainers(ctx context.Context, project string, oneO
|
||||
f = append(f, oneOffFilter(false))
|
||||
case oneOffInclude:
|
||||
}
|
||||
containers, err := s.apiClient.ContainerList(ctx, moby.ContainerListOptions{
|
||||
containers, err := s.apiClient().ContainerList(ctx, moby.ContainerListOptions{
|
||||
Filters: filters.NewArgs(f...),
|
||||
All: stopped,
|
||||
})
|
||||
|
||||
@@ -180,11 +180,11 @@ func (c *convergence) ensureService(ctx context.Context, project *types.Project,
|
||||
// Scale Down
|
||||
container := container
|
||||
eg.Go(func() error {
|
||||
err := c.service.apiClient.ContainerStop(ctx, container.ID, timeout)
|
||||
err := c.service.apiClient().ContainerStop(ctx, container.ID, timeout)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return c.service.apiClient.ContainerRemove(ctx, container.ID, moby.ContainerRemoveOptions{})
|
||||
return c.service.apiClient().ContainerRemove(ctx, container.ID, moby.ContainerRemoveOptions{})
|
||||
})
|
||||
continue
|
||||
}
|
||||
@@ -395,13 +395,13 @@ func (s *composeService) recreateContainer(ctx context.Context, project *types.P
|
||||
var created moby.Container
|
||||
w := progress.ContextWriter(ctx)
|
||||
w.Event(progress.NewEvent(getContainerProgressName(replaced), progress.Working, "Recreate"))
|
||||
err := s.apiClient.ContainerStop(ctx, replaced.ID, timeout)
|
||||
err := s.apiClient().ContainerStop(ctx, replaced.ID, timeout)
|
||||
if err != nil {
|
||||
return created, err
|
||||
}
|
||||
name := getCanonicalContainerName(replaced)
|
||||
tmpName := fmt.Sprintf("%s_%s", replaced.ID[:12], name)
|
||||
err = s.apiClient.ContainerRename(ctx, replaced.ID, tmpName)
|
||||
err = s.apiClient().ContainerRename(ctx, replaced.ID, tmpName)
|
||||
if err != nil {
|
||||
return created, err
|
||||
}
|
||||
@@ -419,7 +419,7 @@ func (s *composeService) recreateContainer(ctx context.Context, project *types.P
|
||||
if err != nil {
|
||||
return created, err
|
||||
}
|
||||
err = s.apiClient.ContainerRemove(ctx, replaced.ID, moby.ContainerRemoveOptions{})
|
||||
err = s.apiClient().ContainerRemove(ctx, replaced.ID, moby.ContainerRemoveOptions{})
|
||||
if err != nil {
|
||||
return created, err
|
||||
}
|
||||
@@ -444,7 +444,7 @@ func setDependentLifecycle(project *types.Project, service string, strategy stri
|
||||
func (s *composeService) startContainer(ctx context.Context, container moby.Container) error {
|
||||
w := progress.ContextWriter(ctx)
|
||||
w.Event(progress.NewEvent(getContainerProgressName(container), progress.Working, "Restart"))
|
||||
err := s.apiClient.ContainerStart(ctx, container.ID, moby.ContainerStartOptions{})
|
||||
err := s.apiClient().ContainerStart(ctx, container.ID, moby.ContainerStartOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -468,11 +468,11 @@ func (s *composeService) createMobyContainer(ctx context.Context, project *types
|
||||
}
|
||||
plat = &p
|
||||
}
|
||||
response, err := s.apiClient.ContainerCreate(ctx, containerConfig, hostConfig, networkingConfig, plat, name)
|
||||
response, err := s.apiClient().ContainerCreate(ctx, containerConfig, hostConfig, networkingConfig, plat, name)
|
||||
if err != nil {
|
||||
return created, err
|
||||
}
|
||||
inspectedContainer, err := s.apiClient.ContainerInspect(ctx, response.ID)
|
||||
inspectedContainer, err := s.apiClient().ContainerInspect(ctx, response.ID)
|
||||
if err != nil {
|
||||
return created, err
|
||||
}
|
||||
@@ -502,7 +502,7 @@ func (s *composeService) createMobyContainer(ctx context.Context, project *types
|
||||
if shortIDAliasExists(created.ID, val.Aliases...) {
|
||||
continue
|
||||
}
|
||||
err = s.apiClient.NetworkDisconnect(ctx, netwrk.Name, created.ID, false)
|
||||
err = s.apiClient().NetworkDisconnect(ctx, netwrk.Name, created.ID, false)
|
||||
if err != nil {
|
||||
return created, err
|
||||
}
|
||||
@@ -596,7 +596,7 @@ func (s *composeService) connectContainerToNetwork(ctx context.Context, id strin
|
||||
IPv6Address: ipv6Address,
|
||||
}
|
||||
}
|
||||
err := s.apiClient.NetworkConnect(ctx, netwrk, id, &network.EndpointSettings{
|
||||
err := s.apiClient().NetworkConnect(ctx, netwrk, id, &network.EndpointSettings{
|
||||
Aliases: aliases,
|
||||
IPAddress: ipv4Address,
|
||||
GlobalIPv6Address: ipv6Address,
|
||||
@@ -619,7 +619,7 @@ func (s *composeService) isServiceHealthy(ctx context.Context, project *types.Pr
|
||||
return false, nil
|
||||
}
|
||||
for _, c := range containers {
|
||||
container, err := s.apiClient.ContainerInspect(ctx, c.ID)
|
||||
container, err := s.apiClient().ContainerInspect(ctx, c.ID)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -651,7 +651,7 @@ func (s *composeService) isServiceCompleted(ctx context.Context, project *types.
|
||||
return false, 0, err
|
||||
}
|
||||
for _, c := range containers {
|
||||
container, err := s.apiClient.ContainerInspect(ctx, c.ID)
|
||||
container, err := s.apiClient().ContainerInspect(ctx, c.ID)
|
||||
if err != nil {
|
||||
return false, 0, err
|
||||
}
|
||||
@@ -671,7 +671,7 @@ func (s *composeService) startService(ctx context.Context, project *types.Projec
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
containers, err := s.apiClient.ContainerList(ctx, moby.ContainerListOptions{
|
||||
containers, err := s.apiClient().ContainerList(ctx, moby.ContainerListOptions{
|
||||
Filters: filters.NewArgs(
|
||||
projectFilter(project.Name),
|
||||
serviceFilter(service.Name),
|
||||
@@ -700,7 +700,7 @@ func (s *composeService) startService(ctx context.Context, project *types.Projec
|
||||
eg.Go(func() error {
|
||||
eventName := getContainerProgressName(container)
|
||||
w.Event(progress.StartingEvent(eventName))
|
||||
err := s.apiClient.ContainerStart(ctx, container.ID, moby.ContainerStartOptions{})
|
||||
err := s.apiClient().ContainerStart(ctx, container.ID, moby.ContainerStartOptions{})
|
||||
if err == nil {
|
||||
w.Event(progress.StartedEvent(eventName))
|
||||
}
|
||||
|
||||
@@ -74,8 +74,11 @@ func TestServiceLinks(t *testing.T) {
|
||||
t.Run("service links default", func(t *testing.T) {
|
||||
mockCtrl := gomock.NewController(t)
|
||||
defer mockCtrl.Finish()
|
||||
|
||||
apiClient := mocks.NewMockAPIClient(mockCtrl)
|
||||
tested.apiClient = apiClient
|
||||
cli := mocks.NewMockCli(mockCtrl)
|
||||
tested.dockerCli = cli
|
||||
cli.EXPECT().Client().Return(apiClient).AnyTimes()
|
||||
|
||||
s.Links = []string{"db"}
|
||||
|
||||
@@ -95,7 +98,9 @@ func TestServiceLinks(t *testing.T) {
|
||||
mockCtrl := gomock.NewController(t)
|
||||
defer mockCtrl.Finish()
|
||||
apiClient := mocks.NewMockAPIClient(mockCtrl)
|
||||
tested.apiClient = apiClient
|
||||
cli := mocks.NewMockCli(mockCtrl)
|
||||
tested.dockerCli = cli
|
||||
cli.EXPECT().Client().Return(apiClient).AnyTimes()
|
||||
|
||||
s.Links = []string{"db:db"}
|
||||
|
||||
@@ -115,7 +120,9 @@ func TestServiceLinks(t *testing.T) {
|
||||
mockCtrl := gomock.NewController(t)
|
||||
defer mockCtrl.Finish()
|
||||
apiClient := mocks.NewMockAPIClient(mockCtrl)
|
||||
tested.apiClient = apiClient
|
||||
cli := mocks.NewMockCli(mockCtrl)
|
||||
tested.dockerCli = cli
|
||||
cli.EXPECT().Client().Return(apiClient).AnyTimes()
|
||||
|
||||
s.Links = []string{"db:dbname"}
|
||||
|
||||
@@ -135,7 +142,9 @@ func TestServiceLinks(t *testing.T) {
|
||||
mockCtrl := gomock.NewController(t)
|
||||
defer mockCtrl.Finish()
|
||||
apiClient := mocks.NewMockAPIClient(mockCtrl)
|
||||
tested.apiClient = apiClient
|
||||
cli := mocks.NewMockCli(mockCtrl)
|
||||
tested.dockerCli = cli
|
||||
cli.EXPECT().Client().Return(apiClient).AnyTimes()
|
||||
|
||||
s.Links = []string{"db:dbname"}
|
||||
s.ExternalLinks = []string{"db1:db2"}
|
||||
@@ -159,7 +168,9 @@ func TestServiceLinks(t *testing.T) {
|
||||
mockCtrl := gomock.NewController(t)
|
||||
defer mockCtrl.Finish()
|
||||
apiClient := mocks.NewMockAPIClient(mockCtrl)
|
||||
tested.apiClient = apiClient
|
||||
cli := mocks.NewMockCli(mockCtrl)
|
||||
tested.dockerCli = cli
|
||||
cli.EXPECT().Client().Return(apiClient).AnyTimes()
|
||||
|
||||
s.Links = []string{}
|
||||
s.ExternalLinks = []string{}
|
||||
@@ -189,8 +200,11 @@ func TestServiceLinks(t *testing.T) {
|
||||
func TestWaitDependencies(t *testing.T) {
|
||||
mockCtrl := gomock.NewController(t)
|
||||
defer mockCtrl.Finish()
|
||||
api := mocks.NewMockAPIClient(mockCtrl)
|
||||
tested.apiClient = api
|
||||
|
||||
apiClient := mocks.NewMockAPIClient(mockCtrl)
|
||||
cli := mocks.NewMockCli(mockCtrl)
|
||||
tested.dockerCli = cli
|
||||
cli.EXPECT().Client().Return(apiClient).AnyTimes()
|
||||
|
||||
t.Run("should skip dependencies with scale 0", func(t *testing.T) {
|
||||
dbService := types.ServiceConfig{Name: "db", Scale: 0}
|
||||
|
||||
@@ -107,7 +107,7 @@ func (s *composeService) copyToContainer(ctx context.Context, containerID string
|
||||
|
||||
// Prepare destination copy info by stat-ing the container path.
|
||||
dstInfo := archive.CopyInfo{Path: dstPath}
|
||||
dstStat, err := s.apiClient.ContainerStatPath(ctx, containerID, dstPath)
|
||||
dstStat, err := s.apiClient().ContainerStatPath(ctx, containerID, dstPath)
|
||||
|
||||
// If the destination is a symbolic link, we should evaluate it.
|
||||
if err == nil && dstStat.Mode&os.ModeSymlink != 0 {
|
||||
@@ -119,7 +119,7 @@ func (s *composeService) copyToContainer(ctx context.Context, containerID string
|
||||
}
|
||||
|
||||
dstInfo.Path = linkTarget
|
||||
dstStat, err = s.apiClient.ContainerStatPath(ctx, containerID, linkTarget)
|
||||
dstStat, err = s.apiClient().ContainerStatPath(ctx, containerID, linkTarget)
|
||||
}
|
||||
|
||||
// Validate the destination path
|
||||
@@ -143,7 +143,7 @@ func (s *composeService) copyToContainer(ctx context.Context, containerID string
|
||||
)
|
||||
|
||||
if srcPath == "-" {
|
||||
content = os.Stdin
|
||||
content = s.stdin()
|
||||
resolvedDstPath = dstInfo.Path
|
||||
if !dstInfo.IsDir {
|
||||
return errors.Errorf("destination \"%s:%s\" must be a directory", containerID, dstPath)
|
||||
@@ -187,7 +187,7 @@ func (s *composeService) copyToContainer(ctx context.Context, containerID string
|
||||
AllowOverwriteDirWithFile: false,
|
||||
CopyUIDGID: opts.CopyUIDGID,
|
||||
}
|
||||
return s.apiClient.CopyToContainer(ctx, containerID, resolvedDstPath, content, options)
|
||||
return s.apiClient().CopyToContainer(ctx, containerID, resolvedDstPath, content, options)
|
||||
}
|
||||
|
||||
func (s *composeService) copyFromContainer(ctx context.Context, containerID, srcPath, dstPath string, opts api.CopyOptions) error {
|
||||
@@ -207,7 +207,7 @@ func (s *composeService) copyFromContainer(ctx context.Context, containerID, src
|
||||
// if client requests to follow symbol link, then must decide target file to be copied
|
||||
var rebaseName string
|
||||
if opts.FollowLink {
|
||||
srcStat, err := s.apiClient.ContainerStatPath(ctx, containerID, srcPath)
|
||||
srcStat, err := s.apiClient().ContainerStatPath(ctx, containerID, srcPath)
|
||||
|
||||
// If the destination is a symbolic link, we should follow it.
|
||||
if err == nil && srcStat.Mode&os.ModeSymlink != 0 {
|
||||
@@ -223,14 +223,14 @@ func (s *composeService) copyFromContainer(ctx context.Context, containerID, src
|
||||
}
|
||||
}
|
||||
|
||||
content, stat, err := s.apiClient.CopyFromContainer(ctx, containerID, srcPath)
|
||||
content, stat, err := s.apiClient().CopyFromContainer(ctx, containerID, srcPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer content.Close() //nolint:errcheck
|
||||
|
||||
if dstPath == "-" {
|
||||
_, err = io.Copy(os.Stdout, content)
|
||||
_, err = io.Copy(s.stdout(), content)
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -255,7 +255,7 @@ func (s *composeService) getCreateOptions(ctx context.Context, p *types.Project,
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
proxyConfig := types.MappingWithEquals(s.configFile.ParseProxyConfig(s.apiClient.DaemonHost(), nil))
|
||||
proxyConfig := types.MappingWithEquals(s.configFile().ParseProxyConfig(s.apiClient().DaemonHost(), nil))
|
||||
env := proxyConfig.OverrideBy(service.Environment)
|
||||
|
||||
containerConfig := container.Config{
|
||||
@@ -500,6 +500,7 @@ func getDeployResources(s types.ServiceConfig) container.Resources {
|
||||
CPUShares: s.CPUShares,
|
||||
CPUPercent: int64(s.CPUS * 100),
|
||||
CpusetCpus: s.CPUSet,
|
||||
DeviceCgroupRules: s.DeviceCgroupRules,
|
||||
}
|
||||
|
||||
if s.PidsLimit != 0 {
|
||||
@@ -693,7 +694,7 @@ func (s *composeService) buildContainerVolumes(ctx context.Context, p types.Proj
|
||||
var mounts = []mount.Mount{}
|
||||
|
||||
image := getImageName(service, p.Name)
|
||||
imgInspect, _, err := s.apiClient.ImageInspectWithRaw(ctx, image)
|
||||
imgInspect, _, err := s.apiClient().ImageInspectWithRaw(ctx, image)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
@@ -1007,7 +1008,7 @@ func getAliases(s types.ServiceConfig, c *types.ServiceNetworkConfig) []string {
|
||||
}
|
||||
|
||||
func (s *composeService) ensureNetwork(ctx context.Context, n types.NetworkConfig) error {
|
||||
_, err := s.apiClient.NetworkInspect(ctx, n.Name, moby.NetworkInspectOptions{})
|
||||
_, err := s.apiClient().NetworkInspect(ctx, n.Name, moby.NetworkInspectOptions{})
|
||||
if err != nil {
|
||||
if errdefs.IsNotFound(err) {
|
||||
if n.External.External {
|
||||
@@ -1065,7 +1066,7 @@ func (s *composeService) ensureNetwork(ctx context.Context, n types.NetworkConfi
|
||||
networkEventName := fmt.Sprintf("Network %s", n.Name)
|
||||
w := progress.ContextWriter(ctx)
|
||||
w.Event(progress.CreatingEvent(networkEventName))
|
||||
if _, err := s.apiClient.NetworkCreate(ctx, n.Name, createOpts); err != nil {
|
||||
if _, err := s.apiClient().NetworkCreate(ctx, n.Name, createOpts); err != nil {
|
||||
w.Event(progress.ErrorEvent(networkEventName))
|
||||
return errors.Wrapf(err, "failed to create network %s", n.Name)
|
||||
}
|
||||
@@ -1082,7 +1083,7 @@ func (s *composeService) removeNetwork(ctx context.Context, networkID string, ne
|
||||
eventName := fmt.Sprintf("Network %s", networkName)
|
||||
w.Event(progress.RemovingEvent(eventName))
|
||||
|
||||
if err := s.apiClient.NetworkRemove(ctx, networkID); err != nil {
|
||||
if err := s.apiClient().NetworkRemove(ctx, networkID); err != nil {
|
||||
w.Event(progress.ErrorEvent(eventName))
|
||||
return errors.Wrapf(err, fmt.Sprintf("failed to remove network %s", networkID))
|
||||
}
|
||||
@@ -1092,7 +1093,7 @@ func (s *composeService) removeNetwork(ctx context.Context, networkID string, ne
|
||||
}
|
||||
|
||||
func (s *composeService) ensureVolume(ctx context.Context, volume types.VolumeConfig, project string) error {
|
||||
inspected, err := s.apiClient.VolumeInspect(ctx, volume.Name)
|
||||
inspected, err := s.apiClient().VolumeInspect(ctx, volume.Name)
|
||||
if err != nil {
|
||||
if !errdefs.IsNotFound(err) {
|
||||
return err
|
||||
@@ -1123,7 +1124,7 @@ func (s *composeService) createVolume(ctx context.Context, volume types.VolumeCo
|
||||
eventName := fmt.Sprintf("Volume %q", volume.Name)
|
||||
w := progress.ContextWriter(ctx)
|
||||
w.Event(progress.CreatingEvent(eventName))
|
||||
_, err := s.apiClient.VolumeCreate(ctx, volume_api.VolumeCreateBody{
|
||||
_, err := s.apiClient().VolumeCreate(ctx, volume_api.VolumeCreateBody{
|
||||
Labels: volume.Labels,
|
||||
Name: volume.Name,
|
||||
Driver: volume.Driver,
|
||||
|
||||
@@ -127,7 +127,7 @@ func (s *composeService) ensureImagesDown(ctx context.Context, projectName strin
|
||||
|
||||
func (s *composeService) ensureNetworksDown(ctx context.Context, projectName string) ([]downOp, error) {
|
||||
var ops []downOp
|
||||
networks, err := s.apiClient.NetworkList(ctx, moby.NetworkListOptions{Filters: filters.NewArgs(projectFilter(projectName))})
|
||||
networks, err := s.apiClient().NetworkList(ctx, moby.NetworkListOptions{Filters: filters.NewArgs(projectFilter(projectName))})
|
||||
if err != nil {
|
||||
return ops, err
|
||||
}
|
||||
@@ -159,7 +159,7 @@ func (s *composeService) getServiceImages(options api.DownOptions, projectName s
|
||||
func (s *composeService) removeImage(ctx context.Context, image string, w progress.Writer) error {
|
||||
id := fmt.Sprintf("Image %s", image)
|
||||
w.Event(progress.NewEvent(id, progress.Working, "Removing"))
|
||||
_, err := s.apiClient.ImageRemove(ctx, image, moby.ImageRemoveOptions{})
|
||||
_, err := s.apiClient().ImageRemove(ctx, image, moby.ImageRemoveOptions{})
|
||||
if err == nil {
|
||||
w.Event(progress.NewEvent(id, progress.Done, "Removed"))
|
||||
return nil
|
||||
@@ -174,7 +174,7 @@ func (s *composeService) removeImage(ctx context.Context, image string, w progre
|
||||
func (s *composeService) removeVolume(ctx context.Context, id string, w progress.Writer) error {
|
||||
resource := fmt.Sprintf("Volume %s", id)
|
||||
w.Event(progress.NewEvent(resource, progress.Working, "Removing"))
|
||||
err := s.apiClient.VolumeRemove(ctx, id, true)
|
||||
err := s.apiClient().VolumeRemove(ctx, id, true)
|
||||
if err == nil {
|
||||
w.Event(progress.NewEvent(resource, progress.Done, "Removed"))
|
||||
return nil
|
||||
@@ -193,7 +193,7 @@ func (s *composeService) stopContainers(ctx context.Context, w progress.Writer,
|
||||
eg.Go(func() error {
|
||||
eventName := getContainerProgressName(container)
|
||||
w.Event(progress.StoppingEvent(eventName))
|
||||
err := s.apiClient.ContainerStop(ctx, container.ID, timeout)
|
||||
err := s.apiClient().ContainerStop(ctx, container.ID, timeout)
|
||||
if err != nil {
|
||||
w.Event(progress.ErrorMessageEvent(eventName, "Error while Stopping"))
|
||||
return err
|
||||
@@ -218,7 +218,7 @@ func (s *composeService) removeContainers(ctx context.Context, w progress.Writer
|
||||
return err
|
||||
}
|
||||
w.Event(progress.RemovingEvent(eventName))
|
||||
err = s.apiClient.ContainerRemove(ctx, container.ID, moby.ContainerRemoveOptions{
|
||||
err = s.apiClient().ContainerRemove(ctx, container.ID, moby.ContainerRemoveOptions{
|
||||
Force: true,
|
||||
RemoveVolumes: volumes,
|
||||
})
|
||||
@@ -236,7 +236,7 @@ func (s *composeService) removeContainers(ctx context.Context, w progress.Writer
|
||||
func (s *composeService) getProjectWithVolumes(ctx context.Context, containers Containers, projectName string) (*types.Project, error) {
|
||||
containers = containers.filter(isNotOneOff)
|
||||
project, _ := s.projectFromName(containers, projectName)
|
||||
volumes, err := s.apiClient.VolumeList(ctx, filters.NewArgs(projectFilter(projectName)))
|
||||
volumes, err := s.apiClient().VolumeList(ctx, filters.NewArgs(projectFilter(projectName)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -34,8 +34,11 @@ import (
|
||||
func TestDown(t *testing.T) {
|
||||
mockCtrl := gomock.NewController(t)
|
||||
defer mockCtrl.Finish()
|
||||
|
||||
api := mocks.NewMockAPIClient(mockCtrl)
|
||||
tested.apiClient = api
|
||||
cli := mocks.NewMockCli(mockCtrl)
|
||||
tested.dockerCli = cli
|
||||
cli.EXPECT().Client().Return(api).AnyTimes()
|
||||
|
||||
api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt()).Return(
|
||||
[]moby.Container{
|
||||
@@ -67,8 +70,11 @@ func TestDown(t *testing.T) {
|
||||
func TestDownRemoveOrphans(t *testing.T) {
|
||||
mockCtrl := gomock.NewController(t)
|
||||
defer mockCtrl.Finish()
|
||||
|
||||
api := mocks.NewMockAPIClient(mockCtrl)
|
||||
tested.apiClient = api
|
||||
cli := mocks.NewMockCli(mockCtrl)
|
||||
tested.dockerCli = cli
|
||||
cli.EXPECT().Client().Return(api).AnyTimes()
|
||||
|
||||
api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt()).Return(
|
||||
[]moby.Container{
|
||||
@@ -99,8 +105,11 @@ func TestDownRemoveOrphans(t *testing.T) {
|
||||
func TestDownRemoveVolumes(t *testing.T) {
|
||||
mockCtrl := gomock.NewController(t)
|
||||
defer mockCtrl.Finish()
|
||||
|
||||
api := mocks.NewMockAPIClient(mockCtrl)
|
||||
tested.apiClient = api
|
||||
cli := mocks.NewMockCli(mockCtrl)
|
||||
tested.dockerCli = cli
|
||||
cli.EXPECT().Client().Return(api).AnyTimes()
|
||||
|
||||
api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt()).Return(
|
||||
[]moby.Container{testContainer("service1", "123", false)}, nil)
|
||||
|
||||
@@ -30,7 +30,7 @@ import (
|
||||
)
|
||||
|
||||
func (s *composeService) Events(ctx context.Context, project string, options api.EventsOptions) error {
|
||||
events, errors := s.apiClient.Events(ctx, moby.EventsOptions{
|
||||
events, errors := s.apiClient().Events(ctx, moby.EventsOptions{
|
||||
Filters: filters.NewArgs(projectFilter(project)),
|
||||
})
|
||||
for {
|
||||
|
||||
@@ -21,7 +21,6 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/docker/cli/cli/streams"
|
||||
moby "github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/pkg/stdcopy"
|
||||
@@ -36,7 +35,7 @@ func (s *composeService) Exec(ctx context.Context, project string, opts api.RunO
|
||||
return 0, err
|
||||
}
|
||||
|
||||
exec, err := s.apiClient.ContainerExecCreate(ctx, container.ID, moby.ExecConfig{
|
||||
exec, err := s.apiClient().ContainerExecCreate(ctx, container.ID, moby.ExecConfig{
|
||||
Cmd: opts.Command,
|
||||
Env: opts.Environment,
|
||||
User: opts.User,
|
||||
@@ -54,13 +53,13 @@ func (s *composeService) Exec(ctx context.Context, project string, opts api.RunO
|
||||
}
|
||||
|
||||
if opts.Detach {
|
||||
return 0, s.apiClient.ContainerExecStart(ctx, exec.ID, moby.ExecStartCheck{
|
||||
return 0, s.apiClient().ContainerExecStart(ctx, exec.ID, moby.ExecStartCheck{
|
||||
Detach: true,
|
||||
Tty: opts.Tty,
|
||||
})
|
||||
}
|
||||
|
||||
resp, err := s.apiClient.ContainerExecAttach(ctx, exec.ID, moby.ExecStartCheck{
|
||||
resp, err := s.apiClient().ContainerExecAttach(ctx, exec.ID, moby.ExecStartCheck{
|
||||
Tty: opts.Tty,
|
||||
})
|
||||
if err != nil {
|
||||
@@ -69,7 +68,7 @@ func (s *composeService) Exec(ctx context.Context, project string, opts api.RunO
|
||||
defer resp.Close() //nolint:errcheck
|
||||
|
||||
if opts.Tty {
|
||||
s.monitorTTySize(ctx, exec.ID, s.apiClient.ContainerExecResize)
|
||||
s.monitorTTySize(ctx, exec.ID, s.apiClient().ContainerExecResize)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -90,12 +89,12 @@ func (s *composeService) interactiveExec(ctx context.Context, opts api.RunOption
|
||||
|
||||
stdout := ContainerStdout{HijackedResponse: resp}
|
||||
stdin := ContainerStdin{HijackedResponse: resp}
|
||||
r, err := s.getEscapeKeyProxy(opts.Stdin, opts.Tty)
|
||||
r, err := s.getEscapeKeyProxy(s.stdin(), opts.Tty)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
in := streams.NewIn(opts.Stdin)
|
||||
in := s.stdin()
|
||||
if in.IsTerminal() && opts.Tty {
|
||||
state, err := term.SetRawTerminal(in.FD())
|
||||
if err != nil {
|
||||
@@ -106,10 +105,10 @@ func (s *composeService) interactiveExec(ctx context.Context, opts api.RunOption
|
||||
|
||||
go func() {
|
||||
if opts.Tty {
|
||||
_, err := io.Copy(opts.Stdout, stdout)
|
||||
_, err := io.Copy(s.stdout(), stdout)
|
||||
outputDone <- err
|
||||
} else {
|
||||
_, err := stdcopy.StdCopy(opts.Stdout, opts.Stderr, stdout)
|
||||
_, err := stdcopy.StdCopy(s.stdout(), s.stderr(), stdout)
|
||||
outputDone <- err
|
||||
}
|
||||
stdout.Close() //nolint:errcheck
|
||||
@@ -140,7 +139,7 @@ func (s *composeService) interactiveExec(ctx context.Context, opts api.RunOption
|
||||
}
|
||||
|
||||
func (s *composeService) getExecTarget(ctx context.Context, projectName string, opts api.RunOptions) (moby.Container, error) {
|
||||
containers, err := s.apiClient.ContainerList(ctx, moby.ContainerListOptions{
|
||||
containers, err := s.apiClient().ContainerList(ctx, moby.ContainerListOptions{
|
||||
Filters: filters.NewArgs(
|
||||
projectFilter(projectName),
|
||||
serviceFilter(opts.Service),
|
||||
@@ -158,7 +157,7 @@ func (s *composeService) getExecTarget(ctx context.Context, projectName string,
|
||||
}
|
||||
|
||||
func (s *composeService) getExecExitStatus(ctx context.Context, execID string) (int, error) {
|
||||
resp, err := s.apiClient.ContainerExecInspect(ctx, execID)
|
||||
resp, err := s.apiClient().ContainerExecInspect(ctx, execID)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ import (
|
||||
)
|
||||
|
||||
func (s *composeService) Images(ctx context.Context, projectName string, options api.ImagesOptions) ([]api.ImageSummary, error) {
|
||||
allContainers, err := s.apiClient.ContainerList(ctx, moby.ContainerListOptions{
|
||||
allContainers, err := s.apiClient().ContainerList(ctx, moby.ContainerListOptions{
|
||||
All: true,
|
||||
Filters: filters.NewArgs(projectFilter(projectName)),
|
||||
})
|
||||
@@ -83,7 +83,7 @@ func (s *composeService) getImages(ctx context.Context, images []string) (map[st
|
||||
for _, img := range images {
|
||||
img := img
|
||||
eg.Go(func() error {
|
||||
inspect, _, err := s.apiClient.ImageInspectWithRaw(ctx, img)
|
||||
inspect, _, err := s.apiClient().ImageInspectWithRaw(ctx, img)
|
||||
if err != nil {
|
||||
if errdefs.IsNotFound(err) {
|
||||
return nil
|
||||
|
||||
@@ -54,7 +54,7 @@ func (s *composeService) kill(ctx context.Context, project *types.Project, optio
|
||||
eg.Go(func() error {
|
||||
eventName := getContainerProgressName(container)
|
||||
w.Event(progress.KillingEvent(eventName))
|
||||
err := s.apiClient.ContainerKill(ctx, container.ID, options.Signal)
|
||||
err := s.apiClient().ContainerKill(ctx, container.ID, options.Signal)
|
||||
if err != nil {
|
||||
w.Event(progress.ErrorMessageEvent(eventName, "Error while Killing"))
|
||||
return err
|
||||
|
||||
@@ -39,8 +39,11 @@ var tested = composeService{}
|
||||
func TestKillAll(t *testing.T) {
|
||||
mockCtrl := gomock.NewController(t)
|
||||
defer mockCtrl.Finish()
|
||||
|
||||
api := mocks.NewMockAPIClient(mockCtrl)
|
||||
tested.apiClient = api
|
||||
cli := mocks.NewMockCli(mockCtrl)
|
||||
tested.dockerCli = cli
|
||||
cli.EXPECT().Client().Return(api).AnyTimes()
|
||||
|
||||
project := types.Project{Name: strings.ToLower(testProject), Services: []types.ServiceConfig{testService("service1"), testService("service2")}}
|
||||
|
||||
@@ -61,8 +64,11 @@ func TestKillSignal(t *testing.T) {
|
||||
const serviceName = "service1"
|
||||
mockCtrl := gomock.NewController(t)
|
||||
defer mockCtrl.Finish()
|
||||
|
||||
api := mocks.NewMockAPIClient(mockCtrl)
|
||||
tested.apiClient = api
|
||||
cli := mocks.NewMockCli(mockCtrl)
|
||||
tested.dockerCli = cli
|
||||
cli.EXPECT().Client().Return(api).AnyTimes()
|
||||
|
||||
project := types.Project{Name: strings.ToLower(testProject), Services: []types.ServiceConfig{testService(serviceName)}}
|
||||
listOptions := moby.ContainerListOptions{
|
||||
|
||||
@@ -75,13 +75,13 @@ func (s *composeService) Logs(ctx context.Context, projectName string, consumer
|
||||
}
|
||||
|
||||
func (s *composeService) logContainers(ctx context.Context, consumer api.LogConsumer, c types.Container, options api.LogOptions) error {
|
||||
cnt, err := s.apiClient.ContainerInspect(ctx, c.ID)
|
||||
cnt, err := s.apiClient().ContainerInspect(ctx, c.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
service := c.Labels[api.ServiceLabel]
|
||||
r, err := s.apiClient.ContainerLogs(ctx, cnt.ID, types.ContainerLogsOptions{
|
||||
r, err := s.apiClient().ContainerLogs(ctx, cnt.ID, types.ContainerLogsOptions{
|
||||
ShowStdout: true,
|
||||
ShowStderr: true,
|
||||
Follow: options.Follow,
|
||||
|
||||
@@ -30,7 +30,7 @@ import (
|
||||
)
|
||||
|
||||
func (s *composeService) List(ctx context.Context, opts api.ListOptions) ([]api.Stack, error) {
|
||||
list, err := s.apiClient.ContainerList(ctx, moby.ContainerListOptions{
|
||||
list, err := s.apiClient().ContainerList(ctx, moby.ContainerListOptions{
|
||||
Filters: filters.NewArgs(hasProjectLabelFilter()),
|
||||
All: opts.All,
|
||||
})
|
||||
|
||||
@@ -42,7 +42,7 @@ func (s *composeService) pause(ctx context.Context, project string, options api.
|
||||
eg, ctx := errgroup.WithContext(ctx)
|
||||
containers.forEach(func(container moby.Container) {
|
||||
eg.Go(func() error {
|
||||
err := s.apiClient.ContainerPause(ctx, container.ID)
|
||||
err := s.apiClient().ContainerPause(ctx, container.ID)
|
||||
if err == nil {
|
||||
eventName := getContainerProgressName(container)
|
||||
w.Event(progress.NewEvent(eventName, progress.Done, "Paused"))
|
||||
@@ -70,7 +70,7 @@ func (s *composeService) unPause(ctx context.Context, project string, options ap
|
||||
eg, ctx := errgroup.WithContext(ctx)
|
||||
containers.forEach(func(container moby.Container) {
|
||||
eg.Go(func() error {
|
||||
err = s.apiClient.ContainerUnpause(ctx, container.ID)
|
||||
err = s.apiClient().ContainerUnpause(ctx, container.ID)
|
||||
if err == nil {
|
||||
eventName := getContainerProgressName(container)
|
||||
w.Event(progress.NewEvent(eventName, progress.Done, "Unpaused"))
|
||||
|
||||
@@ -27,7 +27,7 @@ import (
|
||||
)
|
||||
|
||||
func (s *composeService) Port(ctx context.Context, project string, service string, port int, options api.PortOptions) (string, int, error) {
|
||||
list, err := s.apiClient.ContainerList(ctx, moby.ContainerListOptions{
|
||||
list, err := s.apiClient().ContainerList(ctx, moby.ContainerListOptions{
|
||||
Filters: filters.NewArgs(
|
||||
projectFilter(project),
|
||||
serviceFilter(service),
|
||||
|
||||
@@ -53,7 +53,7 @@ func (s *composeService) Ps(ctx context.Context, projectName string, options api
|
||||
})
|
||||
}
|
||||
|
||||
inspect, err := s.apiClient.ContainerInspect(ctx, container.ID)
|
||||
inspect, err := s.apiClient().ContainerInspect(ctx, container.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -34,8 +34,11 @@ import (
|
||||
func TestPs(t *testing.T) {
|
||||
mockCtrl := gomock.NewController(t)
|
||||
defer mockCtrl.Finish()
|
||||
|
||||
api := mocks.NewMockAPIClient(mockCtrl)
|
||||
tested.apiClient = api
|
||||
cli := mocks.NewMockCli(mockCtrl)
|
||||
tested.dockerCli = cli
|
||||
cli.EXPECT().Client().Return(api).AnyTimes()
|
||||
|
||||
ctx := context.Background()
|
||||
args := filters.NewArgs(projectFilter(strings.ToLower(testProject)))
|
||||
|
||||
@@ -46,7 +46,7 @@ func (s *composeService) Pull(ctx context.Context, project *types.Project, opts
|
||||
}
|
||||
|
||||
func (s *composeService) pull(ctx context.Context, project *types.Project, opts api.PullOptions) error {
|
||||
info, err := s.apiClient.Info(ctx)
|
||||
info, err := s.apiClient().Info(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -70,7 +70,7 @@ func (s *composeService) pull(ctx context.Context, project *types.Project, opts
|
||||
continue
|
||||
}
|
||||
eg.Go(func() error {
|
||||
err := s.pullServiceImage(ctx, service, info, s.configFile, w, false)
|
||||
err := s.pullServiceImage(ctx, service, info, s.configFile(), w, false)
|
||||
if err != nil {
|
||||
if !opts.IgnoreFailures {
|
||||
if service.Build != nil {
|
||||
@@ -124,7 +124,7 @@ func (s *composeService) pullServiceImage(ctx context.Context, service types.Ser
|
||||
return err
|
||||
}
|
||||
|
||||
stream, err := s.apiClient.ImagePull(ctx, service.Image, moby.ImagePullOptions{
|
||||
stream, err := s.apiClient().ImagePull(ctx, service.Image, moby.ImagePullOptions{
|
||||
RegistryAuth: base64.URLEncoding.EncodeToString(buf),
|
||||
Platform: service.Platform,
|
||||
})
|
||||
@@ -162,7 +162,7 @@ func (s *composeService) pullServiceImage(ctx context.Context, service types.Ser
|
||||
}
|
||||
|
||||
func (s *composeService) pullRequiredImages(ctx context.Context, project *types.Project, images map[string]string, quietPull bool) error {
|
||||
info, err := s.apiClient.Info(ctx)
|
||||
info, err := s.apiClient().Info(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -198,7 +198,7 @@ func (s *composeService) pullRequiredImages(ctx context.Context, project *types.
|
||||
for _, service := range needPull {
|
||||
service := service
|
||||
eg.Go(func() error {
|
||||
err := s.pullServiceImage(ctx, service, info, s.configFile, w, quietPull)
|
||||
err := s.pullServiceImage(ctx, service, info, s.configFile(), w, quietPull)
|
||||
if err != nil && service.Build != nil {
|
||||
// image can be built, so we can ignore pull failure
|
||||
return nil
|
||||
|
||||
@@ -45,7 +45,7 @@ func (s *composeService) Push(ctx context.Context, project *types.Project, optio
|
||||
func (s *composeService) push(ctx context.Context, project *types.Project, options api.PushOptions) error {
|
||||
eg, ctx := errgroup.WithContext(ctx)
|
||||
|
||||
info, err := s.apiClient.Info(ctx)
|
||||
info, err := s.apiClient().Info(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -65,7 +65,7 @@ func (s *composeService) push(ctx context.Context, project *types.Project, optio
|
||||
}
|
||||
service := service
|
||||
eg.Go(func() error {
|
||||
err := s.pushServiceImage(ctx, service, info, s.configFile, w)
|
||||
err := s.pushServiceImage(ctx, service, info, s.configFile(), w)
|
||||
if err != nil {
|
||||
if !options.IgnoreFailures {
|
||||
return err
|
||||
@@ -103,7 +103,7 @@ func (s *composeService) pushServiceImage(ctx context.Context, service types.Ser
|
||||
return err
|
||||
}
|
||||
|
||||
stream, err := s.apiClient.ImagePush(ctx, service.Image, moby.ImagePushOptions{
|
||||
stream, err := s.apiClient().ImagePush(ctx, service.Image, moby.ImagePushOptions{
|
||||
RegistryAuth: base64.URLEncoding.EncodeToString(buf),
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@@ -21,7 +21,6 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/docker/compose/v2/pkg/api"
|
||||
moby "github.com/docker/docker/api/types"
|
||||
"golang.org/x/sync/errgroup"
|
||||
@@ -30,13 +29,8 @@ import (
|
||||
"github.com/docker/compose/v2/pkg/prompt"
|
||||
)
|
||||
|
||||
func (s *composeService) Remove(ctx context.Context, project *types.Project, options api.RemoveOptions) error {
|
||||
services := options.Services
|
||||
if len(services) == 0 {
|
||||
services = project.ServiceNames()
|
||||
}
|
||||
|
||||
containers, err := s.getContainers(ctx, project.Name, oneOffInclude, true, services...)
|
||||
func (s *composeService) Remove(ctx context.Context, projectName string, options api.RemoveOptions) error {
|
||||
containers, _, err := s.actualState(ctx, projectName, options.Services)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -79,7 +73,7 @@ func (s *composeService) remove(ctx context.Context, containers Containers, opti
|
||||
eg.Go(func() error {
|
||||
eventName := getContainerProgressName(container)
|
||||
w.Event(progress.RemovingEvent(eventName))
|
||||
err := s.apiClient.ContainerRemove(ctx, container.ID, moby.ContainerRemoveOptions{
|
||||
err := s.apiClient().ContainerRemove(ctx, container.ID, moby.ContainerRemoveOptions{
|
||||
RemoveVolumes: options.Volumes,
|
||||
Force: options.Force,
|
||||
})
|
||||
|
||||
@@ -59,7 +59,7 @@ func (s *composeService) restart(ctx context.Context, projectName string, option
|
||||
eg.Go(func() error {
|
||||
eventName := getContainerProgressName(container)
|
||||
w.Event(progress.RestartingEvent(eventName))
|
||||
err := s.apiClient.ContainerRestart(ctx, container.ID, options.Timeout)
|
||||
err := s.apiClient().ContainerRestart(ctx, container.ID, options.Timeout)
|
||||
if err == nil {
|
||||
w.Event(progress.StartedEvent(eventName))
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ import (
|
||||
"io"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/docker/cli/cli/streams"
|
||||
"github.com/docker/compose/v2/pkg/api"
|
||||
moby "github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
@@ -39,11 +38,11 @@ func (s *composeService) RunOneOffContainer(ctx context.Context, project *types.
|
||||
}
|
||||
|
||||
if opts.Detach {
|
||||
err := s.apiClient.ContainerStart(ctx, containerID, moby.ContainerStartOptions{})
|
||||
err := s.apiClient().ContainerStart(ctx, containerID, moby.ContainerStartOptions{})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
fmt.Fprintln(opts.Stdout, containerID)
|
||||
fmt.Fprintln(s.stdout(), containerID)
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
@@ -51,7 +50,8 @@ func (s *composeService) RunOneOffContainer(ctx context.Context, project *types.
|
||||
}
|
||||
|
||||
func (s *composeService) runInteractive(ctx context.Context, containerID string, opts api.RunOptions) (int, error) {
|
||||
r, err := s.getEscapeKeyProxy(opts.Stdin, opts.Tty)
|
||||
in := s.stdin()
|
||||
r, err := s.getEscapeKeyProxy(in, opts.Tty)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -61,7 +61,6 @@ func (s *composeService) runInteractive(ctx context.Context, containerID string,
|
||||
return 0, err
|
||||
}
|
||||
|
||||
in := streams.NewIn(opts.Stdin)
|
||||
if in.IsTerminal() && opts.Tty {
|
||||
state, err := term.SetRawTerminal(in.FD())
|
||||
if err != nil {
|
||||
@@ -75,10 +74,10 @@ func (s *composeService) runInteractive(ctx context.Context, containerID string,
|
||||
|
||||
go func() {
|
||||
if opts.Tty {
|
||||
_, err := io.Copy(opts.Stdout, stdout) //nolint:errcheck
|
||||
_, err := io.Copy(s.stdout(), stdout) //nolint:errcheck
|
||||
outputDone <- err
|
||||
} else {
|
||||
_, err := stdcopy.StdCopy(opts.Stdout, opts.Stderr, stdout) //nolint:errcheck
|
||||
_, err := stdcopy.StdCopy(s.stdout(), s.stderr(), stdout) //nolint:errcheck
|
||||
outputDone <- err
|
||||
}
|
||||
stdout.Close() //nolint:errcheck
|
||||
@@ -90,12 +89,12 @@ func (s *composeService) runInteractive(ctx context.Context, containerID string,
|
||||
stdin.Close() //nolint:errcheck
|
||||
}()
|
||||
|
||||
err = s.apiClient.ContainerStart(ctx, containerID, moby.ContainerStartOptions{})
|
||||
err = s.apiClient().ContainerStart(ctx, containerID, moby.ContainerStartOptions{})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
s.monitorTTySize(ctx, containerID, s.apiClient.ContainerResize)
|
||||
s.monitorTTySize(ctx, containerID, s.apiClient().ContainerResize)
|
||||
|
||||
for {
|
||||
select {
|
||||
@@ -119,7 +118,7 @@ func (s *composeService) runInteractive(ctx context.Context, containerID string,
|
||||
}
|
||||
|
||||
func (s *composeService) terminateRun(ctx context.Context, containerID string, opts api.RunOptions) (exitCode int, err error) {
|
||||
exitCh, errCh := s.apiClient.ContainerWait(ctx, containerID, container.WaitConditionNotRunning)
|
||||
exitCh, errCh := s.apiClient().ContainerWait(ctx, containerID, container.WaitConditionNotRunning)
|
||||
select {
|
||||
case exit := <-exitCh:
|
||||
exitCode = int(exit.StatusCode)
|
||||
@@ -127,7 +126,7 @@ func (s *composeService) terminateRun(ctx context.Context, containerID string, o
|
||||
return
|
||||
}
|
||||
if opts.AutoRemove {
|
||||
err = s.apiClient.ContainerRemove(ctx, containerID, moby.ContainerRemoveOptions{})
|
||||
err = s.apiClient().ContainerRemove(ctx, containerID, moby.ContainerRemoveOptions{})
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -185,8 +184,8 @@ func (s *composeService) getEscapeKeyProxy(r io.ReadCloser, isTty bool) (io.Read
|
||||
return r, nil
|
||||
}
|
||||
var escapeKeys = []byte{16, 17}
|
||||
if s.configFile.DetachKeys != "" {
|
||||
customEscapeKeys, err := term.ToBytes(s.configFile.DetachKeys)
|
||||
if s.configFile().DetachKeys != "" {
|
||||
customEscapeKeys, err := term.ToBytes(s.configFile().DetachKeys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ func (s *composeService) watchContainers(ctx context.Context, projectName string
|
||||
return nil
|
||||
}
|
||||
|
||||
inspected, err := s.apiClient.ContainerInspect(ctx, event.Container)
|
||||
inspected, err := s.apiClient().ContainerInspect(ctx, event.Container)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -32,26 +32,11 @@ func (s *composeService) Stop(ctx context.Context, projectName string, options a
|
||||
func (s *composeService) stop(ctx context.Context, projectName string, options api.StopOptions) error {
|
||||
w := progress.ContextWriter(ctx)
|
||||
|
||||
services := options.Services
|
||||
if len(services) == 0 {
|
||||
services = []string{}
|
||||
}
|
||||
|
||||
var containers Containers
|
||||
containers, err := s.getContainers(ctx, projectName, oneOffInclude, true, services...)
|
||||
containers, project, err := s.actualState(ctx, projectName, options.Services)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
project, err := s.projectFromName(containers, projectName, services...)
|
||||
if err != nil && !api.IsNotFoundError(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(services) > 0 {
|
||||
containers = containers.filter(isService(services...))
|
||||
}
|
||||
|
||||
return InReverseDependencyOrder(ctx, project, func(c context.Context, service string) error {
|
||||
return s.stopContainers(ctx, w, containers.filter(isService(service)), options.Timeout)
|
||||
})
|
||||
|
||||
@@ -33,8 +33,11 @@ import (
|
||||
func TestStopTimeout(t *testing.T) {
|
||||
mockCtrl := gomock.NewController(t)
|
||||
defer mockCtrl.Finish()
|
||||
|
||||
api := mocks.NewMockAPIClient(mockCtrl)
|
||||
tested.apiClient = api
|
||||
cli := mocks.NewMockCli(mockCtrl)
|
||||
tested.dockerCli = cli
|
||||
cli.EXPECT().Client().Return(api).AnyTimes()
|
||||
|
||||
ctx := context.Background()
|
||||
api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt()).Return(
|
||||
|
||||
@@ -37,7 +37,7 @@ func (s *composeService) Top(ctx context.Context, projectName string, services [
|
||||
for i, container := range containers {
|
||||
i, container := i, container
|
||||
eg.Go(func() error {
|
||||
topContent, err := s.apiClient.ContainerTop(ctx, container.ID, []string{})
|
||||
topContent, err := s.apiClient().ContainerTop(ctx, container.ID, []string{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
8
pkg/e2e/fixtures/dependencies/compose.yaml
Normal file
8
pkg/e2e/fixtures/dependencies/compose.yaml
Normal file
@@ -0,0 +1,8 @@
|
||||
services:
|
||||
foo:
|
||||
image: nginx:alpine
|
||||
depends_on:
|
||||
- bar
|
||||
|
||||
bar:
|
||||
image: nginx:alpine
|
||||
@@ -95,3 +95,43 @@ func TestStartStop(t *testing.T) {
|
||||
_ = c.RunDockerComposeCmd("--project-name", projectName, "down")
|
||||
})
|
||||
}
|
||||
|
||||
func TestStartStopWithDependencies(t *testing.T) {
|
||||
c := NewParallelE2eCLI(t, binDir)
|
||||
const projectName = "e2e-start-stop-with-dependencies"
|
||||
|
||||
defer c.RunDockerComposeCmd("--project-name", projectName, "rm", "-fsv")
|
||||
|
||||
t.Run("Up", func(t *testing.T) {
|
||||
res := c.RunDockerComposeCmd("-f", "./fixtures/dependencies/compose.yaml", "--project-name", projectName, "up", "-d")
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-with-dependencies-foo-1 Started"), res.Combined())
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-with-dependencies-bar-1 Started"), res.Combined())
|
||||
})
|
||||
|
||||
t.Run("stop foo", func(t *testing.T) {
|
||||
res := c.RunDockerComposeCmd("--project-name", projectName, "stop", "foo")
|
||||
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-with-dependencies-foo-1 Stopped"), res.Combined())
|
||||
|
||||
res = c.RunDockerComposeCmd("--project-name", projectName, "ps", "--status", "running")
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "e2e-start-stop-with-dependencies-bar-1"), res.Combined())
|
||||
assert.Assert(t, !strings.Contains(res.Combined(), "e2e-start-stop-with-dependencies-foo-1"), res.Combined())
|
||||
})
|
||||
|
||||
t.Run("start foo", func(t *testing.T) {
|
||||
res := c.RunDockerComposeCmd("--project-name", projectName, "stop")
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-with-dependencies-bar-1 Stopped"), res.Combined())
|
||||
|
||||
res = c.RunDockerComposeCmd("--project-name", projectName, "start", "foo")
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-with-dependencies-bar-1 Started"), res.Combined())
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-with-dependencies-foo-1 Started"), res.Combined())
|
||||
|
||||
res = c.RunDockerComposeCmd("--project-name", projectName, "ps", "--status", "running")
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "e2e-start-stop-with-dependencies-bar-1"), res.Combined())
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "e2e-start-stop-with-dependencies-foo-1"), res.Combined())
|
||||
})
|
||||
|
||||
t.Run("down", func(t *testing.T) {
|
||||
_ = c.RunDockerComposeCmd("--project-name", projectName, "down")
|
||||
})
|
||||
}
|
||||
|
||||
301
pkg/mocks/mock_docker_cli.go
Normal file
301
pkg/mocks/mock_docker_cli.go
Normal file
@@ -0,0 +1,301 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: github.com/docker/cli/cli/command (interfaces: Cli)
|
||||
|
||||
// Package mocks is a generated GoMock package.
|
||||
package mocks
|
||||
|
||||
import (
|
||||
io "io"
|
||||
reflect "reflect"
|
||||
|
||||
command "github.com/docker/cli/cli/command"
|
||||
configfile "github.com/docker/cli/cli/config/configfile"
|
||||
docker "github.com/docker/cli/cli/context/docker"
|
||||
store "github.com/docker/cli/cli/context/store"
|
||||
store0 "github.com/docker/cli/cli/manifest/store"
|
||||
client "github.com/docker/cli/cli/registry/client"
|
||||
streams "github.com/docker/cli/cli/streams"
|
||||
trust "github.com/docker/cli/cli/trust"
|
||||
client0 "github.com/docker/docker/client"
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
client1 "github.com/theupdateframework/notary/client"
|
||||
)
|
||||
|
||||
// MockCli is a mock of Cli interface.
|
||||
type MockCli struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockCliMockRecorder
|
||||
}
|
||||
|
||||
// MockCliMockRecorder is the mock recorder for MockCli.
|
||||
type MockCliMockRecorder struct {
|
||||
mock *MockCli
|
||||
}
|
||||
|
||||
// NewMockCli creates a new mock instance.
|
||||
func NewMockCli(ctrl *gomock.Controller) *MockCli {
|
||||
mock := &MockCli{ctrl: ctrl}
|
||||
mock.recorder = &MockCliMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockCli) EXPECT() *MockCliMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// Apply mocks base method.
|
||||
func (m *MockCli) Apply(arg0 ...command.DockerCliOption) error {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []interface{}{}
|
||||
for _, a := range arg0 {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "Apply", varargs...)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Apply indicates an expected call of Apply.
|
||||
func (mr *MockCliMockRecorder) Apply(arg0 ...interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Apply", reflect.TypeOf((*MockCli)(nil).Apply), arg0...)
|
||||
}
|
||||
|
||||
// Client mocks base method.
|
||||
func (m *MockCli) Client() client0.APIClient {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Client")
|
||||
ret0, _ := ret[0].(client0.APIClient)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Client indicates an expected call of Client.
|
||||
func (mr *MockCliMockRecorder) Client() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Client", reflect.TypeOf((*MockCli)(nil).Client))
|
||||
}
|
||||
|
||||
// ClientInfo mocks base method.
|
||||
func (m *MockCli) ClientInfo() command.ClientInfo {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ClientInfo")
|
||||
ret0, _ := ret[0].(command.ClientInfo)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// ClientInfo indicates an expected call of ClientInfo.
|
||||
func (mr *MockCliMockRecorder) ClientInfo() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClientInfo", reflect.TypeOf((*MockCli)(nil).ClientInfo))
|
||||
}
|
||||
|
||||
// ConfigFile mocks base method.
|
||||
func (m *MockCli) ConfigFile() *configfile.ConfigFile {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ConfigFile")
|
||||
ret0, _ := ret[0].(*configfile.ConfigFile)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// ConfigFile indicates an expected call of ConfigFile.
|
||||
func (mr *MockCliMockRecorder) ConfigFile() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ConfigFile", reflect.TypeOf((*MockCli)(nil).ConfigFile))
|
||||
}
|
||||
|
||||
// ContentTrustEnabled mocks base method.
|
||||
func (m *MockCli) ContentTrustEnabled() bool {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ContentTrustEnabled")
|
||||
ret0, _ := ret[0].(bool)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// ContentTrustEnabled indicates an expected call of ContentTrustEnabled.
|
||||
func (mr *MockCliMockRecorder) ContentTrustEnabled() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ContentTrustEnabled", reflect.TypeOf((*MockCli)(nil).ContentTrustEnabled))
|
||||
}
|
||||
|
||||
// ContextStore mocks base method.
|
||||
func (m *MockCli) ContextStore() store.Store {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ContextStore")
|
||||
ret0, _ := ret[0].(store.Store)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// ContextStore indicates an expected call of ContextStore.
|
||||
func (mr *MockCliMockRecorder) ContextStore() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ContextStore", reflect.TypeOf((*MockCli)(nil).ContextStore))
|
||||
}
|
||||
|
||||
// CurrentContext mocks base method.
|
||||
func (m *MockCli) CurrentContext() string {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "CurrentContext")
|
||||
ret0, _ := ret[0].(string)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// CurrentContext indicates an expected call of CurrentContext.
|
||||
func (mr *MockCliMockRecorder) CurrentContext() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CurrentContext", reflect.TypeOf((*MockCli)(nil).CurrentContext))
|
||||
}
|
||||
|
||||
// DefaultVersion mocks base method.
|
||||
func (m *MockCli) DefaultVersion() string {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "DefaultVersion")
|
||||
ret0, _ := ret[0].(string)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// DefaultVersion indicates an expected call of DefaultVersion.
|
||||
func (mr *MockCliMockRecorder) DefaultVersion() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DefaultVersion", reflect.TypeOf((*MockCli)(nil).DefaultVersion))
|
||||
}
|
||||
|
||||
// DockerEndpoint mocks base method.
|
||||
func (m *MockCli) DockerEndpoint() docker.Endpoint {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "DockerEndpoint")
|
||||
ret0, _ := ret[0].(docker.Endpoint)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// DockerEndpoint indicates an expected call of DockerEndpoint.
|
||||
func (mr *MockCliMockRecorder) DockerEndpoint() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DockerEndpoint", reflect.TypeOf((*MockCli)(nil).DockerEndpoint))
|
||||
}
|
||||
|
||||
// Err mocks base method.
|
||||
func (m *MockCli) Err() io.Writer {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Err")
|
||||
ret0, _ := ret[0].(io.Writer)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Err indicates an expected call of Err.
|
||||
func (mr *MockCliMockRecorder) Err() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Err", reflect.TypeOf((*MockCli)(nil).Err))
|
||||
}
|
||||
|
||||
// In mocks base method.
|
||||
func (m *MockCli) In() *streams.In {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "In")
|
||||
ret0, _ := ret[0].(*streams.In)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// In indicates an expected call of In.
|
||||
func (mr *MockCliMockRecorder) In() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "In", reflect.TypeOf((*MockCli)(nil).In))
|
||||
}
|
||||
|
||||
// ManifestStore mocks base method.
|
||||
func (m *MockCli) ManifestStore() store0.Store {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ManifestStore")
|
||||
ret0, _ := ret[0].(store0.Store)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// ManifestStore indicates an expected call of ManifestStore.
|
||||
func (mr *MockCliMockRecorder) ManifestStore() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ManifestStore", reflect.TypeOf((*MockCli)(nil).ManifestStore))
|
||||
}
|
||||
|
||||
// NotaryClient mocks base method.
|
||||
func (m *MockCli) NotaryClient(arg0 trust.ImageRefAndAuth, arg1 []string) (client1.Repository, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "NotaryClient", arg0, arg1)
|
||||
ret0, _ := ret[0].(client1.Repository)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// NotaryClient indicates an expected call of NotaryClient.
|
||||
func (mr *MockCliMockRecorder) NotaryClient(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NotaryClient", reflect.TypeOf((*MockCli)(nil).NotaryClient), arg0, arg1)
|
||||
}
|
||||
|
||||
// Out mocks base method.
|
||||
func (m *MockCli) Out() *streams.Out {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Out")
|
||||
ret0, _ := ret[0].(*streams.Out)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Out indicates an expected call of Out.
|
||||
func (mr *MockCliMockRecorder) Out() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Out", reflect.TypeOf((*MockCli)(nil).Out))
|
||||
}
|
||||
|
||||
// RegistryClient mocks base method.
|
||||
func (m *MockCli) RegistryClient(arg0 bool) client.RegistryClient {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "RegistryClient", arg0)
|
||||
ret0, _ := ret[0].(client.RegistryClient)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// RegistryClient indicates an expected call of RegistryClient.
|
||||
func (mr *MockCliMockRecorder) RegistryClient(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegistryClient", reflect.TypeOf((*MockCli)(nil).RegistryClient), arg0)
|
||||
}
|
||||
|
||||
// ServerInfo mocks base method.
|
||||
func (m *MockCli) ServerInfo() command.ServerInfo {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ServerInfo")
|
||||
ret0, _ := ret[0].(command.ServerInfo)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// ServerInfo indicates an expected call of ServerInfo.
|
||||
func (mr *MockCliMockRecorder) ServerInfo() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ServerInfo", reflect.TypeOf((*MockCli)(nil).ServerInfo))
|
||||
}
|
||||
|
||||
// SetIn mocks base method.
|
||||
func (m *MockCli) SetIn(arg0 *streams.In) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "SetIn", arg0)
|
||||
}
|
||||
|
||||
// SetIn indicates an expected call of SetIn.
|
||||
func (mr *MockCliMockRecorder) SetIn(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetIn", reflect.TypeOf((*MockCli)(nil).SetIn), arg0)
|
||||
}
|
||||
|
||||
// StackOrchestrator mocks base method.
|
||||
func (m *MockCli) StackOrchestrator(arg0 string) (command.Orchestrator, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "StackOrchestrator", arg0)
|
||||
ret0, _ := ret[0].(command.Orchestrator)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// StackOrchestrator indicates an expected call of StackOrchestrator.
|
||||
func (mr *MockCliMockRecorder) StackOrchestrator(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StackOrchestrator", reflect.TypeOf((*MockCli)(nil).StackOrchestrator), arg0)
|
||||
}
|
||||
@@ -90,28 +90,45 @@ func RunWithStatus(ctx context.Context, pf progressFuncWithStatus) (string, erro
|
||||
return result, err
|
||||
}
|
||||
|
||||
const (
|
||||
// ModeAuto detect console capabilities
|
||||
ModeAuto = "auto"
|
||||
// ModeTTY use terminal capability for advanced rendering
|
||||
ModeTTY = "tty"
|
||||
// ModePlain dump raw events to output
|
||||
ModePlain = "plain"
|
||||
)
|
||||
|
||||
// Mode define how progress should be rendered, either as ModePlain or ModeTTY
|
||||
var Mode = ModeAuto
|
||||
|
||||
// NewWriter returns a new multi-progress writer
|
||||
func NewWriter(out console.File) (Writer, error) {
|
||||
_, isTerminal := term.GetFdInfo(out)
|
||||
|
||||
if isTerminal {
|
||||
con, err := console.ConsoleFromFile(out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &ttyWriter{
|
||||
out: con,
|
||||
eventIDs: []string{},
|
||||
events: map[string]Event{},
|
||||
repeated: false,
|
||||
done: make(chan bool),
|
||||
mtx: &sync.Mutex{},
|
||||
}, nil
|
||||
if Mode == ModeAuto && isTerminal {
|
||||
return newTTYWriter(out)
|
||||
}
|
||||
if Mode == ModeTTY {
|
||||
return newTTYWriter(out)
|
||||
}
|
||||
|
||||
return &plainWriter{
|
||||
out: out,
|
||||
done: make(chan bool),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func newTTYWriter(out console.File) (Writer, error) {
|
||||
con, err := console.ConsoleFromFile(out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &ttyWriter{
|
||||
out: con,
|
||||
eventIDs: []string{},
|
||||
events: map[string]Event{},
|
||||
repeated: false,
|
||||
done: make(chan bool),
|
||||
mtx: &sync.Mutex{},
|
||||
}, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user