Repository: docker/compose-cli
Pull request #1143 (2021-01-14 11:34:16)

Local: Volumes implementation - align with docker-compose
Align with docker-compose volume setup.

Fixes https://github.com/docker/compose-cli/issues/1117

_docker-compose.yml_
```
version: "3.8"
services:
  test:
    image: test/hello
    build: ./backend
    ports:
      - 80:8080
    secrets:
      - my_secret                        # bind-mount
    volumes:
      - testvolume:/vol                  # named volume
      - type: bind                       # bind-mount
        source: ../nginx
        target: /compose
      - ./backend/creds:/src/creds.txt   # bind-mount
      - /anonymous                       # anonymous volume
      - externalvolume:/external         # external volume
      - type: tmpfs                      # tmpfs mount
        target: /temp
      

volumes:
  testvolume:
  externalvolume:
    external: True
    name: myvol
secrets:
  my_secret:
    file: ./secrets/mysecret.txt

```

```
$ docker-compose up -d

$ docker inspect hello_test_1 | jq '.[0].Config.Volumes, .[0].Mounts, .[0].HostConfig.Binds, .[0].HostConfig.Mounts'
{
  "/anonymous": {},
  "/data": {},
  "/external": {},
  "/src/creds.txt": {},
  "/vol": {}
}
[
  {
    "Type": "volume",
    "Name": "0cff20f55042c559881196a517f43596a4a990115fb093f0a43718300c019781",
    "Source": "/docker/volumes/0cff20f55042c559881196a517f43596a4a990115fb093f0a43718300c019781/_data",
    "Destination": "/anonymous",
    "Driver": "local",
    "Mode": "",
    "RW": true,
    "Propagation": ""
  },
  {
    "Type": "volume",
    "Name": "4168b061865866ca9900ad15c0f3b70785187c109e5eaa6346be69845656bc17",
    "Source": "/docker/volumes/4168b061865866ca9900ad15c0f3b70785187c109e5eaa6346be69845656bc17/_data",
    "Destination": "/data",
    "Driver": "local",
    "Mode": "",
    "RW": true,
    "Propagation": ""
  },
  {
    "Type": "volume",
    "Name": "myvol",
    "Source": "/docker/volumes/myvol/_data",
    "Destination": "/external",
    "Driver": "local",
    "Mode": "rw",
    "RW": true,
    "Propagation": ""
  },
  {
    "Type": "bind",
    "Source": "/test/hello/backend/creds",
    "Destination": "/src/creds.txt",
    "Mode": "rw",
    "RW": true,
    "Propagation": "rprivate"
  },
  {
    "Type": "volume",
    "Name": "hello_testvolume",
    "Source": "/docker/volumes/hello_testvolume/_data",
    "Destination": "/vol",
    "Driver": "local",
    "Mode": "rw",
    "RW": true,
    "Propagation": ""
  },
  {
    "Type": "tmpfs",
    "Source": "",
    "Destination": "/temp",
    "Mode": "",
    "RW": true,
    "Propagation": ""
  },
  {
    "Type": "bind",
    "Source": "/test/nginx",
    "Destination": "/compose",
    "Mode": "",
    "RW": true,
    "Propagation": "rprivate"
  },
  {
    "Type": "bind",
    "Source": "/test/hello/secrets/mysecret.txt",
    "Destination": "/run/secrets/my_secret",
    "Mode": "",
    "RW": false,
    "Propagation": "rprivate"
  }
]
[
  "myvol:/external:rw",
  /test/hello/backend/creds:/src/creds.txt:rw",
  "hello_testvolume:/vol:rw"
]
[
  {
    "Type": "tmpfs",
    "Target": "/temp"
  },
  {
    "Type": "bind",
    "Source": "/test/nginx",
    "Target": "/compose"
  },
  {
    "Type": "bind",
    "Source": "/test/hello/secrets/mysecret.txt",
    "Target": "/run/secrets/my_secret",
    "ReadOnly": true
  }
]

```



```
$ docker compose up -d

$ docker inspect hello_test_1 | jq '.[0].Config.Volumes, .[0].Mounts, .[0].HostConfig.Binds, .[0].HostConfig.Mounts'
{
  "/anonymous": {},
  "/data": {},
  "/external": {},
  "/vol": {}
}
[
  {
    "Type": "bind",
    "Source": "/test/nginx",
    "Destination": "/compose",
    "Mode": "",
    "RW": true,
    "Propagation": "rprivate"
  },
  {
    "Type": "volume",
    "Name": "f06a5c997f924bf7a8ef900bff4209239330c60c411468f16cd7e95484581090",
    "Source": "/docker/volumes/f06a5c997f924bf7a8ef900bff4209239330c60c411468f16cd7e95484581090/_data",
    "Destination": "/anonymous",
    "Driver": "local",
    "Mode": "",
    "RW": true,
    "Propagation": ""
  },
  {
    "Type": "volume",
    "Name": "11c2f88dcff366572e223412694ed5099e4a82f861494c6a4d245d575426383b",
    "Source": "/docker/volumes/11c2f88dcff366572e223412694ed5099e4a82f861494c6a4d245d575426383b/_data",
    "Destination": "/data",
    "Driver": "local",
    "Mode": "",
    "RW": true,
    "Propagation": ""
  },
  {
    "Type": "volume",
    "Name": "myvol",
    "Source": "/docker/volumes/myvol/_data",
    "Destination": "/external",
    "Driver": "local",
    "Mode": "rw",
    "RW": true,
    "Propagation": ""
  },
  {
    "Type": "volume",
    "Name": "hello_testvolume",
    "Source": "/docker/volumes/hello_testvolume/_data",
    "Destination": "/vol",
    "Driver": "local",
    "Mode": "rw",
    "RW": true,
    "Propagation": ""
  },
  {
    "Type": "bind",
    "Source": "/test/hello/secrets/mysecret.txt",
    "Destination": "/run/secrets/my_secret",
    "Mode": "",
    "RW": true,
    "Propagation": "rprivate"
  },
  {
    "Type": "bind",
    "Source": "/test/hello/backend/creds",
    "Destination": "/src/creds.txt",
    "Mode": "",
    "RW": true,
    "Propagation": "rprivate"
  },
  {
    "Type": "tmpfs",
    "Source": "",
    "Destination": "/temp",
    "Mode": "",
    "RW": true,
    "Propagation": ""
  }
]
[
  "myvol:/external:rw",
  "hello_testvolume:/vol:rw"
]
[
  {
    "Type": "bind",
    "Source": "/test/hello/secrets/mysecret.txt",
    "Target": "/run/secrets/my_secret"
  },
  {
    "Type": "bind",
    "Source": "/test/hello/backend/creds",
    "Target": "/src/creds.txt"
  },
  {
    "Type": "tmpfs",
    "Target": "/temp"
  },
  {
    "Type": "bind",
    "Source": "/test/nginx",
    "Target": "/compose"
  }
]



```









Patch:
diff --git a/aci/aci.go b/aci/aci.go
index 7478b978..d576d224 100644
--- a/aci/aci.go
+++ b/aci/aci.go
@@ -38,9 +38,9 @@ import (
 	"github.com/docker/compose-cli/aci/login"
 	"github.com/docker/compose-cli/api/client"
 	"github.com/docker/compose-cli/api/containers"
-	"github.com/docker/compose-cli/api/context/store"
-	"github.com/docker/compose-cli/api/errdefs"
-	"github.com/docker/compose-cli/api/progress"
+	"github.com/docker/compose-cli/context/store"
+	"github.com/docker/compose-cli/errdefs"
+	"github.com/docker/compose-cli/progress"
 )
 
 func createACIContainers(ctx context.Context, aciContext store.AciContext, groupDefinition containerinstance.ContainerGroup) error {
diff --git a/aci/backend.go b/aci/backend.go
index 37332636..b2886392 100644
--- a/aci/backend.go
+++ b/aci/backend.go
@@ -26,16 +26,15 @@ import (
 
 	"github.com/docker/compose-cli/aci/convert"
 	"github.com/docker/compose-cli/aci/login"
-	"github.com/docker/compose-cli/api/backend"
 	"github.com/docker/compose-cli/api/compose"
 	"github.com/docker/compose-cli/api/containers"
 	"github.com/docker/compose-cli/api/resources"
 	"github.com/docker/compose-cli/api/secrets"
 	"github.com/docker/compose-cli/api/volumes"
-
-	"github.com/docker/compose-cli/api/cloud"
-	apicontext "github.com/docker/compose-cli/api/context"
-	"github.com/docker/compose-cli/api/context/store"
+	"github.com/docker/compose-cli/backend"
+	apicontext "github.com/docker/compose-cli/context"
+	"github.com/docker/compose-cli/context/cloud"
+	"github.com/docker/compose-cli/context/store"
 )
 
 const (
diff --git a/aci/compose.go b/aci/compose.go
index 60a42b17..2820e192 100644
--- a/aci/compose.go
+++ b/aci/compose.go
@@ -27,8 +27,8 @@ import (
 	"github.com/docker/compose-cli/aci/convert"
 	"github.com/docker/compose-cli/aci/login"
 	"github.com/docker/compose-cli/api/compose"
-	"github.com/docker/compose-cli/api/context/store"
-	"github.com/docker/compose-cli/api/errdefs"
+	"github.com/docker/compose-cli/context/store"
+	"github.com/docker/compose-cli/errdefs"
 	"github.com/docker/compose-cli/utils/formatter"
 )
 
diff --git a/aci/containers.go b/aci/containers.go
index 0425c583..1b8a926d 100644
--- a/aci/containers.go
+++ b/aci/containers.go
@@ -32,8 +32,8 @@ import (
 	"github.com/docker/compose-cli/aci/convert"
 	"github.com/docker/compose-cli/aci/login"
 	"github.com/docker/compose-cli/api/containers"
-	"github.com/docker/compose-cli/api/context/store"
-	"github.com/docker/compose-cli/api/errdefs"
+	"github.com/docker/compose-cli/context/store"
+	"github.com/docker/compose-cli/errdefs"
 )
 
 type aciContainerService struct {
diff --git a/aci/context.go b/aci/context.go
index 7f9cdb4c..7ef34a2a 100644
--- a/aci/context.go
+++ b/aci/context.go
@@ -27,9 +27,9 @@ import (
 	"github.com/hashicorp/go-uuid"
 	"github.com/pkg/errors"
 
-	"github.com/docker/compose-cli/api/context/store"
-	"github.com/docker/compose-cli/api/errdefs"
-	"github.com/docker/compose-cli/utils/prompt"
+	"github.com/docker/compose-cli/context/store"
+	"github.com/docker/compose-cli/errdefs"
+	"github.com/docker/compose-cli/prompt"
 )
 
 // ContextParams options for creating ACI context
diff --git a/aci/convert/convert.go b/aci/convert/convert.go
index 0032a4b9..9dbcee3f 100644
--- a/aci/convert/convert.go
+++ b/aci/convert/convert.go
@@ -33,7 +33,7 @@ import (
 	"github.com/docker/compose-cli/aci/login"
 	"github.com/docker/compose-cli/api/compose"
 	"github.com/docker/compose-cli/api/containers"
-	"github.com/docker/compose-cli/api/context/store"
+	"github.com/docker/compose-cli/context/store"
 	"github.com/docker/compose-cli/utils/formatter"
 )
 
diff --git a/aci/convert/volume.go b/aci/convert/volume.go
index 3c3e0dd4..c64aa53b 100644
--- a/aci/convert/volume.go
+++ b/aci/convert/volume.go
@@ -30,7 +30,7 @@ import (
 	"github.com/compose-spec/compose-go/types"
 
 	"github.com/docker/compose-cli/aci/login"
-	"github.com/docker/compose-cli/api/errdefs"
+	"github.com/docker/compose-cli/errdefs"
 )
 
 const (
diff --git a/aci/login/client.go b/aci/login/client.go
index 55b2fb97..635288b3 100644
--- a/aci/login/client.go
+++ b/aci/login/client.go
@@ -26,7 +26,7 @@ import (
 	"github.com/Azure/go-autorest/autorest"
 	"github.com/pkg/errors"
 
-	"github.com/docker/compose-cli/api/errdefs"
+	"github.com/docker/compose-cli/errdefs"
 	"github.com/docker/compose-cli/internal"
 )
 
diff --git a/aci/login/login.go b/aci/login/login.go
index 21cb30fc..9c99bcb8 100644
--- a/aci/login/login.go
+++ b/aci/login/login.go
@@ -33,7 +33,7 @@ import (
 	"github.com/pkg/errors"
 	"golang.org/x/oauth2"
 
-	"github.com/docker/compose-cli/api/errdefs"
+	"github.com/docker/compose-cli/errdefs"
 )
 
 //go login process, derived from code sample provided by MS at https://github.com/devigned/go-az-cli-stuff
diff --git a/aci/login/storagelogin.go b/aci/login/storagelogin.go
index fbaefb06..8ec65b06 100644
--- a/aci/login/storagelogin.go
+++ b/aci/login/storagelogin.go
@@ -22,7 +22,7 @@ import (
 
 	"github.com/pkg/errors"
 
-	"github.com/docker/compose-cli/api/context/store"
+	"github.com/docker/compose-cli/context/store"
 )
 
 // StorageLogin helper for Azure Storage Login
diff --git a/aci/resources.go b/aci/resources.go
index c483de1b..8732dbc6 100644
--- a/aci/resources.go
+++ b/aci/resources.go
@@ -23,8 +23,8 @@ import (
 	"github.com/hashicorp/go-multierror"
 
 	"github.com/docker/compose-cli/aci/convert"
-	"github.com/docker/compose-cli/api/context/store"
 	"github.com/docker/compose-cli/api/resources"
+	"github.com/docker/compose-cli/context/store"
 )
 
 type aciResourceService struct {
diff --git a/aci/volumes.go b/aci/volumes.go
index caa2bc0f..2c012b53 100644
--- a/aci/volumes.go
+++ b/aci/volumes.go
@@ -29,10 +29,10 @@ import (
 	"github.com/Azure/go-autorest/autorest/to"
 
 	"github.com/docker/compose-cli/aci/login"
-	"github.com/docker/compose-cli/api/context/store"
-	"github.com/docker/compose-cli/api/errdefs"
-	"github.com/docker/compose-cli/api/progress"
 	"github.com/docker/compose-cli/api/volumes"
+	"github.com/docker/compose-cli/context/store"
+	"github.com/docker/compose-cli/errdefs"
+	"github.com/docker/compose-cli/progress"
 )
 
 type aciVolumeService struct {
diff --git a/api/client/client.go b/api/client/client.go
index bbcd759a..10c0bbda 100644
--- a/api/client/client.go
+++ b/api/client/client.go
@@ -19,15 +19,15 @@ package client
 import (
 	"context"
 
-	"github.com/docker/compose-cli/api/backend"
-	"github.com/docker/compose-cli/api/cloud"
 	"github.com/docker/compose-cli/api/compose"
 	"github.com/docker/compose-cli/api/containers"
-	apicontext "github.com/docker/compose-cli/api/context"
-	"github.com/docker/compose-cli/api/context/store"
 	"github.com/docker/compose-cli/api/resources"
 	"github.com/docker/compose-cli/api/secrets"
 	"github.com/docker/compose-cli/api/volumes"
+	"github.com/docker/compose-cli/backend"
+	apicontext "github.com/docker/compose-cli/context"
+	"github.com/docker/compose-cli/context/cloud"
+	"github.com/docker/compose-cli/context/store"
 )
 
 // New returns a backend client associated with current context
diff --git a/api/client/compose.go b/api/client/compose.go
index 072b06b9..0c621123 100644
--- a/api/client/compose.go
+++ b/api/client/compose.go
@@ -20,7 +20,7 @@ import (
 	"context"
 
 	"github.com/docker/compose-cli/api/compose"
-	"github.com/docker/compose-cli/api/errdefs"
+	"github.com/docker/compose-cli/errdefs"
 
 	"github.com/compose-spec/compose-go/types"
 )
diff --git a/api/client/containers.go b/api/client/containers.go
index 1b1e665b..efa39537 100644
--- a/api/client/containers.go
+++ b/api/client/containers.go
@@ -20,7 +20,7 @@ import (
 	"context"
 
 	"github.com/docker/compose-cli/api/containers"
-	"github.com/docker/compose-cli/api/errdefs"
+	"github.com/docker/compose-cli/errdefs"
 )
 
 type containerService struct {
diff --git a/api/client/resources.go b/api/client/resources.go
index 04b74219..cefb6c48 100644
--- a/api/client/resources.go
+++ b/api/client/resources.go
@@ -19,8 +19,8 @@ package client
 import (
 	"context"
 
-	"github.com/docker/compose-cli/api/errdefs"
 	"github.com/docker/compose-cli/api/resources"
+	"github.com/docker/compose-cli/errdefs"
 )
 
 type resourceService struct {
diff --git a/api/client/secrets.go b/api/client/secrets.go
index a263e5fd..8c2debd2 100644
--- a/api/client/secrets.go
+++ b/api/client/secrets.go
@@ -19,8 +19,8 @@ package client
 import (
 	"context"
 
-	"github.com/docker/compose-cli/api/errdefs"
 	"github.com/docker/compose-cli/api/secrets"
+	"github.com/docker/compose-cli/errdefs"
 )
 
 type secretsService struct {
diff --git a/api/client/volume.go b/api/client/volume.go
index aa359754..23d99c3d 100644
--- a/api/client/volume.go
+++ b/api/client/volume.go
@@ -19,8 +19,8 @@ package client
 import (
 	"context"
 
-	"github.com/docker/compose-cli/api/errdefs"
 	"github.com/docker/compose-cli/api/volumes"
+	"github.com/docker/compose-cli/errdefs"
 )
 
 type volumeService struct {
diff --git a/api/compose/api.go b/api/compose/api.go
index 19a535b2..72f3517e 100644
--- a/api/compose/api.go
+++ b/api/compose/api.go
@@ -67,8 +67,6 @@ type UpOptions struct {
 type DownOptions struct {
 	// RemoveOrphans will cleanup containers that are not declared on the compose model but own the same labels
 	RemoveOrphans bool
-	// Project is the compose project used to define this app. Might be nil if user ran `down` just with project name
-	Project *types.Project
 }
 
 // ConvertOptions group options of the Convert API
diff --git a/api/containers/api.go b/api/containers/api.go
index 02cab49d..f5f55d2c 100644
--- a/api/containers/api.go
+++ b/api/containers/api.go
@@ -23,7 +23,7 @@ import (
 	"github.com/compose-spec/compose-go/types"
 	specs "github.com/opencontainers/image-spec/specs-go/v1"
 
-	"github.com/docker/compose-cli/utils"
+	"github.com/docker/compose-cli/formatter"
 )
 
 const (
@@ -102,7 +102,7 @@ type ContainerConfig struct {
 	// Volumes to be mounted
 	Volumes []string
 	// Memlimit
-	MemLimit utils.MemBytes
+	MemLimit formatter.MemBytes
 	// CPUlimit
 	CPULimit float64
 	// Environment variables
diff --git a/api/backend/backend.go b/backend/backend.go
similarity index 97%
rename from api/backend/backend.go
rename to backend/backend.go
index b1aa3ead..8852151b 100644
--- a/api/backend/backend.go
+++ b/backend/backend.go
@@ -23,13 +23,13 @@ import (
 
 	"github.com/sirupsen/logrus"
 
-	"github.com/docker/compose-cli/api/cloud"
 	"github.com/docker/compose-cli/api/compose"
 	"github.com/docker/compose-cli/api/containers"
-	"github.com/docker/compose-cli/api/errdefs"
 	"github.com/docker/compose-cli/api/resources"
 	"github.com/docker/compose-cli/api/secrets"
 	"github.com/docker/compose-cli/api/volumes"
+	"github.com/docker/compose-cli/context/cloud"
+	"github.com/docker/compose-cli/errdefs"
 )
 
 var (
diff --git a/cli/cmd/compose/build.go b/cli/cmd/compose/build.go
index 2389f939..6caf7474 100644
--- a/cli/cmd/compose/build.go
+++ b/cli/cmd/compose/build.go
@@ -19,10 +19,11 @@ package compose
 import (
 	"context"
 
+	"github.com/compose-spec/compose-go/cli"
 	"github.com/spf13/cobra"
 
 	"github.com/docker/compose-cli/api/client"
-	"github.com/docker/compose-cli/api/progress"
+	"github.com/docker/compose-cli/progress"
 )
 
 type buildOptions struct {
@@ -51,7 +52,11 @@ func runBuild(ctx context.Context, opts buildOptions, services []string) error {
 	}
 
 	_, err = progress.Run(ctx, func(ctx context.Context) (string, error) {
-		project, err := opts.toProject()
+		options, err := opts.toProjectOptions()
+		if err != nil {
+			return "", err
+		}
+		project, err := cli.ProjectFromOptions(options)
 		if err != nil {
 			return "", err
 		}
diff --git a/cli/cmd/compose/compose.go b/cli/cmd/compose/compose.go
index 7f9b44fa..ddd04385 100644
--- a/cli/cmd/compose/compose.go
+++ b/cli/cmd/compose/compose.go
@@ -24,7 +24,7 @@ import (
 	"github.com/spf13/cobra"
 	"github.com/spf13/pflag"
 
-	"github.com/docker/compose-cli/api/context/store"
+	"github.com/docker/compose-cli/context/store"
 )
 
 type composeOptions struct {
@@ -50,24 +50,16 @@ func (o *composeOptions) toProjectName() (string, error) {
 		return o.ProjectName, nil
 	}
 
-	project, err := o.toProject()
-	if err != nil {
-		return "", err
-	}
-	return project.Name, nil
-}
-
-func (o *composeOptions) toProject() (*types.Project, error) {
 	options, err := o.toProjectOptions()
 	if err != nil {
-		return nil, err
+		return "", err
 	}
 
 	project, err := cli.ProjectFromOptions(options)
 	if err != nil {
-		return nil, err
+		return "", err
 	}
-	return project, nil
+	return project.Name, nil
 }
 
 func (o *composeOptions) toProjectOptions() (*cli.ProjectOptions, error) {
diff --git a/cli/cmd/compose/convert.go b/cli/cmd/compose/convert.go
index 8085b5f7..57a77bec 100644
--- a/cli/cmd/compose/convert.go
+++ b/cli/cmd/compose/convert.go
@@ -22,6 +22,7 @@ import (
 
 	"github.com/docker/compose-cli/api/compose"
 
+	"github.com/compose-spec/compose-go/cli"
 	"github.com/spf13/cobra"
 
 	"github.com/docker/compose-cli/api/client"
@@ -52,7 +53,12 @@ func runConvert(ctx context.Context, opts composeOptions) error {
 		return err
 	}
 
-	project, err := opts.toProject()
+	options, err := opts.toProjectOptions()
+	if err != nil {
+		return err
+	}
+
+	project, err := cli.ProjectFromOptions(options)
 	if err != nil {
 		return err
 	}
diff --git a/cli/cmd/compose/down.go b/cli/cmd/compose/down.go
index dec17e31..ac1b9355 100644
--- a/cli/cmd/compose/down.go
+++ b/cli/cmd/compose/down.go
@@ -19,14 +19,12 @@ package compose
 import (
 	"context"
 
-	"github.com/compose-spec/compose-go/types"
-
 	"github.com/docker/compose-cli/api/compose"
 
 	"github.com/spf13/cobra"
 
 	"github.com/docker/compose-cli/api/client"
-	"github.com/docker/compose-cli/api/progress"
+	"github.com/docker/compose-cli/progress"
 )
 
 func downCommand() *cobra.Command {
@@ -52,20 +50,12 @@ func runDown(ctx context.Context, opts composeOptions) error {
 	}
 
 	_, err = progress.Run(ctx, func(ctx context.Context) (string, error) {
-		name := opts.ProjectName
-		var project *types.Project
-		if opts.ProjectName == "" {
-			p, err := opts.toProject()
-			if err != nil {
-				return "", err
-			}
-			project = p
-			name = p.Name
+		projectName, err := opts.toProjectName()
+		if err != nil {
+			return "", err
 		}
-
-		return name, c.ComposeService().Down(ctx, name, compose.DownOptions{
+		return projectName, c.ComposeService().Down(ctx, projectName, compose.DownOptions{
 			RemoveOrphans: false,
-			Project:       project,
 		})
 	})
 	return err
diff --git a/cli/cmd/compose/list.go b/cli/cmd/compose/list.go
index 114cf2aa..8b8d7c07 100644
--- a/cli/cmd/compose/list.go
+++ b/cli/cmd/compose/list.go
@@ -27,7 +27,7 @@ import (
 
 	"github.com/docker/compose-cli/api/client"
 	"github.com/docker/compose-cli/api/compose"
-	"github.com/docker/compose-cli/cli/formatter"
+	"github.com/docker/compose-cli/formatter"
 )
 
 func listCommand() *cobra.Command {
diff --git a/cli/cmd/compose/logs.go b/cli/cmd/compose/logs.go
index 49758d45..6993943b 100644
--- a/cli/cmd/compose/logs.go
+++ b/cli/cmd/compose/logs.go
@@ -24,7 +24,7 @@ import (
 
 	"github.com/docker/compose-cli/api/client"
 	"github.com/docker/compose-cli/api/compose"
-	"github.com/docker/compose-cli/cli/formatter"
+	"github.com/docker/compose-cli/formatter"
 )
 
 func logsCommand() *cobra.Command {
diff --git a/cli/cmd/compose/ps.go b/cli/cmd/compose/ps.go
index aa317aa9..63d7b512 100644
--- a/cli/cmd/compose/ps.go
+++ b/cli/cmd/compose/ps.go
@@ -27,7 +27,7 @@ import (
 	"github.com/spf13/cobra"
 
 	"github.com/docker/compose-cli/api/client"
-	"github.com/docker/compose-cli/cli/formatter"
+	"github.com/docker/compose-cli/formatter"
 )
 
 func psCommand() *cobra.Command {
diff --git a/cli/cmd/compose/pull.go b/cli/cmd/compose/pull.go
index 154cd603..03ce586a 100644
--- a/cli/cmd/compose/pull.go
+++ b/cli/cmd/compose/pull.go
@@ -19,10 +19,11 @@ package compose
 import (
 	"context"
 
+	"github.com/compose-spec/compose-go/cli"
 	"github.com/spf13/cobra"
 
 	"github.com/docker/compose-cli/api/client"
-	"github.com/docker/compose-cli/api/progress"
+	"github.com/docker/compose-cli/progress"
 )
 
 type pullOptions struct {
@@ -52,7 +53,11 @@ func runPull(ctx context.Context, opts pullOptions, services []string) error {
 	}
 
 	_, err = progress.Run(ctx, func(ctx context.Context) (string, error) {
-		project, err := opts.toProject()
+		options, err := opts.toProjectOptions()
+		if err != nil {
+			return "", err
+		}
+		project, err := cli.ProjectFromOptions(options)
 		if err != nil {
 			return "", err
 		}
diff --git a/cli/cmd/compose/push.go b/cli/cmd/compose/push.go
index 49b028ab..2c95ceea 100644
--- a/cli/cmd/compose/push.go
+++ b/cli/cmd/compose/push.go
@@ -19,10 +19,11 @@ package compose
 import (
 	"context"
 
+	"github.com/compose-spec/compose-go/cli"
 	"github.com/spf13/cobra"
 
 	"github.com/docker/compose-cli/api/client"
-	"github.com/docker/compose-cli/api/progress"
+	"github.com/docker/compose-cli/progress"
 )
 
 type pushOptions struct {
@@ -52,7 +53,11 @@ func runPush(ctx context.Context, opts pushOptions, services []string) error {
 	}
 
 	_, err = progress.Run(ctx, func(ctx context.Context) (string, error) {
-		project, err := opts.toProject()
+		options, err := opts.toProjectOptions()
+		if err != nil {
+			return "", err
+		}
+		project, err := cli.ProjectFromOptions(options)
 		if err != nil {
 			return "", err
 		}
diff --git a/cli/cmd/compose/run.go b/cli/cmd/compose/run.go
index b97574d1..3c019cb1 100644
--- a/cli/cmd/compose/run.go
+++ b/cli/cmd/compose/run.go
@@ -25,7 +25,7 @@ import (
 
 	"github.com/docker/compose-cli/api/client"
 	"github.com/docker/compose-cli/api/compose"
-	"github.com/docker/compose-cli/api/progress"
+	"github.com/docker/compose-cli/progress"
 )
 
 type runOptions struct {
diff --git a/cli/cmd/compose/up.go b/cli/cmd/compose/up.go
index 6d0dfb5a..c84b9dd5 100644
--- a/cli/cmd/compose/up.go
+++ b/cli/cmd/compose/up.go
@@ -24,10 +24,11 @@ import (
 
 	"github.com/docker/compose-cli/api/client"
 	"github.com/docker/compose-cli/api/compose"
-	"github.com/docker/compose-cli/api/context/store"
-	"github.com/docker/compose-cli/api/progress"
-	"github.com/docker/compose-cli/cli/formatter"
+	"github.com/docker/compose-cli/context/store"
+	"github.com/docker/compose-cli/formatter"
+	"github.com/docker/compose-cli/progress"
 
+	"github.com/compose-spec/compose-go/cli"
 	"github.com/compose-spec/compose-go/types"
 	"github.com/spf13/cobra"
 )
@@ -117,7 +118,11 @@ func setup(ctx context.Context, opts composeOptions, services []string) (*client
 		return nil, nil, err
 	}
 
-	project, err := opts.toProject()
+	options, err := opts.toProjectOptions()
+	if err != nil {
+		return nil, nil, err
+	}
+	project, err := cli.ProjectFromOptions(options)
 	if err != nil {
 		return nil, nil, err
 	}
diff --git a/cli/cmd/context/create.go b/cli/cmd/context/create.go
index 65354da8..941527f9 100644
--- a/cli/cmd/context/create.go
+++ b/cli/cmd/context/create.go
@@ -23,8 +23,8 @@ import (
 
 	"github.com/spf13/cobra"
 
-	"github.com/docker/compose-cli/api/context/store"
 	"github.com/docker/compose-cli/cli/mobycli"
+	"github.com/docker/compose-cli/context/store"
 )
 
 type descriptionCreateOpts struct {
diff --git a/cli/cmd/context/create_aci.go b/cli/cmd/context/create_aci.go
index 0c6f7c41..c66787df 100644
--- a/cli/cmd/context/create_aci.go
+++ b/cli/cmd/context/create_aci.go
@@ -24,8 +24,8 @@ import (
 
 	"github.com/docker/compose-cli/aci"
 	"github.com/docker/compose-cli/api/client"
-	"github.com/docker/compose-cli/api/context/store"
-	"github.com/docker/compose-cli/api/errdefs"
+	"github.com/docker/compose-cli/context/store"
+	"github.com/docker/compose-cli/errdefs"
 )
 
 func init() {
diff --git a/cli/cmd/context/create_ecs.go b/cli/cmd/context/create_ecs.go
index 34ba11c4..2d76bf0d 100644
--- a/cli/cmd/context/create_ecs.go
+++ b/cli/cmd/context/create_ecs.go
@@ -23,13 +23,12 @@ import (
 	"os"
 	"strings"
 
-	"github.com/pkg/errors"
-	"github.com/spf13/cobra"
-
 	"github.com/docker/compose-cli/api/client"
-	"github.com/docker/compose-cli/api/context/store"
-	"github.com/docker/compose-cli/api/errdefs"
+	"github.com/docker/compose-cli/context/store"
 	"github.com/docker/compose-cli/ecs"
+	"github.com/docker/compose-cli/errdefs"
+	"github.com/pkg/errors"
+	"github.com/spf13/cobra"
 )
 
 func init() {
diff --git a/cli/cmd/context/ls.go b/cli/cmd/context/ls.go
index ffcd1b8e..b5119328 100644
--- a/cli/cmd/context/ls.go
+++ b/cli/cmd/context/ls.go
@@ -26,10 +26,10 @@ import (
 	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
 
-	apicontext "github.com/docker/compose-cli/api/context"
-	"github.com/docker/compose-cli/api/context/store"
-	"github.com/docker/compose-cli/cli/formatter"
 	"github.com/docker/compose-cli/cli/mobycli"
+	apicontext "github.com/docker/compose-cli/context"
+	"github.com/docker/compose-cli/context/store"
+	"github.com/docker/compose-cli/formatter"
 )
 
 type lsOpts struct {
diff --git a/cli/cmd/context/rm.go b/cli/cmd/context/rm.go
index 473b13e6..5ad9f060 100644
--- a/cli/cmd/context/rm.go
+++ b/cli/cmd/context/rm.go
@@ -24,9 +24,9 @@ import (
 	"github.com/hashicorp/go-multierror"
 	"github.com/spf13/cobra"
 
-	apicontext "github.com/docker/compose-cli/api/context"
-	"github.com/docker/compose-cli/api/context/store"
 	"github.com/docker/compose-cli/cli/formatter"
+	apicontext "github.com/docker/compose-cli/context"
+	"github.com/docker/compose-cli/context/store"
 )
 
 type removeOpts struct {
diff --git a/cli/cmd/context/show.go b/cli/cmd/context/show.go
index 69dc91da..5b6c2129 100644
--- a/cli/cmd/context/show.go
+++ b/cli/cmd/context/show.go
@@ -22,8 +22,8 @@ import (
 
 	"github.com/spf13/cobra"
 
-	apicontext "github.com/docker/compose-cli/api/context"
-	"github.com/docker/compose-cli/api/context/store"
+	apicontext "github.com/docker/compose-cli/context"
+	"github.com/docker/compose-cli/context/store"
 )
 
 func showCommand() *cobra.Command {
diff --git a/cli/cmd/context/update.go b/cli/cmd/context/update.go
index f21182b4..dcc4a3b4 100644
--- a/cli/cmd/context/update.go
+++ b/cli/cmd/context/update.go
@@ -20,9 +20,9 @@ import (
 	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
 
-	"github.com/docker/compose-cli/api/context/store"
-	"github.com/docker/compose-cli/api/errdefs"
 	"github.com/docker/compose-cli/cli/mobycli"
+	"github.com/docker/compose-cli/context/store"
+	"github.com/docker/compose-cli/errdefs"
 )
 
 func updateCommand() *cobra.Command {
diff --git a/cli/cmd/context/use.go b/cli/cmd/context/use.go
index 8c4684c5..d58c2d99 100644
--- a/cli/cmd/context/use.go
+++ b/cli/cmd/context/use.go
@@ -22,8 +22,8 @@ import (
 
 	"github.com/spf13/cobra"
 
-	"github.com/docker/compose-cli/api/config"
-	"github.com/docker/compose-cli/api/context/store"
+	"github.com/docker/compose-cli/config"
+	"github.com/docker/compose-cli/context/store"
 )
 
 func useCommand() *cobra.Command {
diff --git a/cli/cmd/inspect.go b/cli/cmd/inspect.go
index e344794c..6ce9a0e2 100644
--- a/cli/cmd/inspect.go
+++ b/cli/cmd/inspect.go
@@ -27,7 +27,7 @@ import (
 
 	"github.com/docker/compose-cli/api/client"
 	"github.com/docker/compose-cli/api/containers"
-	"github.com/docker/compose-cli/cli/formatter"
+	"github.com/docker/compose-cli/formatter"
 )
 
 // InspectCommand inspects into containers
diff --git a/cli/cmd/kill.go b/cli/cmd/kill.go
index 0de597d7..9b14f7fe 100644
--- a/cli/cmd/kill.go
+++ b/cli/cmd/kill.go
@@ -25,8 +25,8 @@ import (
 	"github.com/spf13/cobra"
 
 	"github.com/docker/compose-cli/api/client"
-	"github.com/docker/compose-cli/api/errdefs"
 	"github.com/docker/compose-cli/cli/formatter"
+	"github.com/docker/compose-cli/errdefs"
 )
 
 type killOpts struct {
diff --git a/cli/cmd/login/login.go b/cli/cmd/login/login.go
index 7163dc96..78cc0a99 100644
--- a/cli/cmd/login/login.go
+++ b/cli/cmd/login/login.go
@@ -24,9 +24,9 @@ import (
 	"github.com/spf13/cobra"
 
 	"github.com/docker/compose-cli/api/client"
-	"github.com/docker/compose-cli/api/errdefs"
 	"github.com/docker/compose-cli/cli/cmd/mobyflags"
 	"github.com/docker/compose-cli/cli/mobycli"
+	"github.com/docker/compose-cli/errdefs"
 )
 
 // Command returns the login command
diff --git a/cli/cmd/logout/azure.go b/cli/cmd/logout/azure.go
index 2c209a49..1f0ca039 100644
--- a/cli/cmd/logout/azure.go
+++ b/cli/cmd/logout/azure.go
@@ -24,7 +24,7 @@ import (
 	"github.com/spf13/cobra"
 
 	"github.com/docker/compose-cli/api/client"
-	"github.com/docker/compose-cli/api/errdefs"
+	"github.com/docker/compose-cli/errdefs"
 )
 
 // AzureLogoutCommand returns the azure logout command
diff --git a/cli/cmd/ps.go b/cli/cmd/ps.go
index 587999b1..56d6ab72 100644
--- a/cli/cmd/ps.go
+++ b/cli/cmd/ps.go
@@ -28,7 +28,7 @@ import (
 
 	"github.com/docker/compose-cli/api/client"
 	"github.com/docker/compose-cli/api/containers"
-	formatter2 "github.com/docker/compose-cli/cli/formatter"
+	formatter2 "github.com/docker/compose-cli/formatter"
 	"github.com/docker/compose-cli/utils/formatter"
 )
 
diff --git a/cli/cmd/rm.go b/cli/cmd/rm.go
index 0f38f8c7..5a824513 100644
--- a/cli/cmd/rm.go
+++ b/cli/cmd/rm.go
@@ -26,8 +26,8 @@ import (
 
 	"github.com/docker/compose-cli/api/client"
 	"github.com/docker/compose-cli/api/containers"
-	"github.com/docker/compose-cli/api/errdefs"
 	"github.com/docker/compose-cli/cli/formatter"
+	"github.com/docker/compose-cli/errdefs"
 )
 
 type rmOpts struct {
diff --git a/cli/cmd/run/run.go b/cli/cmd/run/run.go
index 62ea4be8..c08008bc 100644
--- a/cli/cmd/run/run.go
+++ b/cli/cmd/run/run.go
@@ -28,9 +28,9 @@ import (
 
 	"github.com/docker/compose-cli/api/client"
 	"github.com/docker/compose-cli/api/containers"
-	"github.com/docker/compose-cli/api/context/store"
-	"github.com/docker/compose-cli/api/progress"
 	"github.com/docker/compose-cli/cli/options/run"
+	"github.com/docker/compose-cli/context/store"
+	"github.com/docker/compose-cli/progress"
 )
 
 // Command runs a container
diff --git a/cli/cmd/secrets.go b/cli/cmd/secrets.go
index 22a9e934..0fc14c58 100644
--- a/cli/cmd/secrets.go
+++ b/cli/cmd/secrets.go
@@ -26,7 +26,7 @@ import (
 
 	"github.com/docker/compose-cli/api/client"
 	"github.com/docker/compose-cli/api/secrets"
-	"github.com/docker/compose-cli/cli/formatter"
+	"github.com/docker/compose-cli/formatter"
 )
 
 // SecretCommand manage secrets
diff --git a/cli/cmd/serve.go b/cli/cmd/serve.go
index dcdde89d..d11e47a0 100644
--- a/cli/cmd/serve.go
+++ b/cli/cmd/serve.go
@@ -23,13 +23,13 @@ import (
 	"github.com/sirupsen/logrus"
 	"github.com/spf13/cobra"
 
-	"github.com/docker/compose-cli/cli/server"
-	composev1 "github.com/docker/compose-cli/cli/server/protos/compose/v1"
-	containersv1 "github.com/docker/compose-cli/cli/server/protos/containers/v1"
-	contextsv1 "github.com/docker/compose-cli/cli/server/protos/contexts/v1"
-	streamsv1 "github.com/docker/compose-cli/cli/server/protos/streams/v1"
-	volumesv1 "github.com/docker/compose-cli/cli/server/protos/volumes/v1"
-	"github.com/docker/compose-cli/cli/server/proxy"
+	composev1 "github.com/docker/compose-cli/protos/compose/v1"
+	containersv1 "github.com/docker/compose-cli/protos/containers/v1"
+	contextsv1 "github.com/docker/compose-cli/protos/contexts/v1"
+	streamsv1 "github.com/docker/compose-cli/protos/streams/v1"
+	volumesv1 "github.com/docker/compose-cli/protos/volumes/v1"
+	"github.com/docker/compose-cli/server"
+	"github.com/docker/compose-cli/server/proxy"
 )
 
 type serveOpts struct {
diff --git a/cli/cmd/start.go b/cli/cmd/start.go
index 32e23112..14fb009d 100644
--- a/cli/cmd/start.go
+++ b/cli/cmd/start.go
@@ -25,8 +25,8 @@ import (
 	"github.com/spf13/cobra"
 
 	"github.com/docker/compose-cli/api/client"
-	"github.com/docker/compose-cli/api/errdefs"
 	"github.com/docker/compose-cli/cli/formatter"
+	"github.com/docker/compose-cli/errdefs"
 )
 
 // StartCommand starts containers
diff --git a/cli/cmd/stop.go b/cli/cmd/stop.go
index 460a301b..219c8e72 100644
--- a/cli/cmd/stop.go
+++ b/cli/cmd/stop.go
@@ -25,8 +25,8 @@ import (
 	"github.com/spf13/cobra"
 
 	"github.com/docker/compose-cli/api/client"
-	"github.com/docker/compose-cli/api/errdefs"
 	"github.com/docker/compose-cli/cli/formatter"
+	"github.com/docker/compose-cli/errdefs"
 )
 
 type stopOpts struct {
diff --git a/cli/cmd/version.go b/cli/cmd/version.go
index 83372aa3..f1238ab9 100644
--- a/cli/cmd/version.go
+++ b/cli/cmd/version.go
@@ -24,8 +24,8 @@ import (
 	"github.com/spf13/cobra"
 
 	"github.com/docker/compose-cli/cli/cmd/mobyflags"
-	"github.com/docker/compose-cli/cli/formatter"
 	"github.com/docker/compose-cli/cli/mobycli"
+	"github.com/docker/compose-cli/formatter"
 	"github.com/docker/compose-cli/internal"
 )
 
diff --git a/cli/cmd/volume/command.go b/cli/cmd/volume/command.go
index 8188c320..852a43d4 100644
--- a/cli/cmd/volume/command.go
+++ b/cli/cmd/volume/command.go
@@ -22,11 +22,11 @@ import (
 
 	"github.com/docker/compose-cli/aci"
 	"github.com/docker/compose-cli/api/client"
-	"github.com/docker/compose-cli/api/context/store"
-	"github.com/docker/compose-cli/api/progress"
 	"github.com/docker/compose-cli/cli/formatter"
-	formatter2 "github.com/docker/compose-cli/cli/formatter"
+	"github.com/docker/compose-cli/context/store"
 	"github.com/docker/compose-cli/ecs"
+	formatter2 "github.com/docker/compose-cli/formatter"
+	"github.com/docker/compose-cli/progress"
 
 	"github.com/hashicorp/go-multierror"
 	"github.com/spf13/cobra"
diff --git a/cli/cmd/volume/list.go b/cli/cmd/volume/list.go
index 8bbc2018..062ef63c 100644
--- a/cli/cmd/volume/list.go
+++ b/cli/cmd/volume/list.go
@@ -25,7 +25,7 @@ import (
 
 	"github.com/docker/compose-cli/api/client"
 	"github.com/docker/compose-cli/api/volumes"
-	"github.com/docker/compose-cli/cli/formatter"
+	"github.com/docker/compose-cli/formatter"
 )
 
 type listVolumeOpts struct {
diff --git a/cli/config/flags.go b/cli/config/flags.go
index 2a5265b2..2ba12e67 100644
--- a/cli/config/flags.go
+++ b/cli/config/flags.go
@@ -22,7 +22,7 @@ import (
 
 	"github.com/spf13/pflag"
 
-	"github.com/docker/compose-cli/api/config"
+	"github.com/docker/compose-cli/config"
 )
 
 // ConfigFlags are the global CLI flags
diff --git a/cli/main.go b/cli/main.go
index 5a772763..446d5046 100644
--- a/cli/main.go
+++ b/cli/main.go
@@ -32,10 +32,6 @@ import (
 	"github.com/sirupsen/logrus"
 	"github.com/spf13/cobra"
 
-	"github.com/docker/compose-cli/api/config"
-	apicontext "github.com/docker/compose-cli/api/context"
-	"github.com/docker/compose-cli/api/context/store"
-	"github.com/docker/compose-cli/api/errdefs"
 	"github.com/docker/compose-cli/cli/cmd"
 	"github.com/docker/compose-cli/cli/cmd/compose"
 	contextcmd "github.com/docker/compose-cli/cli/cmd/context"
@@ -43,9 +39,13 @@ import (
 	"github.com/docker/compose-cli/cli/cmd/logout"
 	"github.com/docker/compose-cli/cli/cmd/run"
 	"github.com/docker/compose-cli/cli/cmd/volume"
-	"github.com/docker/compose-cli/cli/metrics"
 	"github.com/docker/compose-cli/cli/mobycli"
 	cliopts "github.com/docker/compose-cli/cli/options"
+	"github.com/docker/compose-cli/config"
+	apicontext "github.com/docker/compose-cli/context"
+	"github.com/docker/compose-cli/context/store"
+	"github.com/docker/compose-cli/errdefs"
+	"github.com/docker/compose-cli/metrics"
 
 	// Backend registrations
 	_ "github.com/docker/compose-cli/aci"
diff --git a/cli/mobycli/exec.go b/cli/mobycli/exec.go
index e264e2cd..c46637ed 100644
--- a/cli/mobycli/exec.go
+++ b/cli/mobycli/exec.go
@@ -26,10 +26,10 @@ import (
 
 	"github.com/spf13/cobra"
 
-	apicontext "github.com/docker/compose-cli/api/context"
-	"github.com/docker/compose-cli/api/context/store"
-	"github.com/docker/compose-cli/cli/metrics"
 	"github.com/docker/compose-cli/cli/mobycli/resolvepath"
+	apicontext "github.com/docker/compose-cli/context"
+	"github.com/docker/compose-cli/context/store"
+	"github.com/docker/compose-cli/metrics"
 )
 
 var delegatedContextTypes = []string{store.DefaultContextType}
diff --git a/cli/options/options.go b/cli/options/options.go
index 0d4aac18..f7575438 100644
--- a/cli/options/options.go
+++ b/cli/options/options.go
@@ -17,8 +17,8 @@
 package options
 
 import (
-	apicontext "github.com/docker/compose-cli/api/context"
 	cliconfig "github.com/docker/compose-cli/cli/config"
+	apicontext "github.com/docker/compose-cli/context"
 )
 
 // GlobalOpts contains the global CLI options
diff --git a/cli/options/run/opts.go b/cli/options/run/opts.go
index 3388d673..ea95be63 100644
--- a/cli/options/run/opts.go
+++ b/cli/options/run/opts.go
@@ -22,8 +22,6 @@ import (
 	"strings"
 	"time"
 
-	"github.com/docker/compose-cli/utils"
-
 	"github.com/compose-spec/compose-go/types"
 	"github.com/containerd/containerd/platforms"
 	"github.com/docker/cli/opts"
@@ -32,6 +30,7 @@ import (
 	specs "github.com/opencontainers/image-spec/specs-go/v1"
 
 	"github.com/docker/compose-cli/api/containers"
+	"github.com/docker/compose-cli/formatter"
 )
 
 // Opts contain run command options
@@ -42,7 +41,7 @@ type Opts struct {
 	Labels                 []string
 	Volumes                []string
 	Cpus                   float64
-	Memory                 utils.MemBytes
+	Memory                 formatter.MemBytes
 	Detach                 bool
 	Environment            []string
 	EnvironmentFiles       []string
diff --git a/api/config/config.go b/config/config.go
similarity index 98%
rename from api/config/config.go
rename to config/config.go
index b771ded8..1ea0e43b 100644
--- a/api/config/config.go
+++ b/config/config.go
@@ -25,7 +25,7 @@ import (
 
 	"github.com/pkg/errors"
 
-	"github.com/docker/compose-cli/api/context/store"
+	"github.com/docker/compose-cli/context/store"
 )
 
 type dirKey struct{}
diff --git a/api/config/config_test.go b/config/config_test.go
similarity index 100%
rename from api/config/config_test.go
rename to config/config_test.go
diff --git a/api/config/keys.go b/config/keys.go
similarity index 100%
rename from api/config/keys.go
rename to config/keys.go
diff --git a/api/cloud/api.go b/context/cloud/api.go
similarity index 97%
rename from api/cloud/api.go
rename to context/cloud/api.go
index aa8b7773..475599d3 100644
--- a/api/cloud/api.go
+++ b/context/cloud/api.go
@@ -19,7 +19,7 @@ package cloud
 import (
 	"context"
 
-	"github.com/docker/compose-cli/api/errdefs"
+	"github.com/docker/compose-cli/errdefs"
 )
 
 // Service cloud specific services
diff --git a/api/context/context.go b/context/context.go
similarity index 100%
rename from api/context/context.go
rename to context/context.go
diff --git a/api/context/flags.go b/context/flags.go
similarity index 100%
rename from api/context/flags.go
rename to context/flags.go
diff --git a/api/context/store/contextmetadata.go b/context/store/contextmetadata.go
similarity index 100%
rename from api/context/store/contextmetadata.go
rename to context/store/contextmetadata.go
diff --git a/api/context/store/contextmetadata_test.go b/context/store/contextmetadata_test.go
similarity index 100%
rename from api/context/store/contextmetadata_test.go
rename to context/store/contextmetadata_test.go
diff --git a/api/context/store/store.go b/context/store/store.go
similarity index 99%
rename from api/context/store/store.go
rename to context/store/store.go
index 78b512ea..917f282e 100644
--- a/api/context/store/store.go
+++ b/context/store/store.go
@@ -28,7 +28,7 @@ import (
 	"github.com/opencontainers/go-digest"
 	"github.com/pkg/errors"
 
-	"github.com/docker/compose-cli/api/errdefs"
+	"github.com/docker/compose-cli/errdefs"
 )
 
 const (
diff --git a/api/context/store/storedefault.go b/context/store/storedefault.go
similarity index 100%
rename from api/context/store/storedefault.go
rename to context/store/storedefault.go
diff --git a/docs/architecture.md b/docs/architecture.md
index e21bb3d6..e6910be1 100644
--- a/docs/architecture.md
+++ b/docs/architecture.md
@@ -23,6 +23,6 @@ What follows is a list of useful links to help navigate the code:
   * An example backend can be found in [`example/`](../example)
 * The API is defined by protobufs that can be found in [`protos/`](../protos)
 * The API server is in [`server/`](../server)
-* The context management and interface can be found in [`context/`](../api/context)
+* The context management and interface can be found in [`context/`](../context)
 * The Node SDK is autogenerated (except for default endpoints managed by Docker Desktop), and can be found in
   [`docker/node-sdk`](https://github.com/docker/node-sdk)
\ No newline at end of file
diff --git a/ecs/aws.go b/ecs/aws.go
index 80234b38..83156b22 100644
--- a/ecs/aws.go
+++ b/ecs/aws.go
@@ -21,7 +21,6 @@ import (
 
 	"github.com/aws/aws-sdk-go/service/cloudformation"
 	"github.com/aws/aws-sdk-go/service/ecs"
-
 	"github.com/docker/compose-cli/api/compose"
 	"github.com/docker/compose-cli/api/secrets"
 )
diff --git a/ecs/awsResources.go b/ecs/awsResources.go
index 71d9d477..0ab60146 100644
--- a/ecs/awsResources.go
+++ b/ecs/awsResources.go
@@ -23,7 +23,7 @@ import (
 	"strings"
 
 	"github.com/docker/compose-cli/api/compose"
-	"github.com/docker/compose-cli/api/errdefs"
+	"github.com/docker/compose-cli/errdefs"
 
 	"github.com/aws/aws-sdk-go/aws/arn"
 	"github.com/aws/aws-sdk-go/service/elbv2"
diff --git a/ecs/aws_mock.go b/ecs/aws_mock.go
index 1ed432d1..6d7ef4f6 100644
--- a/ecs/aws_mock.go
+++ b/ecs/aws_mock.go
@@ -6,14 +6,12 @@ package ecs
 
 import (
 	context "context"
-	reflect "reflect"
-
 	cloudformation "github.com/aws/aws-sdk-go/service/cloudformation"
 	ecs "github.com/aws/aws-sdk-go/service/ecs"
-	gomock "github.com/golang/mock/gomock"
-
 	compose "github.com/docker/compose-cli/api/compose"
 	secrets "github.com/docker/compose-cli/api/secrets"
+	gomock "github.com/golang/mock/gomock"
+	reflect "reflect"
 )
 
 // MockAPI is a mock of API interface
diff --git a/ecs/backend.go b/ecs/backend.go
index bb075b4c..3831ac45 100644
--- a/ecs/backend.go
+++ b/ecs/backend.go
@@ -20,17 +20,16 @@ import (
 	"context"
 	"fmt"
 
-	"github.com/docker/compose-cli/api/backend"
-
-	"github.com/docker/compose-cli/api/cloud"
 	"github.com/docker/compose-cli/api/compose"
 	"github.com/docker/compose-cli/api/containers"
-	apicontext "github.com/docker/compose-cli/api/context"
-	"github.com/docker/compose-cli/api/context/store"
-	"github.com/docker/compose-cli/api/errdefs"
 	"github.com/docker/compose-cli/api/resources"
 	"github.com/docker/compose-cli/api/secrets"
 	"github.com/docker/compose-cli/api/volumes"
+	"github.com/docker/compose-cli/backend"
+	apicontext "github.com/docker/compose-cli/context"
+	"github.com/docker/compose-cli/context/cloud"
+	"github.com/docker/compose-cli/context/store"
+	"github.com/docker/compose-cli/errdefs"
 
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/aws/session"
diff --git a/ecs/cloudformation.go b/ecs/cloudformation.go
index afb50358..d8f6e12d 100644
--- a/ecs/cloudformation.go
+++ b/ecs/cloudformation.go
@@ -24,7 +24,7 @@ import (
 	"strings"
 
 	"github.com/docker/compose-cli/api/compose"
-	"github.com/docker/compose-cli/api/config"
+	"github.com/docker/compose-cli/config"
 
 	ecsapi "github.com/aws/aws-sdk-go/service/ecs"
 	"github.com/aws/aws-sdk-go/service/elbv2"
diff --git a/ecs/context.go b/ecs/context.go
index e1f43f3e..8c76635c 100644
--- a/ecs/context.go
+++ b/ecs/context.go
@@ -24,9 +24,9 @@ import (
 	"sort"
 	"strings"
 
-	"github.com/docker/compose-cli/api/context/store"
-	"github.com/docker/compose-cli/api/errdefs"
-	"github.com/docker/compose-cli/utils/prompt"
+	"github.com/docker/compose-cli/context/store"
+	"github.com/docker/compose-cli/errdefs"
+	"github.com/docker/compose-cli/prompt"
 
 	"github.com/AlecAivazis/survey/v2/terminal"
 	"github.com/aws/aws-sdk-go/aws"
diff --git a/ecs/down.go b/ecs/down.go
index 95982989..047613ad 100644
--- a/ecs/down.go
+++ b/ecs/down.go
@@ -21,7 +21,7 @@ import (
 
 	"github.com/docker/compose-cli/api/compose"
 
-	"github.com/docker/compose-cli/api/progress"
+	"github.com/docker/compose-cli/progress"
 )
 
 func (b *ecsAPIService) Down(ctx context.Context, projectName string, options compose.DownOptions) error {
diff --git a/ecs/local/backend.go b/ecs/local/backend.go
index 7d80380d..952c48ca 100644
--- a/ecs/local/backend.go
+++ b/ecs/local/backend.go
@@ -23,14 +23,14 @@ import (
 
 	"github.com/docker/docker/client"
 
-	"github.com/docker/compose-cli/api/backend"
-	"github.com/docker/compose-cli/api/cloud"
 	"github.com/docker/compose-cli/api/compose"
 	"github.com/docker/compose-cli/api/containers"
-	"github.com/docker/compose-cli/api/context/store"
 	"github.com/docker/compose-cli/api/resources"
 	"github.com/docker/compose-cli/api/secrets"
 	"github.com/docker/compose-cli/api/volumes"
+	"github.com/docker/compose-cli/backend"
+	"github.com/docker/compose-cli/context/cloud"
+	"github.com/docker/compose-cli/context/store"
 )
 
 const backendType = store.EcsLocalSimulationContextType
diff --git a/ecs/local/compose.go b/ecs/local/compose.go
index b20741af..d5c9728f 100644
--- a/ecs/local/compose.go
+++ b/ecs/local/compose.go
@@ -25,11 +25,10 @@ import (
 
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/compose-spec/compose-go/types"
+	"github.com/docker/compose-cli/api/compose"
+	"github.com/docker/compose-cli/errdefs"
 	"github.com/pkg/errors"
 	"github.com/sanathkr/go-yaml"
-
-	"github.com/docker/compose-cli/api/compose"
-	"github.com/docker/compose-cli/api/errdefs"
 )
 
 func (e ecsLocalSimulation) Build(ctx context.Context, project *types.Project) error {
diff --git a/ecs/local/context.go b/ecs/local/context.go
index c623a0f9..ebd71c22 100644
--- a/ecs/local/context.go
+++ b/ecs/local/context.go
@@ -19,9 +19,9 @@ package local
 import (
 	"context"
 
-	"github.com/docker/compose-cli/api/cloud"
-	"github.com/docker/compose-cli/api/errdefs"
+	"github.com/docker/compose-cli/context/cloud"
 	"github.com/docker/compose-cli/ecs"
+	"github.com/docker/compose-cli/errdefs"
 )
 
 var _ cloud.Service = ecsLocalSimulation{}
diff --git a/ecs/run.go b/ecs/run.go
index 4699ec41..6e3f8bf9 100644
--- a/ecs/run.go
+++ b/ecs/run.go
@@ -20,9 +20,8 @@ import (
 	"context"
 
 	"github.com/compose-spec/compose-go/types"
-
 	"github.com/docker/compose-cli/api/compose"
-	"github.com/docker/compose-cli/api/errdefs"
+	"github.com/docker/compose-cli/errdefs"
 )
 
 func (b *ecsAPIService) RunOneOffContainer(ctx context.Context, project *types.Project, opts compose.RunOptions) error {
diff --git a/ecs/sdk.go b/ecs/sdk.go
index 92a2b3f2..1c9fa57d 100644
--- a/ecs/sdk.go
+++ b/ecs/sdk.go
@@ -25,8 +25,8 @@ import (
 	"time"
 
 	"github.com/docker/compose-cli/api/compose"
-	"github.com/docker/compose-cli/api/errdefs"
 	"github.com/docker/compose-cli/api/secrets"
+	"github.com/docker/compose-cli/errdefs"
 	"github.com/docker/compose-cli/internal"
 
 	"github.com/aws/aws-sdk-go/aws"
diff --git a/ecs/tags.go b/ecs/tags.go
index 6e7206ee..01dead2f 100644
--- a/ecs/tags.go
+++ b/ecs/tags.go
@@ -19,7 +19,6 @@ package ecs
 import (
 	"github.com/awslabs/goformation/v4/cloudformation/tags"
 	"github.com/compose-spec/compose-go/types"
-
 	"github.com/docker/compose-cli/api/compose"
 )
 
diff --git a/ecs/up.go b/ecs/up.go
index 6a71b1bf..a47f7adb 100644
--- a/ecs/up.go
+++ b/ecs/up.go
@@ -26,7 +26,7 @@ import (
 	"github.com/sirupsen/logrus"
 
 	"github.com/docker/compose-cli/api/compose"
-	"github.com/docker/compose-cli/api/errdefs"
+	"github.com/docker/compose-cli/errdefs"
 
 	"github.com/compose-spec/compose-go/types"
 )
diff --git a/ecs/volumes.go b/ecs/volumes.go
index df1a296f..81aefe73 100644
--- a/ecs/volumes.go
+++ b/ecs/volumes.go
@@ -21,8 +21,8 @@ import (
 	"fmt"
 
 	"github.com/docker/compose-cli/api/compose"
-	"github.com/docker/compose-cli/api/errdefs"
 	"github.com/docker/compose-cli/api/volumes"
+	"github.com/docker/compose-cli/errdefs"
 
 	"github.com/awslabs/goformation/v4/cloudformation"
 	"github.com/awslabs/goformation/v4/cloudformation/efs"
diff --git a/ecs/wait.go b/ecs/wait.go
index 3d3e7069..183c5954 100644
--- a/ecs/wait.go
+++ b/ecs/wait.go
@@ -26,7 +26,7 @@ import (
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/iancoleman/strcase"
 
-	"github.com/docker/compose-cli/api/progress"
+	"github.com/docker/compose-cli/progress"
 )
 
 func (b *ecsAPIService) WaitStackCompletion(ctx context.Context, name string, operation int, ignored ...string) error { //nolint:gocyclo
diff --git a/api/errdefs/errors.go b/errdefs/errors.go
similarity index 100%
rename from api/errdefs/errors.go
rename to errdefs/errors.go
diff --git a/api/errdefs/errors_test.go b/errdefs/errors_test.go
similarity index 100%
rename from api/errdefs/errors_test.go
rename to errdefs/errors_test.go
diff --git a/example/backend.go b/example/backend.go
index 94427fda..58cf7a6c 100644
--- a/example/backend.go
+++ b/example/backend.go
@@ -23,14 +23,14 @@ import (
 	"errors"
 	"fmt"
 
-	"github.com/docker/compose-cli/api/backend"
-	"github.com/docker/compose-cli/api/cloud"
 	"github.com/docker/compose-cli/api/compose"
 	"github.com/docker/compose-cli/api/containers"
-	"github.com/docker/compose-cli/api/errdefs"
 	"github.com/docker/compose-cli/api/resources"
 	"github.com/docker/compose-cli/api/secrets"
 	"github.com/docker/compose-cli/api/volumes"
+	"github.com/docker/compose-cli/backend"
+	"github.com/docker/compose-cli/context/cloud"
+	"github.com/docker/compose-cli/errdefs"
 
 	"github.com/compose-spec/compose-go/types"
 )
diff --git a/cli/formatter/colors.go b/formatter/colors.go
similarity index 100%
rename from cli/formatter/colors.go
rename to formatter/colors.go
diff --git a/cli/formatter/consts.go b/formatter/consts.go
similarity index 100%
rename from cli/formatter/consts.go
rename to formatter/consts.go
diff --git a/cli/formatter/formatter.go b/formatter/formatter.go
similarity index 97%
rename from cli/formatter/formatter.go
rename to formatter/formatter.go
index b1472024..4f8df536 100644
--- a/cli/formatter/formatter.go
+++ b/formatter/formatter.go
@@ -24,7 +24,7 @@ import (
 
 	"github.com/pkg/errors"
 
-	"github.com/docker/compose-cli/api/errdefs"
+	"github.com/docker/compose-cli/errdefs"
 )
 
 // Print prints formatted lists in different formats
diff --git a/cli/formatter/formatter_test.go b/formatter/formatter_test.go
similarity index 100%
rename from cli/formatter/formatter_test.go
rename to formatter/formatter_test.go
diff --git a/cli/formatter/json.go b/formatter/json.go
similarity index 100%
rename from cli/formatter/json.go
rename to formatter/json.go
diff --git a/cli/formatter/logs.go b/formatter/logs.go
similarity index 100%
rename from cli/formatter/logs.go
rename to formatter/logs.go
diff --git a/cli/formatter/pretty.go b/formatter/pretty.go
similarity index 100%
rename from cli/formatter/pretty.go
rename to formatter/pretty.go
diff --git a/utils/units.go b/formatter/units.go
similarity index 98%
rename from utils/units.go
rename to formatter/units.go
index 401dddbe..d26902cd 100644
--- a/utils/units.go
+++ b/formatter/units.go
@@ -14,7 +14,7 @@
    limitations under the License.
 */
 
-package utils
+package formatter
 
 import (
 	"github.com/docker/go-units"
diff --git a/import-restrictions.yaml b/import-restrictions.yaml
index 6e03d903..7b344557 100644
--- a/import-restrictions.yaml
+++ b/import-restrictions.yaml
@@ -5,21 +5,29 @@
     - github.com/docker/compose-cli/ecs
     - github.com/docker/compose-cli/example
     - github.com/docker/compose-cli/local
+    - github.com/docker/compose-cli/metrics
+    - github.com/docker/compose-cli/server
 - path: ./ecs
   forbiddenImports:
     - github.com/docker/compose-cli/aci
     - github.com/docker/compose-cli/cli
     - github.com/docker/compose-cli/example
     - github.com/docker/compose-cli/local
+    - github.com/docker/compose-cli/metrics
+    - github.com/docker/compose-cli/server
 - path: ./example
   forbiddenImports:
     - github.com/docker/compose-cli/aci
     - github.com/docker/compose-cli/cli
     - github.com/docker/compose-cli/ecs
     - github.com/docker/compose-cli/local
+    - github.com/docker/compose-cli/metrics
+    - github.com/docker/compose-cli/server
 - path: ./local
   forbiddenImports:
     - github.com/docker/compose-cli/aci
     - github.com/docker/compose-cli/cli
     - github.com/docker/compose-cli/ecs
     - github.com/docker/compose-cli/example
+    - github.com/docker/compose-cli/metrics
+    - github.com/docker/compose-cli/server
diff --git a/local/backend.go b/local/backend.go
index 0e5ea277..8e25d8b5 100644
--- a/local/backend.go
+++ b/local/backend.go
@@ -21,13 +21,13 @@ import (
 
 	"github.com/docker/docker/client"
 
-	"github.com/docker/compose-cli/api/backend"
-	"github.com/docker/compose-cli/api/cloud"
 	"github.com/docker/compose-cli/api/compose"
 	"github.com/docker/compose-cli/api/containers"
 	"github.com/docker/compose-cli/api/resources"
 	"github.com/docker/compose-cli/api/secrets"
 	"github.com/docker/compose-cli/api/volumes"
+	"github.com/docker/compose-cli/backend"
+	"github.com/docker/compose-cli/context/cloud"
 	local_compose "github.com/docker/compose-cli/local/compose"
 )
 
diff --git a/local/compose/compose.go b/local/compose/compose.go
index 894db8fe..88cb6fc4 100644
--- a/local/compose/compose.go
+++ b/local/compose/compose.go
@@ -29,7 +29,7 @@ import (
 	"github.com/docker/docker/client"
 	"github.com/sanathkr/go-yaml"
 
-	errdefs2 "github.com/docker/compose-cli/api/errdefs"
+	errdefs2 "github.com/docker/compose-cli/errdefs"
 )
 
 // NewComposeService create a local implementation of the compose.Service API
diff --git a/local/compose/convergence.go b/local/compose/convergence.go
index f5f98e2a..e3f46e61 100644
--- a/local/compose/convergence.go
+++ b/local/compose/convergence.go
@@ -28,8 +28,8 @@ import (
 	"github.com/docker/docker/api/types/network"
 	"golang.org/x/sync/errgroup"
 
-	"github.com/docker/compose-cli/api/progress"
 	status "github.com/docker/compose-cli/local/moby"
+	"github.com/docker/compose-cli/progress"
 )
 
 const (
@@ -93,7 +93,6 @@ func (s *composeService) ensureService(ctx context.Context, observedState Contai
 	}
 
 	for _, container := range actual {
-		container := container
 		name := getCanonicalContainerName(container)
 
 		diverged := container.Labels[configHashLabel] != expected
@@ -251,7 +250,7 @@ func (s *composeService) restartContainer(ctx context.Context, container moby.Co
 }
 
 func (s *composeService) createMobyContainer(ctx context.Context, project *types.Project, service types.ServiceConfig, name string, number int, container *moby.Container, autoRemove bool) error {
-	containerConfig, hostConfig, networkingConfig, err := getCreateOptions(project, service, number, container, autoRemove)
+	containerConfig, hostConfig, networkingConfig, err := s.getCreateOptions(ctx, project, service, number, container, autoRemove)
 	if err != nil {
 		return err
 	}
diff --git a/local/compose/create.go b/local/compose/create.go
index 84ea697d..126ef212 100644
--- a/local/compose/create.go
+++ b/local/compose/create.go
@@ -38,8 +38,8 @@ import (
 	"golang.org/x/sync/errgroup"
 
 	"github.com/docker/compose-cli/api/compose"
-	"github.com/docker/compose-cli/api/progress"
 	convert "github.com/docker/compose-cli/local/moby"
+	"github.com/docker/compose-cli/progress"
 )
 
 func (s *composeService) Create(ctx context.Context, project *types.Project, opts compose.CreateOptions) error {
@@ -50,6 +50,11 @@ func (s *composeService) Create(ctx context.Context, project *types.Project, opt
 
 	prepareNetworks(project)
 
+	err = prepareVolumes(project)
+	if err != nil {
+		return err
+	}
+
 	if err := s.ensureNetworks(ctx, project.Networks); err != nil {
 		return err
 	}
@@ -91,6 +96,29 @@ func (s *composeService) Create(ctx context.Context, project *types.Project, opt
 	})
 }
 
+func prepareVolumes(p *types.Project) error {
+	for i := range p.Services {
+		volumesFrom, dependServices, err := getVolumesFrom(p, p.Services[i].VolumesFrom)
+		if err != nil {
+			return err
+		}
+		p.Services[i].VolumesFrom = volumesFrom
+		if len(dependServices) > 0 {
+			if p.Services[i].DependsOn == nil {
+				p.Services[i].DependsOn = make(types.DependsOnConfig, len(dependServices))
+			}
+			for _, service := range p.Services {
+				if contains(dependServices, service.Name) {
+					p.Services[i].DependsOn[service.Name] = types.ServiceDependency{
+						Condition: types.ServiceConditionStarted,
+					}
+				}
+			}
+		}
+	}
+	return nil
+}
+
 func prepareNetworks(project *types.Project) {
 	for k, network := range project.Networks {
 		network.Labels = network.Labels.Add(networkLabel, k)
@@ -131,21 +159,23 @@ func getImageName(service types.ServiceConfig, projectName string) string {
 	return imageName
 }
 
-func getCreateOptions(p *types.Project, s types.ServiceConfig, number int, inherit *moby.Container, autoRemove bool) (*container.Config, *container.HostConfig, *network.NetworkingConfig, error) {
-	hash, err := jsonHash(s)
+func (s *composeService) getCreateOptions(ctx context.Context, p *types.Project, service types.ServiceConfig, number int, inherit *moby.Container,
+	autoRemove bool) (*container.Config, *container.HostConfig, *network.NetworkingConfig, error) {
+
+	hash, err := jsonHash(service)
 	if err != nil {
 		return nil, nil, nil, err
 	}
 
 	labels := map[string]string{}
-	for k, v := range s.Labels {
+	for k, v := range service.Labels {
 		labels[k] = v
 	}
 
 	labels[projectLabel] = p.Name
-	labels[serviceLabel] = s.Name
+	labels[serviceLabel] = service.Name
 	labels[versionLabel] = ComposeVersion
-	if _, ok := s.Labels[oneoffLabel]; !ok {
+	if _, ok := service.Labels[oneoffLabel]; !ok {
 		labels[oneoffLabel] = "False"
 	}
 	labels[configHashLabel] = hash
@@ -157,24 +187,29 @@ func getCreateOptions(p *types.Project, s types.ServiceConfig, number int, inher
 		runCmd     strslice.StrSlice
 		entrypoint strslice.StrSlice
 	)
-	if len(s.Command) > 0 {
-		runCmd = strslice.StrSlice(s.Command)
+	if len(service.Command) > 0 {
+		runCmd = strslice.StrSlice(service.Command)
 	}
-	if len(s.Entrypoint) > 0 {
-		entrypoint = strslice.StrSlice(s.Entrypoint)
+	if len(service.Entrypoint) > 0 {
+		entrypoint = strslice.StrSlice(service.Entrypoint)
 	}
 
 	var (
-		tty         = s.Tty
-		stdinOpen   = s.StdinOpen
+		tty         = service.Tty
+		stdinOpen   = service.StdinOpen
 		attachStdin = false
 	)
 
+	volumeMounts, binds, mounts, err := s.buildContainerVolumes(ctx, *p, service, inherit)
+	if err != nil {
+		return nil, nil, nil, err
+	}
+
 	containerConfig := container.Config{
-		Hostname:        s.Hostname,
-		Domainname:      s.DomainName,
-		User:            s.User,
-		ExposedPorts:    buildContainerPorts(s),
+		Hostname:        service.Hostname,
+		Domainname:      service.DomainName,
+		User:            service.User,
+		ExposedPorts:    buildContainerPorts(service),
 		Tty:             tty,
 		OpenStdin:       stdinOpen,
 		StdinOnce:       true,
@@ -182,42 +217,42 @@ func getCreateOptions(p *types.Project, s types.ServiceConfig, number int, inher
 		AttachStderr:    true,
 		AttachStdout:    true,
 		Cmd:             runCmd,
-		Image:           getImageName(s, p.Name),
-		WorkingDir:      s.WorkingDir,
+		Image:           getImageName(service, p.Name),
+		WorkingDir:      service.WorkingDir,
 		Entrypoint:      entrypoint,
-		NetworkDisabled: s.NetworkMode == "disabled",
-		MacAddress:      s.MacAddress,
+		NetworkDisabled: service.NetworkMode == "disabled",
+		MacAddress:      service.MacAddress,
 		Labels:          labels,
-		StopSignal:      s.StopSignal,
-		Env:             convert.ToMobyEnv(s.Environment),
-		Healthcheck:     convert.ToMobyHealthCheck(s.HealthCheck),
-		// Volumes:         // FIXME unclear to me the overlap with HostConfig.Mounts
-		StopTimeout: convert.ToSeconds(s.StopGracePeriod),
-	}
+		StopSignal:      service.StopSignal,
+		Env:             convert.ToMobyEnv(service.Environment),
+		Healthcheck:     convert.ToMobyHealthCheck(service.HealthCheck),
+		Volumes:         volumeMounts,
 
-	mountOptions, err := buildContainerMountOptions(*p, s, inherit)
-	if err != nil {
-		return nil, nil, nil, err
+		StopTimeout: convert.ToSeconds(service.StopGracePeriod),
 	}
-	bindings := buildContainerBindingOptions(s)
 
-	resources := getDeployResources(s)
-	networkMode := getNetworkMode(p, s)
+	portBindings := buildContainerPortBindingOptions(service)
+
+	resources := getDeployResources(service)
+	networkMode := getNetworkMode(p, service)
 	hostConfig := container.HostConfig{
 		AutoRemove:     autoRemove,
-		Mounts:         mountOptions,
-		CapAdd:         strslice.StrSlice(s.CapAdd),
-		CapDrop:        strslice.StrSlice(s.CapDrop),
+		Binds:          binds,
+		Mounts:         mounts,
+		CapAdd:         strslice.StrSlice(service.CapAdd),
+		CapDrop:        strslice.StrSlice(service.CapDrop),
 		NetworkMode:    networkMode,
-		Init:           s.Init,
-		ReadonlyRootfs: s.ReadOnly,
+		Init:           service.Init,
+		ReadonlyRootfs: service.ReadOnly,
 		// ShmSize: , TODO
-		Sysctls:      s.Sysctls,
-		PortBindings: bindings,
+		Sysctls:      service.Sysctls,
+		PortBindings: portBindings,
 		Resources:    resources,
+		VolumeDriver: service.VolumeDriver,
+		VolumesFrom:  service.VolumesFrom,
 	}
 
-	networkConfig := buildDefaultNetworkConfig(s, networkMode, getContainerName(p.Name, s, number))
+	networkConfig := buildDefaultNetworkConfig(service, networkMode, getContainerName(p.Name, service, number))
 	return &containerConfig, &hostConfig, networkConfig, nil
 }
 
@@ -253,7 +288,7 @@ func buildContainerPorts(s types.ServiceConfig) nat.PortSet {
 	return ports
 }
 
-func buildContainerBindingOptions(s types.ServiceConfig) nat.PortMap {
+func buildContainerPortBindingOptions(s types.ServiceConfig) nat.PortMap {
 	bindings := nat.PortMap{}
 	for _, port := range s.Ports {
 		p := nat.Port(fmt.Sprintf("%d/%s", port.Target, port.Protocol))
@@ -268,9 +303,71 @@ func buildContainerBindingOptions(s types.ServiceConfig) nat.PortMap {
 	return bindings
 }
 
-func buildContainerMountOptions(p types.Project, s types.ServiceConfig, inherit *moby.Container) ([]mount.Mount, error) {
-	mounts := []mount.Mount{}
-	var inherited []string
+func getVolumesFrom(project *types.Project, volumesFrom []string) ([]string, []string, error) {
+	var volumes = []string{}
+	var services = []string{}
+	// parse volumes_from
+	if len(volumesFrom) == 0 {
+		return volumes, services, nil
+	}
+	for _, vol := range volumesFrom {
+		spec := strings.Split(vol, ":")
+		if spec[0] == "container" {
+			volumes = append(volumes, strings.Join(spec[1:], ":"))
+			continue
+		}
+		serviceName := spec[0]
+		services = append(services, serviceName)
+		service, err := project.GetService(serviceName)
+		if err != nil {
+			return nil, nil, err
+		}
+
+		firstContainer := getContainerName(project.Name, service, 1)
+		v := fmt.Sprintf("%s:%s", firstContainer, strings.Join(spec[1:], ":"))
+		volumes = append(volumes, v)
+	}
+	return volumes, services, nil
+
+}
+
+func (s *composeService) buildContainerVolumes(ctx context.Context, p types.Project, service types.ServiceConfig,
+	inherit *moby.Container) (map[string]struct{}, []string, []mount.Mount, error) {
+	var mounts = []mount.Mount{}
+
+	image := getImageName(service, p.Name)
+	imgInspect, _, err := s.apiClient.ImageInspectWithRaw(ctx, image)
+	if err != nil {
+		return nil, nil, nil, err
+	}
+
+	mountOptions, err := buildContainerMountOptions(p, service, imgInspect, inherit)
+	if err != nil {
+		return nil, nil, nil, err
+	}
+
+	// filter binds and volumes mount targets
+	volumeMounts := map[string]struct{}{}
+	binds := []string{}
+	for _, m := range mountOptions {
+
+		if m.Type == mount.TypeVolume {
+			volumeMounts[m.Target] = struct{}{}
+			if m.Source != "" {
+				binds = append(binds, fmt.Sprintf("%s:%s:rw", m.Source, m.Target))
+			}
+		}
+	}
+	for _, m := range mountOptions {
+		if m.Type == mount.TypeBind || m.Type == mount.TypeTmpfs {
+			mounts = append(mounts, m)
+		}
+	}
+	return volumeMounts, binds, mounts, nil
+}
+
+func buildContainerMountOptions(p types.Project, s types.ServiceConfig, img moby.ImageInspect, inherit *moby.Container) ([]mount.Mount, error) {
+	var mounts = map[string]mount.Mount{}
 	if inherit != nil {
 		for _, m := range inherit.Mounts {
 			if m.Type == "tmpfs" {
@@ -280,27 +377,56 @@ func buildContainerMountOptions(p types.Project, s types.ServiceConfig, inherit
 			if m.Type == "volume" {
 				src = m.Name
 			}
-			mounts = append(mounts, mount.Mount{
+			mounts[m.Destination] = mount.Mount{
 				Type:     m.Type,
 				Source:   src,
 				Target:   m.Destination,
 				ReadOnly: !m.RW,
-			})
-			inherited = append(inherited, m.Destination)
+			}
 		}
 	}
+	if img.ContainerConfig != nil {
+		for k := range img.ContainerConfig.Volumes {
+			mount, err := buildMount(p, types.ServiceVolumeConfig{
+				Type:   types.VolumeTypeVolume,
+				Target: k,
+			})
+			if err != nil {
+				return nil, err
+			}
+			mounts[k] = mount
 
-	for _, v := range s.Volumes {
-		if contains(inherited, v.Target) {
-			continue
 		}
+	}
+	for _, v := range s.Volumes {
 		mount, err := buildMount(p, v)
 		if err != nil {
 			return nil, err
 		}
-		mounts = append(mounts, mount)
+		mounts[mount.Target] = mount
+	}
+
+	secrets, err := buildContainerSecretMounts(p, s)
+	if err != nil {
+		return nil, err
+	}
+	for _, s := range secrets {
+		if _, found := mounts[s.Target]; found {
+			continue
+		}
+		mounts[s.Target] = s
 	}
 
+	values := make([]mount.Mount, 0, len(mounts))
+	for _, v := range mounts {
+		values = append(values, v)
+	}
+	return values, nil
+}
+
+func buildContainerSecretMounts(p types.Project, s types.ServiceConfig) ([]mount.Mount, error) {
+	var mounts = map[string]mount.Mount{}
+
 	secretsDir := "/run/secrets"
 	for _, secret := range s.Secrets {
 		target := secret.Target
@@ -315,27 +441,22 @@ func buildContainerMountOptions(p types.Project, s types.ServiceConfig, inherit
 			return nil, fmt.Errorf("unsupported external secret %s", definedSecret.Name)
 		}
 
-		if contains(inherited, target) {
-			// remove inherited mount
-			pos := indexOf(inherited, target)
-			if pos >= 0 {
-				mounts = append(mounts[:pos], mounts[pos+1])
-				inherited = append(inherited[:pos], inherited[pos+1])
-			}
-		}
-
 		mount, err := buildMount(p, types.ServiceVolumeConfig{
-			Type:   types.VolumeTypeBind,
-			Source: definedSecret.File,
-			Target: target,
+			Type:     types.VolumeTypeBind,
+			Source:   definedSecret.File,
+			Target:   target,
+			ReadOnly: true,
 		})
 		if err != nil {
 			return nil, err
 		}
-		mounts = append(mounts, mount)
+		mounts[target] = mount
 	}
-
-	return mounts, nil
+	values := make([]mount.Mount, 0, len(mounts))
+	for _, v := range mounts {
+		values = append(values, v)
+	}
+	return values, nil
 }
 
 func buildMount(project types.Project, volume types.ServiceVolumeConfig) (mount.Mount, error) {
@@ -349,10 +470,14 @@ func buildMount(project types.Project, volume types.ServiceVolumeConfig) (mount.
 		}
 	}
 	if volume.Type == types.VolumeTypeVolume {
-		pVolume, ok := project.Volumes[volume.Source]
-		if ok {
-			source = pVolume.Name
+		if volume.Source != "" {
+
+			pVolume, ok := project.Volumes[volume.Source]
+			if ok {
+				source = pVolume.Name
+			}
 		}
+
 	}
 
 	return mount.Mount{
diff --git a/local/compose/down.go b/local/compose/down.go
index 4bfcbd32..bd699ae6 100644
--- a/local/compose/down.go
+++ b/local/compose/down.go
@@ -23,7 +23,7 @@ import (
 
 	"github.com/docker/compose-cli/api/compose"
 
-	"github.com/docker/compose-cli/api/progress"
+	"github.com/docker/compose-cli/progress"
 
 	"github.com/compose-spec/compose-go/cli"
 	"github.com/compose-spec/compose-go/types"
@@ -36,24 +36,21 @@ func (s *composeService) Down(ctx context.Context, projectName string, options c
 	eg, _ := errgroup.WithContext(ctx)
 	w := progress.ContextWriter(ctx)
 
-	if options.Project == nil {
-		project, err := s.projectFromContainerLabels(ctx, projectName)
-		if err != nil {
-			return err
-		}
-		options.Project = project
+	project, err := s.projectFromContainerLabels(ctx, projectName)
+	if err != nil {
+		return err
 	}
 
 	var containers Containers
-	containers, err := s.apiClient.ContainerList(ctx, moby.ContainerListOptions{
-		Filters: filters.NewArgs(projectFilter(options.Project.Name)),
+	containers, err = s.apiClient.ContainerList(ctx, moby.ContainerListOptions{
+		Filters: filters.NewArgs(projectFilter(project.Name)),
 		All:     true,
 	})
 	if err != nil {
 		return err
 	}
 
-	err = InReverseDependencyOrder(ctx, options.Project, func(c context.Context, service types.ServiceConfig) error {
+	err = InReverseDependencyOrder(ctx, project, func(c context.Context, service types.ServiceConfig) error {
 		serviceContainers, others := containers.split(isService(service.Name))
 		s.removeContainers(ctx, w, eg, serviceContainers)
 		containers = others
diff --git a/local/compose/pull.go b/local/compose/pull.go
index caf75b08..133056cd 100644
--- a/local/compose/pull.go
+++ b/local/compose/pull.go
@@ -32,8 +32,8 @@ import (
 	"github.com/docker/docker/registry"
 	"golang.org/x/sync/errgroup"
 
-	"github.com/docker/compose-cli/api/config"
-	"github.com/docker/compose-cli/api/progress"
+	"github.com/docker/compose-cli/config"
+	"github.com/docker/compose-cli/progress"
 )
 
 func (s *composeService) Pull(ctx context.Context, project *types.Project) error {
diff --git a/local/compose/push.go b/local/compose/push.go
index 934b2e9e..351c1c01 100644
--- a/local/compose/push.go
+++ b/local/compose/push.go
@@ -25,8 +25,8 @@ import (
 
 	"github.com/docker/buildx/driver"
 
-	"github.com/docker/compose-cli/api/config"
-	"github.com/docker/compose-cli/api/progress"
+	"github.com/docker/compose-cli/config"
+	"github.com/docker/compose-cli/progress"
 
 	"github.com/compose-spec/compose-go/types"
 	cliconfig "github.com/docker/cli/cli/config"
diff --git a/local/compose/util.go b/local/compose/util.go
index b0af71ca..dd9cbbcf 100644
--- a/local/compose/util.go
+++ b/local/compose/util.go
@@ -38,12 +38,3 @@ func contains(slice []string, item string) bool {
 	}
 	return false
 }
-
-func indexOf(slice []string, item string) int {
-	for i, v := range slice {
-		if v == item {
-			return i
-		}
-	}
-	return -1
-}
diff --git a/local/containers.go b/local/containers.go
index e3e72d25..3c6d7e6b 100644
--- a/local/containers.go
+++ b/local/containers.go
@@ -34,7 +34,7 @@ import (
 	"github.com/pkg/errors"
 
 	"github.com/docker/compose-cli/api/containers"
-	"github.com/docker/compose-cli/api/errdefs"
+	"github.com/docker/compose-cli/errdefs"
 	"github.com/docker/compose-cli/local/moby"
 )
 
diff --git a/cli/metrics/client.go b/metrics/client.go
similarity index 100%
rename from cli/metrics/client.go
rename to metrics/client.go
diff --git a/cli/metrics/commands.go b/metrics/commands.go
similarity index 100%
rename from cli/metrics/commands.go
rename to metrics/commands.go
diff --git a/cli/metrics/conn_e2e.go b/metrics/conn_e2e.go
similarity index 100%
rename from cli/metrics/conn_e2e.go
rename to metrics/conn_e2e.go
diff --git a/cli/metrics/conn_other.go b/metrics/conn_other.go
similarity index 100%
rename from cli/metrics/conn_other.go
rename to metrics/conn_other.go
diff --git a/cli/metrics/conn_windows.go b/metrics/conn_windows.go
similarity index 100%
rename from cli/metrics/conn_windows.go
rename to metrics/conn_windows.go
diff --git a/cli/metrics/generatecommands/main.go b/metrics/generatecommands/main.go
similarity index 100%
rename from cli/metrics/generatecommands/main.go
rename to metrics/generatecommands/main.go
diff --git a/cli/metrics/metrics.go b/metrics/metrics.go
similarity index 100%
rename from cli/metrics/metrics.go
rename to metrics/metrics.go
diff --git a/cli/metrics/metrics_test.go b/metrics/metrics_test.go
similarity index 100%
rename from cli/metrics/metrics_test.go
rename to metrics/metrics_test.go
diff --git a/api/progress/event.go b/progress/event.go
similarity index 100%
rename from api/progress/event.go
rename to progress/event.go
diff --git a/api/progress/noop.go b/progress/noop.go
similarity index 100%
rename from api/progress/noop.go
rename to progress/noop.go
diff --git a/api/progress/plain.go b/progress/plain.go
similarity index 100%
rename from api/progress/plain.go
rename to progress/plain.go
diff --git a/api/progress/spinner.go b/progress/spinner.go
similarity index 100%
rename from api/progress/spinner.go
rename to progress/spinner.go
diff --git a/api/progress/tty.go b/progress/tty.go
similarity index 100%
rename from api/progress/tty.go
rename to progress/tty.go
diff --git a/api/progress/tty_test.go b/progress/tty_test.go
similarity index 100%
rename from api/progress/tty_test.go
rename to progress/tty_test.go
diff --git a/api/progress/writer.go b/progress/writer.go
similarity index 100%
rename from api/progress/writer.go
rename to progress/writer.go
diff --git a/api/progress/writer_test.go b/progress/writer_test.go
similarity index 100%
rename from api/progress/writer_test.go
rename to progress/writer_test.go
diff --git a/utils/prompt/prompt.go b/prompt/prompt.go
similarity index 100%
rename from utils/prompt/prompt.go
rename to prompt/prompt.go
diff --git a/utils/prompt/prompt_mock.go b/prompt/prompt_mock.go
similarity index 99%
rename from utils/prompt/prompt_mock.go
rename to prompt/prompt_mock.go
index b2f2ea7c..06886e0f 100644
--- a/utils/prompt/prompt_mock.go
+++ b/prompt/prompt_mock.go
@@ -5,9 +5,8 @@
 package prompt
 
 import (
-	reflect "reflect"
-
 	gomock "github.com/golang/mock/gomock"
+	reflect "reflect"
 )
 
 // MockUI is a mock of UI interface
diff --git a/cli/server/protos/compose/v1/compose.pb.go b/protos/compose/v1/compose.pb.go
similarity index 99%
rename from cli/server/protos/compose/v1/compose.pb.go
rename to protos/compose/v1/compose.pb.go
index 820be0d3..712fa40f 100644
--- a/cli/server/protos/compose/v1/compose.pb.go
+++ b/protos/compose/v1/compose.pb.go
@@ -23,15 +23,14 @@ package v1
 
 import (
 	context "context"
-	reflect "reflect"
-	sync "sync"
-
 	proto "github.com/golang/protobuf/proto"
 	grpc "google.golang.org/grpc"
 	codes "google.golang.org/grpc/codes"
 	status "google.golang.org/grpc/status"
 	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
 	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	reflect "reflect"
+	sync "sync"
 )
 
 const (
diff --git a/cli/server/protos/compose/v1/compose.proto b/protos/compose/v1/compose.proto
similarity index 95%
rename from cli/server/protos/compose/v1/compose.proto
rename to protos/compose/v1/compose.proto
index 2858af16..216a905e 100644
--- a/cli/server/protos/compose/v1/compose.proto
+++ b/protos/compose/v1/compose.proto
@@ -17,7 +17,7 @@ syntax = "proto3";
 
 package com.docker.api.protos.compose.v1;
 
-option go_package = "github.com/docker/compose-cli/cli/server/protos/compose/v1;v1";
+option go_package = "github.com/docker/compose-cli/protos/compose/v1;v1";
 
 service Compose {
   rpc Up(ComposeUpRequest) returns (ComposeUpResponse);
diff --git a/cli/server/protos/compose/v1/doc.go b/protos/compose/v1/doc.go
similarity index 100%
rename from cli/server/protos/compose/v1/doc.go
rename to protos/compose/v1/doc.go
diff --git a/cli/server/protos/containers/v1/containers.pb.go b/protos/containers/v1/containers.pb.go
similarity index 99%
rename from cli/server/protos/containers/v1/containers.pb.go
rename to protos/containers/v1/containers.pb.go
index 638a3780..2a34bde3 100644
--- a/cli/server/protos/containers/v1/containers.pb.go
+++ b/protos/containers/v1/containers.pb.go
@@ -23,15 +23,14 @@ package v1
 
 import (
 	context "context"
-	reflect "reflect"
-	sync "sync"
-
 	proto "github.com/golang/protobuf/proto"
 	grpc "google.golang.org/grpc"
 	codes "google.golang.org/grpc/codes"
 	status "google.golang.org/grpc/status"
 	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
 	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	reflect "reflect"
+	sync "sync"
 )
 
 const (
diff --git a/cli/server/protos/containers/v1/containers.proto b/protos/containers/v1/containers.proto
similarity index 97%
rename from cli/server/protos/containers/v1/containers.proto
rename to protos/containers/v1/containers.proto
index 86ea30fb..647b58b3 100644
--- a/cli/server/protos/containers/v1/containers.proto
+++ b/protos/containers/v1/containers.proto
@@ -17,7 +17,7 @@ syntax = "proto3";
 
 package com.docker.api.protos.containers.v1;
 
-option go_package = "github.com/docker/compose-cli/cli/server/protos/containers/v1;v1";
+option go_package = "github.com/docker/compose-cli/protos/containers/v1;v1";
 
 service Containers {
 	rpc List(ListRequest) returns (ListResponse);
diff --git a/cli/server/protos/containers/v1/doc.go b/protos/containers/v1/doc.go
similarity index 100%
rename from cli/server/protos/containers/v1/doc.go
rename to protos/containers/v1/doc.go
diff --git a/cli/server/protos/contexts/v1/contexts.pb.go b/protos/contexts/v1/contexts.pb.go
similarity index 99%
rename from cli/server/protos/contexts/v1/contexts.pb.go
rename to protos/contexts/v1/contexts.pb.go
index 201becdc..761a9589 100644
--- a/cli/server/protos/contexts/v1/contexts.pb.go
+++ b/protos/contexts/v1/contexts.pb.go
@@ -23,15 +23,14 @@ package v1
 
 import (
 	context "context"
-	reflect "reflect"
-	sync "sync"
-
 	proto "github.com/golang/protobuf/proto"
 	grpc "google.golang.org/grpc"
 	codes "google.golang.org/grpc/codes"
 	status "google.golang.org/grpc/status"
 	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
 	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	reflect "reflect"
+	sync "sync"
 )
 
 const (
diff --git a/cli/server/protos/contexts/v1/contexts.proto b/protos/contexts/v1/contexts.proto
similarity index 94%
rename from cli/server/protos/contexts/v1/contexts.proto
rename to protos/contexts/v1/contexts.proto
index a77239ca..2c4755cd 100644
--- a/cli/server/protos/contexts/v1/contexts.proto
+++ b/protos/contexts/v1/contexts.proto
@@ -17,7 +17,7 @@ syntax = "proto3";
 
 package com.docker.api.protos.context.v1;
 
-option go_package = "github.com/docker/compose-cli/cli/server/protos/context/v1;v1";
+option go_package = "github.com/docker/compose-cli/protos/context/v1;v1";
 
 service Contexts {
 	// Sets the current request for all calls
diff --git a/cli/server/protos/contexts/v1/doc.go b/protos/contexts/v1/doc.go
similarity index 100%
rename from cli/server/protos/contexts/v1/doc.go
rename to protos/contexts/v1/doc.go
diff --git a/cli/server/protos/streams/v1/streams.pb.go b/protos/streams/v1/streams.pb.go
similarity index 99%
rename from cli/server/protos/streams/v1/streams.pb.go
rename to protos/streams/v1/streams.pb.go
index 12a3b5ce..f9c54bb1 100644
--- a/cli/server/protos/streams/v1/streams.pb.go
+++ b/protos/streams/v1/streams.pb.go
@@ -23,9 +23,6 @@ package v1
 
 import (
 	context "context"
-	reflect "reflect"
-	sync "sync"
-
 	proto "github.com/golang/protobuf/proto"
 	any "github.com/golang/protobuf/ptypes/any"
 	grpc "google.golang.org/grpc"
@@ -33,6 +30,8 @@ import (
 	status "google.golang.org/grpc/status"
 	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
 	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	reflect "reflect"
+	sync "sync"
 )
 
 const (
diff --git a/cli/server/protos/streams/v1/streams.proto b/protos/streams/v1/streams.proto
similarity index 92%
rename from cli/server/protos/streams/v1/streams.proto
rename to protos/streams/v1/streams.proto
index cde5b3d3..8d396118 100644
--- a/cli/server/protos/streams/v1/streams.proto
+++ b/protos/streams/v1/streams.proto
@@ -19,7 +19,7 @@ package com.docker.api.protos.streams.v1;
 
 import "google/protobuf/any.proto";
 
-option go_package = "github.com/docker/compose-cli/cli/server/protos/streams/v1;v1";
+option go_package = "github.com/docker/compose-cli/protos/streams/v1;v1";
 
 service Streaming {
 	rpc NewStream(stream google.protobuf.Any) returns (stream google.protobuf.Any);
diff --git a/cli/server/protos/volumes/v1/volumes.pb.go b/protos/volumes/v1/volumes.pb.go
similarity index 99%
rename from cli/server/protos/volumes/v1/volumes.pb.go
rename to protos/volumes/v1/volumes.pb.go
index 6ee4208d..b6b2433c 100644
--- a/cli/server/protos/volumes/v1/volumes.pb.go
+++ b/protos/volumes/v1/volumes.pb.go
@@ -23,9 +23,6 @@ package v1
 
 import (
 	context "context"
-	reflect "reflect"
-	sync "sync"
-
 	proto "github.com/golang/protobuf/proto"
 	_ "github.com/golang/protobuf/ptypes/any"
 	grpc "google.golang.org/grpc"
@@ -33,6 +30,8 @@ import (
 	status "google.golang.org/grpc/status"
 	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
 	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	reflect "reflect"
+	sync "sync"
 )
 
 const (
diff --git a/cli/server/protos/volumes/v1/volumes.proto b/protos/volumes/v1/volumes.proto
similarity index 94%
rename from cli/server/protos/volumes/v1/volumes.proto
rename to protos/volumes/v1/volumes.proto
index 4048621e..6ae22e29 100644
--- a/cli/server/protos/volumes/v1/volumes.proto
+++ b/protos/volumes/v1/volumes.proto
@@ -19,7 +19,7 @@ package com.docker.api.protos.volumes.v1;
 
 import "google/protobuf/any.proto";
 
-option go_package = "github.com/docker/compose-cli/cli/server/protos/volumes/v1;v1";
+option go_package = "github.com/docker/compose-cli/protos/volumes/v1;v1";
 
 service Volumes {
 	rpc VolumesCreate(VolumesCreateRequest) returns (VolumesCreateResponse);
diff --git a/cli/server/contextserverstream.go b/server/contextserverstream.go
similarity index 100%
rename from cli/server/contextserverstream.go
rename to server/contextserverstream.go
diff --git a/cli/server/interceptor.go b/server/interceptor.go
similarity index 94%
rename from cli/server/interceptor.go
rename to server/interceptor.go
index 7528a513..17165a10 100644
--- a/cli/server/interceptor.go
+++ b/server/interceptor.go
@@ -25,10 +25,10 @@ import (
 	"google.golang.org/grpc/metadata"
 
 	"github.com/docker/compose-cli/api/client"
-	"github.com/docker/compose-cli/api/config"
-	apicontext "github.com/docker/compose-cli/api/context"
-	"github.com/docker/compose-cli/api/context/store"
-	"github.com/docker/compose-cli/cli/server/proxy"
+	"github.com/docker/compose-cli/config"
+	apicontext "github.com/docker/compose-cli/context"
+	"github.com/docker/compose-cli/context/store"
+	"github.com/docker/compose-cli/server/proxy"
 )
 
 // key is the key where the current docker context is stored in the metadata
diff --git a/cli/server/metrics.go b/server/metrics.go
similarity index 96%
rename from cli/server/metrics.go
rename to server/metrics.go
index 8dd5065e..bbd1131e 100644
--- a/cli/server/metrics.go
+++ b/server/metrics.go
@@ -21,8 +21,8 @@ import (
 
 	"google.golang.org/grpc"
 
-	"github.com/docker/compose-cli/cli/metrics"
-	"github.com/docker/compose-cli/cli/server/proxy"
+	"github.com/docker/compose-cli/metrics"
+	"github.com/docker/compose-cli/server/proxy"
 )
 
 var (
diff --git a/cli/server/proxy/compose.go b/server/proxy/compose.go
similarity index 97%
rename from cli/server/proxy/compose.go
rename to server/proxy/compose.go
index edb07bcf..4fa76548 100644
--- a/cli/server/proxy/compose.go
+++ b/server/proxy/compose.go
@@ -24,7 +24,7 @@ import (
 	"github.com/compose-spec/compose-go/cli"
 	"github.com/compose-spec/compose-go/types"
 
-	composev1 "github.com/docker/compose-cli/cli/server/protos/compose/v1"
+	composev1 "github.com/docker/compose-cli/protos/compose/v1"
 )
 
 func (p *proxy) Up(ctx context.Context, request *composev1.ComposeUpRequest) (*composev1.ComposeUpResponse, error) {
diff --git a/cli/server/proxy/containers.go b/server/proxy/containers.go
similarity index 96%
rename from cli/server/proxy/containers.go
rename to server/proxy/containers.go
index 802a0930..03ed1386 100644
--- a/cli/server/proxy/containers.go
+++ b/server/proxy/containers.go
@@ -20,15 +20,14 @@ import (
 	"context"
 	"errors"
 
-	"github.com/docker/compose-cli/utils"
-
 	"github.com/compose-spec/compose-go/types"
 	"github.com/containerd/containerd/platforms"
 	specs "github.com/opencontainers/image-spec/specs-go/v1"
 
 	"github.com/docker/compose-cli/api/containers"
-	containersv1 "github.com/docker/compose-cli/cli/server/protos/containers/v1"
-	"github.com/docker/compose-cli/cli/server/proxy/streams"
+	"github.com/docker/compose-cli/formatter"
+	containersv1 "github.com/docker/compose-cli/protos/containers/v1"
+	"github.com/docker/compose-cli/server/proxy/streams"
 )
 
 func portsToGrpc(ports []containers.Port) []*containersv1.Port {
@@ -186,7 +185,7 @@ func grpcContainerToContainerConfig(request *containersv1.RunRequest) (container
 		Ports:                  ports,
 		Labels:                 request.GetLabels(),
 		Volumes:                request.GetVolumes(),
-		MemLimit:               utils.MemBytes(request.GetMemoryLimit()),
+		MemLimit:               formatter.MemBytes(request.GetMemoryLimit()),
 		CPULimit:               float64(request.GetCpuLimit()),
 		RestartPolicyCondition: request.RestartPolicyCondition,
 		Environment:            request.Environment,
diff --git a/cli/server/proxy/contexts.go b/server/proxy/contexts.go
similarity index 94%
rename from cli/server/proxy/contexts.go
rename to server/proxy/contexts.go
index dead6921..10f3b3aa 100644
--- a/cli/server/proxy/contexts.go
+++ b/server/proxy/contexts.go
@@ -19,9 +19,9 @@ package proxy
 import (
 	"context"
 
-	"github.com/docker/compose-cli/api/config"
-	"github.com/docker/compose-cli/api/context/store"
-	contextsv1 "github.com/docker/compose-cli/cli/server/protos/contexts/v1"
+	"github.com/docker/compose-cli/config"
+	"github.com/docker/compose-cli/context/store"
+	contextsv1 "github.com/docker/compose-cli/protos/contexts/v1"
 )
 
 type contextsProxy struct {
diff --git a/cli/server/proxy/proxy.go b/server/proxy/proxy.go
similarity index 79%
rename from cli/server/proxy/proxy.go
rename to server/proxy/proxy.go
index 621b14f4..89f46b6a 100644
--- a/cli/server/proxy/proxy.go
+++ b/server/proxy/proxy.go
@@ -21,13 +21,13 @@ import (
 	"sync"
 
 	"github.com/docker/compose-cli/api/client"
-	"github.com/docker/compose-cli/api/config"
-	composev1 "github.com/docker/compose-cli/cli/server/protos/compose/v1"
-	containersv1 "github.com/docker/compose-cli/cli/server/protos/containers/v1"
-	contextsv1 "github.com/docker/compose-cli/cli/server/protos/contexts/v1"
-	streamsv1 "github.com/docker/compose-cli/cli/server/protos/streams/v1"
-	volumesv1 "github.com/docker/compose-cli/cli/server/protos/volumes/v1"
-	"github.com/docker/compose-cli/cli/server/proxy/streams"
+	"github.com/docker/compose-cli/config"
+	composev1 "github.com/docker/compose-cli/protos/compose/v1"
+	containersv1 "github.com/docker/compose-cli/protos/containers/v1"
+	contextsv1 "github.com/docker/compose-cli/protos/contexts/v1"
+	streamsv1 "github.com/docker/compose-cli/protos/streams/v1"
+	volumesv1 "github.com/docker/compose-cli/protos/volumes/v1"
+	"github.com/docker/compose-cli/server/proxy/streams"
 )
 
 type clientKey struct{}
diff --git a/cli/server/proxy/streams.go b/server/proxy/streams.go
similarity index 91%
rename from cli/server/proxy/streams.go
rename to server/proxy/streams.go
index 763d61ac..dee404d3 100644
--- a/cli/server/proxy/streams.go
+++ b/server/proxy/streams.go
@@ -21,8 +21,8 @@ import (
 	"github.com/sirupsen/logrus"
 	"google.golang.org/grpc/metadata"
 
-	streamsv1 "github.com/docker/compose-cli/cli/server/protos/streams/v1"
-	"github.com/docker/compose-cli/cli/server/proxy/streams"
+	streamsv1 "github.com/docker/compose-cli/protos/streams/v1"
+	"github.com/docker/compose-cli/server/proxy/streams"
 )
 
 func (p *proxy) NewStream(stream streamsv1.Streaming_NewStreamServer) error {
diff --git a/cli/server/proxy/streams/io.go b/server/proxy/streams/io.go
similarity index 94%
rename from cli/server/proxy/streams/io.go
rename to server/proxy/streams/io.go
index 28fd6fd0..b7e29462 100644
--- a/cli/server/proxy/streams/io.go
+++ b/server/proxy/streams/io.go
@@ -19,7 +19,7 @@ package streams
 import (
 	"github.com/golang/protobuf/ptypes"
 
-	streamsv1 "github.com/docker/compose-cli/cli/server/protos/streams/v1"
+	streamsv1 "github.com/docker/compose-cli/protos/streams/v1"
 )
 
 // IO implements an io.ReadWriter that forwards everything to the stream
diff --git a/cli/server/proxy/streams/logs.go b/server/proxy/streams/logs.go
similarity index 92%
rename from cli/server/proxy/streams/logs.go
rename to server/proxy/streams/logs.go
index 52cff554..58a94851 100644
--- a/cli/server/proxy/streams/logs.go
+++ b/server/proxy/streams/logs.go
@@ -21,7 +21,7 @@ import (
 
 	"google.golang.org/grpc"
 
-	containersv1 "github.com/docker/compose-cli/cli/server/protos/containers/v1"
+	containersv1 "github.com/docker/compose-cli/protos/containers/v1"
 )
 
 // Log implements an io.Writer that proxies logs over a gRPC stream
diff --git a/cli/server/proxy/streams/stream.go b/server/proxy/streams/stream.go
similarity index 93%
rename from cli/server/proxy/streams/stream.go
rename to server/proxy/streams/stream.go
index e10b3962..79d07b96 100644
--- a/cli/server/proxy/streams/stream.go
+++ b/server/proxy/streams/stream.go
@@ -19,7 +19,7 @@ package streams
 import (
 	"sync"
 
-	streamsv1 "github.com/docker/compose-cli/cli/server/protos/streams/v1"
+	streamsv1 "github.com/docker/compose-cli/protos/streams/v1"
 )
 
 // Stream is a bidirectional stream for container IO
diff --git a/cli/server/proxy/volumes.go b/server/proxy/volumes.go
similarity index 97%
rename from cli/server/proxy/volumes.go
rename to server/proxy/volumes.go
index 164d4151..6da27432 100644
--- a/cli/server/proxy/volumes.go
+++ b/server/proxy/volumes.go
@@ -21,7 +21,7 @@ import (
 
 	"github.com/docker/compose-cli/aci"
 	"github.com/docker/compose-cli/api/volumes"
-	volumesv1 "github.com/docker/compose-cli/cli/server/protos/volumes/v1"
+	volumesv1 "github.com/docker/compose-cli/protos/volumes/v1"
 )
 
 // VolumesCreate creates a volume.
diff --git a/cli/server/server.go b/server/server.go
similarity index 97%
rename from cli/server/server.go
rename to server/server.go
index a5511af1..e5adfa53 100644
--- a/cli/server/server.go
+++ b/server/server.go
@@ -25,7 +25,7 @@ import (
 	"google.golang.org/grpc/health"
 	"google.golang.org/grpc/health/grpc_health_v1"
 
-	"github.com/docker/compose-cli/cli/metrics"
+	"github.com/docker/compose-cli/metrics"
 )
 
 // New returns a new GRPC server.


Test patch:
diff --git a/aci/context_test.go b/aci/context_test.go
index 88d72656..e834498a 100644
--- a/aci/context_test.go
+++ b/aci/context_test.go
@@ -28,7 +28,7 @@ import (
 	"gotest.tools/v3/assert"
 	"gotest.tools/v3/assert/cmp"
 
-	"github.com/docker/compose-cli/api/context/store"
+	"github.com/docker/compose-cli/context/store"
 )
 
 type contextMocks struct {
diff --git a/aci/convert/convert_test.go b/aci/convert/convert_test.go
index ee3bcc2c..be7a72e5 100644
--- a/aci/convert/convert_test.go
+++ b/aci/convert/convert_test.go
@@ -30,7 +30,7 @@ import (
 
 	"github.com/docker/compose-cli/api/compose"
 	"github.com/docker/compose-cli/api/containers"
-	"github.com/docker/compose-cli/api/context/store"
+	"github.com/docker/compose-cli/context/store"
 )
 
 var (
diff --git a/cli/cmd/inspect_test.go b/cli/cmd/inspect_test.go
new file mode 100644
index 00000000..af75d4df
--- /dev/null
+++ b/cli/cmd/inspect_test.go
@@ -0,0 +1,34 @@
+/*
+   Copyright 2020 Docker Compose CLI authors
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+package cmd
+
+import (
+	"testing"
+
+	"gotest.tools/v3/assert"
+	"gotest.tools/v3/golden"
+
+	_ "github.com/docker/compose-cli/example"
+	"github.com/docker/compose-cli/tests/framework"
+)
+
+func TestInspectId(t *testing.T) {
+	c := framework.NewTestCLI(t)
+	err := runInspect(c.Context(), "id")
+	assert.NilError(t, err)
+	golden.Assert(t, c.GetStdOut(), "inspect-out-id.golden")
+}
diff --git a/cli/cmd/ps_test.go b/cli/cmd/ps_test.go
new file mode 100644
index 00000000..7dc72d57
--- /dev/null
+++ b/cli/cmd/ps_test.go
@@ -0,0 +1,51 @@
+/*
+   Copyright 2020 Docker Compose CLI authors
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+package cmd
+
+import (
+	"testing"
+
+	"gotest.tools/v3/assert"
+	"gotest.tools/v3/golden"
+
+	_ "github.com/docker/compose-cli/example"
+	"github.com/docker/compose-cli/tests/framework"
+)
+
+func TestPs(t *testing.T) {
+	c := framework.NewTestCLI(t)
+	opts := psOpts{
+		quiet: false,
+	}
+
+	err := runPs(c.Context(), opts)
+	assert.NilError(t, err)
+
+	golden.Assert(t, c.GetStdOut(), "ps-out.golden")
+}
+
+func TestPsQuiet(t *testing.T) {
+	c := framework.NewTestCLI(t)
+	opts := psOpts{
+		quiet: true,
+	}
+
+	err := runPs(c.Context(), opts)
+	assert.NilError(t, err)
+
+	golden.Assert(t, c.GetStdOut(), "ps-out-quiet.golden")
+}
diff --git a/cli/cmd/testdata/inspect-out-id.golden b/cli/cmd/testdata/inspect-out-id.golden
new file mode 100644
index 00000000..1200c98e
--- /dev/null
+++ b/cli/cmd/testdata/inspect-out-id.golden
@@ -0,0 +1,14 @@
+{
+    "ID": "id",
+    "Status": "",
+    "Image": "nginx",
+    "HostConfig": {
+        "RestartPolicy": "none",
+        "CPUReservation": 0,
+        "CPULimit": 0,
+        "MemoryReservation": 0,
+        "MemoryLimit": 0,
+        "AutoRemove": false
+    },
+    "Platform": "Linux"
+}
diff --git a/cli/cmd/testdata/ps-out-quiet.golden b/cli/cmd/testdata/ps-out-quiet.golden
new file mode 100644
index 00000000..ceeb39db
--- /dev/null
+++ b/cli/cmd/testdata/ps-out-quiet.golden
@@ -0,0 +1,2 @@
+id
+1234
diff --git a/cli/cmd/testdata/ps-out.golden b/cli/cmd/testdata/ps-out.golden
new file mode 100644
index 00000000..ee7ef979
--- /dev/null
+++ b/cli/cmd/testdata/ps-out.golden
@@ -0,0 +1,3 @@
+CONTAINER ID        IMAGE               COMMAND             STATUS              PORTS
+id                  nginx                                                       
+1234                alpine                                                      
diff --git a/cli/main_test.go b/cli/main_test.go
index bb62ee04..20426de3 100644
--- a/cli/main_test.go
+++ b/cli/main_test.go
@@ -24,11 +24,11 @@ import (
 
 	"gotest.tools/v3/assert"
 
-	"github.com/docker/compose-cli/api/config"
 	"github.com/docker/compose-cli/cli/cmd"
 	"github.com/docker/compose-cli/cli/cmd/context"
 	"github.com/docker/compose-cli/cli/cmd/login"
 	"github.com/docker/compose-cli/cli/cmd/run"
+	"github.com/docker/compose-cli/config"
 )
 
 var contextSetConfig = []byte(`{
diff --git a/cli/mobycli/exec_test.go b/cli/mobycli/exec_test.go
index 7138464f..20bd71fa 100644
--- a/cli/mobycli/exec_test.go
+++ b/cli/mobycli/exec_test.go
@@ -21,7 +21,7 @@ import (
 
 	"gotest.tools/v3/assert"
 
-	"github.com/docker/compose-cli/api/context/store"
+	"github.com/docker/compose-cli/context/store"
 )
 
 func TestDelegateContextTypeToMoby(t *testing.T) {
diff --git a/api/context/store/store_test.go b/context/store/store_test.go
similarity index 98%
rename from api/context/store/store_test.go
rename to context/store/store_test.go
index 97e7613e..29b814f1 100644
--- a/api/context/store/store_test.go
+++ b/context/store/store_test.go
@@ -25,7 +25,7 @@ import (
 	"gotest.tools/v3/assert"
 	"gotest.tools/v3/assert/cmp"
 
-	"github.com/docker/compose-cli/api/errdefs"
+	"github.com/docker/compose-cli/errdefs"
 )
 
 func testStore(t *testing.T) Store {
diff --git a/ecs/context_test.go b/ecs/context_test.go
index f196edc4..a69385e7 100644
--- a/ecs/context_test.go
+++ b/ecs/context_test.go
@@ -21,8 +21,8 @@ import (
 	"os"
 	"testing"
 
-	"github.com/docker/compose-cli/api/context/store"
-	"github.com/docker/compose-cli/utils/prompt"
+	"github.com/docker/compose-cli/context/store"
+	"github.com/docker/compose-cli/prompt"
 
 	"github.com/golang/mock/gomock"
 	"gotest.tools/v3/assert"
diff --git a/utils/units_test.go b/formatter/units_test.go
similarity index 98%
rename from utils/units_test.go
rename to formatter/units_test.go
index 2e35e11b..ea21a210 100644
--- a/utils/units_test.go
+++ b/formatter/units_test.go
@@ -14,7 +14,7 @@
    limitations under the License.
 */
 
-package utils
+package formatter
 
 import (
 	"testing"
diff --git a/cli/server/interceptor_test.go b/server/interceptor_test.go
similarity index 97%
rename from cli/server/interceptor_test.go
rename to server/interceptor_test.go
index 66dbf4a7..88fa1ae2 100644
--- a/cli/server/interceptor_test.go
+++ b/server/interceptor_test.go
@@ -28,8 +28,8 @@ import (
 	"gotest.tools/v3/assert"
 	"gotest.tools/v3/assert/cmp"
 
-	"github.com/docker/compose-cli/api/config"
-	apicontext "github.com/docker/compose-cli/api/context"
+	"github.com/docker/compose-cli/config"
+	apicontext "github.com/docker/compose-cli/context"
 )
 
 func testContext(t *testing.T) context.Context {
diff --git a/cli/server/metrics_test.go b/server/metrics_test.go
similarity index 88%
rename from cli/server/metrics_test.go
rename to server/metrics_test.go
index 498ef5e3..3b47c7ef 100644
--- a/cli/server/metrics_test.go
+++ b/server/metrics_test.go
@@ -31,16 +31,16 @@ import (
 	"github.com/docker/compose-cli/api/client"
 	"github.com/docker/compose-cli/api/compose"
 	"github.com/docker/compose-cli/api/containers"
-	"github.com/docker/compose-cli/api/errdefs"
 	"github.com/docker/compose-cli/api/secrets"
 	"github.com/docker/compose-cli/api/volumes"
-	"github.com/docker/compose-cli/cli/metrics"
-	composev1 "github.com/docker/compose-cli/cli/server/protos/compose/v1"
-	containersv1 "github.com/docker/compose-cli/cli/server/protos/containers/v1"
-	contextsv1 "github.com/docker/compose-cli/cli/server/protos/contexts/v1"
-	streamsv1 "github.com/docker/compose-cli/cli/server/protos/streams/v1"
-	volumesv1 "github.com/docker/compose-cli/cli/server/protos/volumes/v1"
-	"github.com/docker/compose-cli/cli/server/proxy"
+	"github.com/docker/compose-cli/errdefs"
+	"github.com/docker/compose-cli/metrics"
+	composev1 "github.com/docker/compose-cli/protos/compose/v1"
+	containersv1 "github.com/docker/compose-cli/protos/containers/v1"
+	contextsv1 "github.com/docker/compose-cli/protos/contexts/v1"
+	streamsv1 "github.com/docker/compose-cli/protos/streams/v1"
+	volumesv1 "github.com/docker/compose-cli/protos/volumes/v1"
+	"github.com/docker/compose-cli/server/proxy"
 )
 
 func TestAllMethodsHaveCorrespondingCliCommand(t *testing.T) {
diff --git a/cli/server/proxy/containers_test.go b/server/proxy/containers_test.go
similarity index 91%
rename from cli/server/proxy/containers_test.go
rename to server/proxy/containers_test.go
index 701175ac..3389c32b 100644
--- a/cli/server/proxy/containers_test.go
+++ b/server/proxy/containers_test.go
@@ -19,12 +19,11 @@ package proxy
 import (
 	"testing"
 
-	"github.com/docker/compose-cli/utils"
-
 	"gotest.tools/v3/assert"
 
 	"github.com/docker/compose-cli/api/containers"
-	containersv1 "github.com/docker/compose-cli/cli/server/protos/containers/v1"
+	"github.com/docker/compose-cli/formatter"
+	containersv1 "github.com/docker/compose-cli/protos/containers/v1"
 )
 
 func TestGrpcContainerToContainerConfig(t *testing.T) {
@@ -54,7 +53,7 @@ func TestGrpcContainerToContainerConfig(t *testing.T) {
 	assert.NilError(t, err)
 	assert.Equal(t, cc.ID, "myId")
 	assert.Equal(t, cc.Image, "myImage")
-	assert.Equal(t, cc.MemLimit, utils.MemBytes(41))
+	assert.Equal(t, cc.MemLimit, formatter.MemBytes(41))
 	assert.Equal(t, cc.CPULimit, float64(42))
 	assert.DeepEqual(t, cc.Volumes, []string{"myvolume"})
 	assert.DeepEqual(t, cc.Ports, []containers.Port{
diff --git a/cli/server/proxy/contexts_test.go b/server/proxy/contexts_test.go
similarity index 95%
rename from cli/server/proxy/contexts_test.go
rename to server/proxy/contexts_test.go
index c0542293..567d46a2 100644
--- a/cli/server/proxy/contexts_test.go
+++ b/server/proxy/contexts_test.go
@@ -21,10 +21,9 @@ import (
 
 	"gotest.tools/v3/assert"
 
+	"github.com/docker/compose-cli/context/store"
+	contextsv1 "github.com/docker/compose-cli/protos/contexts/v1"
 	"github.com/google/go-cmp/cmp/cmpopts"
-
-	"github.com/docker/compose-cli/api/context/store"
-	contextsv1 "github.com/docker/compose-cli/cli/server/protos/contexts/v1"
 )
 
 func TestConvertContext(t *testing.T) {
diff --git a/cli/server/proxy/streams/logs_test.go b/server/proxy/streams/logs_test.go
similarity index 96%
rename from cli/server/proxy/streams/logs_test.go
rename to server/proxy/streams/logs_test.go
index eaa60b23..46a59e15 100644
--- a/cli/server/proxy/streams/logs_test.go
+++ b/server/proxy/streams/logs_test.go
@@ -24,7 +24,7 @@ import (
 	"gotest.tools/v3/assert"
 	"gotest.tools/v3/assert/cmp"
 
-	v1 "github.com/docker/compose-cli/cli/server/protos/containers/v1"
+	v1 "github.com/docker/compose-cli/protos/containers/v1"
 )
 
 type logServer struct {
diff --git a/cli/server/proxy/streams/stream_test.go b/server/proxy/streams/stream_test.go
similarity index 97%
rename from cli/server/proxy/streams/stream_test.go
rename to server/proxy/streams/stream_test.go
index bb6ea0b2..1bc22aa2 100644
--- a/cli/server/proxy/streams/stream_test.go
+++ b/server/proxy/streams/stream_test.go
@@ -29,7 +29,7 @@ import (
 	"gotest.tools/v3/assert"
 	"gotest.tools/v3/assert/cmp"
 
-	streamsv1 "github.com/docker/compose-cli/cli/server/protos/streams/v1"
+	streamsv1 "github.com/docker/compose-cli/protos/streams/v1"
 )
 
 type byteStream struct {
diff --git a/cli/server/socket_unix.go b/server/socket_unix.go
similarity index 100%
rename from cli/server/socket_unix.go
rename to server/socket_unix.go
diff --git a/cli/server/socket_windows.go b/server/socket_windows.go
similarity index 100%
rename from cli/server/socket_windows.go
rename to server/socket_windows.go
diff --git a/tests/aci-e2e/e2e-aci_test.go b/tests/aci-e2e/e2e-aci_test.go
index 0ac81b97..3bcdea55 100644
--- a/tests/aci-e2e/e2e-aci_test.go
+++ b/tests/aci-e2e/e2e-aci_test.go
@@ -51,9 +51,9 @@ import (
 	"github.com/docker/compose-cli/aci/convert"
 	"github.com/docker/compose-cli/aci/login"
 	"github.com/docker/compose-cli/api/containers"
-	"github.com/docker/compose-cli/api/context/store"
-	"github.com/docker/compose-cli/api/errdefs"
 	"github.com/docker/compose-cli/cli/cmd"
+	"github.com/docker/compose-cli/context/store"
+	"github.com/docker/compose-cli/errdefs"
 	. "github.com/docker/compose-cli/tests/framework"
 )
 
diff --git a/tests/compose-e2e/compose_test.go b/tests/compose-e2e/compose_test.go
index e23f5f61..8b17a09b 100644
--- a/tests/compose-e2e/compose_test.go
+++ b/tests/compose-e2e/compose_test.go
@@ -261,9 +261,18 @@ func TestLocalComposeVolume(t *testing.T) {
 	})
 
 	t.Run("check container volume specs", func(t *testing.T) {
-		res := c.RunDockerCmd("inspect", "compose-e2e-volume_nginx2_1", "--format", "{{ json .HostConfig.Mounts }}")
+		res := c.RunDockerCmd("inspect", "compose-e2e-volume_nginx2_1", "--format", "{{ json .Mounts }}")
+		output := res.Stdout()
 		//nolint
-		res.Assert(t, icmd.Expected{Out: `[{"Type":"volume","Source":"compose-e2e-volume_staticVol","Target":"/usr/share/nginx/html","ReadOnly":true},{"Type":"volume","Target":"/usr/src/app/node_modules"},{"Type":"volume","Source":"myVolume","Target":"/usr/share/nginx/test"}]`})
+		assert.Assert(t, strings.Contains(output, `"Destination":"/usr/src/app/node_modules","Driver":"local","Mode":"","RW":true,"Propagation":""`))
+	})
+
+	t.Run("check container bind-mounts specs", func(t *testing.T) {
+		res := c.RunDockerCmd("inspect", "compose-e2e-volume_nginx_1", "--format", "{{ json .HostConfig.Mounts }}")
+		output := res.Stdout()
+		//nolint
+		assert.Assert(t, strings.Contains(output, `"Type":"bind"`))
+		assert.Assert(t, strings.Contains(output, `"Target":"/usr/share/nginx/html"`))
 	})
 
 	t.Run("cleanup volume project", func(t *testing.T) {
diff --git a/tests/framework/unit.go b/tests/framework/unit.go
index 6f37d63d..d2c8dc14 100644
--- a/tests/framework/unit.go
+++ b/tests/framework/unit.go
@@ -20,6 +20,13 @@ import (
 	"context"
 	"io/ioutil"
 	"os"
+	"testing"
+
+	"gotest.tools/v3/assert"
+	"gotest.tools/v3/assert/cmp"
+
+	apicontext "github.com/docker/compose-cli/context"
+	"github.com/docker/compose-cli/context/store"
 )
 
 // TestCLI is a helper struct for CLI tests.
@@ -29,6 +36,33 @@ type TestCLI struct {
 	reader *os.File
 }
 
+// NewTestCLI returns a CLI testing helper.
+func NewTestCLI(t *testing.T) *TestCLI {
+	dir, err := ioutil.TempDir("", "store")
+	assert.Check(t, cmp.Nil(err))
+
+	originalStdout := os.Stdout
+
+	t.Cleanup(func() {
+		os.Stdout = originalStdout
+		_ = os.RemoveAll(dir)
+	})
+
+	s, err := store.New(dir)
+	assert.Check(t, cmp.Nil(err))
+	err = s.Create("example", "example", "", store.ContextMetadata{})
+	assert.Check(t, cmp.Nil(err))
+
+	ctx := context.Background()
+	ctx = store.WithContextStore(ctx, s)
+	ctx = apicontext.WithCurrentContext(ctx, "example")
+
+	r, w, err := os.Pipe()
+	os.Stdout = w
+	assert.Check(t, cmp.Nil(err))
+	return &TestCLI{ctx, w, r}
+}
+
 // Context returns a configured context
 func (c *TestCLI) Context() context.Context {
 	return c.ctx