Repository: docker/compose (go)

Issue:
docker compose version command depends on project configuration
<!--
If you are reporting a new issue, make sure that we do not have any duplicates
already open. You can ensure this by searching the issue list for this
repository. If there is a duplicate, please close your issue and add a comment
to the existing issue instead.

If you suspect your issue is a bug, please edit your issue description to
include the BUG REPORT INFORMATION shown below. If you fail to provide this
information within 7 days, we cannot debug your issue and will close it. We
will, however, reopen it if you later provide the information.

For more information about reporting issues, see
https://github.com/docker/compose-cli/blob/master/CONTRIBUTING.md#reporting-other-issues

---------------------------------------------------
GENERAL SUPPORT INFORMATION
---------------------------------------------------

The GitHub issue tracker is for bug reports and feature requests.
General support can be found at the following locations:

- Docker Support Forums - https://forums.docker.com
- Docker Community Slack - https://dockr.ly/slack
- Post a question on StackOverflow, using the Docker tag

---------------------------------------------------
BUG REPORT INFORMATION
---------------------------------------------------
Use the commands below to provide key information from your environment:
You do NOT have to include this information if this is a FEATURE REQUEST
-->

**Description**

<!--
Briefly describe the problem you are having in a few paragraphs.
-->
The docker compose version command attempts to load the project configuration.
IMO, this is unexpected and counter intuitive. I would expect the version command to work regardless of the project runtime environment.

**Steps to reproduce the issue:**
1. `COMPOSE_FILE=foo docker compose version`


**Describe the results you received:**
```
stat <PWD>/foo: no such file or directory
````

**Describe the results you expected:**
```
Docker Compose version v2.6.1
```

**Additional information you deem important (e.g. issue happens only occasionally):**

**Output of `docker compose version`:**

```
Docker Compose version v2.6.1
```

**Output of `docker info`:**

```
Client:
 Context:    default
 Debug Mode: false
 Plugins:
  buildx: Docker Buildx (Docker Inc., v0.8.2-docker)
  compose: Docker Compose (Docker Inc., v2.6.1)
  scan: Docker Scan (Docker Inc., v0.1.0-227-g061fe0a0c5)

Server:
 Containers: 69
  Running: 0
  Paused: 0
  Stopped: 69
 Images: 200
 Server Version: 20.10.16
 Storage Driver: overlay2
  Backing Filesystem: extfs
  Supports d_type: true
  Native Overlay Diff: false
  userxattr: false
 Logging Driver: json-file
 Cgroup Driver: systemd
 Cgroup Version: 2
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
 Swarm: inactive
 Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: 96df0994faabc1944fc614e52b0b3c6feb609a57.m
 runc version: 
 init version: de40ad0
 Security Options:
  seccomp
   Profile: default
  cgroupns
 Kernel Version: xxx
 Operating System: xxx
 OSType: linux
 Architecture: x86_64
 CPUs: 4
 Total Memory: 15.49GiB
 Name: xxx
 ID: xxx
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Username: nocive
 Registry: https://index.docker.io/v1/
 Labels:
 Experimental: true
 Insecure Registries:
  127.0.0.0/8
 Live Restore Enabled: false

```

**Additional environment details:**
NA


Pull request:
Overwrite parent commands PreRun code for `compose version`
.. to avoid trying (and failing) to load a compose file if the COMPOSE_FILE env var is set such as `COMPOSE_FILE=foo compose version`

Signed-off-by: Laura Brehm <laurabrehm@hey.com>

**What I did**

Overwrite parent `compose` command's `PersistentPreRunE` that attempts to load compose file for `compose version` command.

**Related issue**
<!-- If this is a bug fix, make sure your description includes "fixes #xxxx", or "closes #xxxx" -->

Closes #9662

**(not mandatory) A picture of a cute animal, if possible in relation with what you did**

![BktxGkF5zqXdVGcJ5TKYs-1200-80](https://user-images.githubusercontent.com/70572044/182122855-e245700d-bc94-48b1-8a28-35564194ac56.jpg)



Patch:
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 2f9ebd847..55be2a92b 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -124,10 +124,9 @@ Fork the repository and make changes on your fork in a feature branch:
     issue.
 
 Submit unit tests for your changes. Go has a great test framework built in; use
-it! Take a look at existing tests for inspiration. Also end-to-end tests are
-available. Run the full test suite, both unit tests and e2e tests on your
-branch before submitting a pull request. See [BUILDING.md](BUILDING.md) for
-instructions to build and run tests.
+it! Take a look at existing tests for inspiration. [Run the full test
+suite](README.md) on your branch before
+submitting a pull request.
 
 Write clean code. Universally formatted code promotes ease of writing, reading,
 and maintenance. Always run `gofmt -s -w file.go` on each changed file before
diff --git a/Dockerfile b/Dockerfile
index e24a0fc17..45d2cc213 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -90,7 +90,7 @@ RUN --mount=target=. \
     make -f builder.Makefile test
 
 FROM base AS check-license-headers
-RUN go install github.com/google/addlicense@latest
+RUN go install github.com/kunalkushwaha/ltag@latest
 RUN --mount=target=. \
     make -f builder.Makefile check-license-headers
 
diff --git a/cmd/compose/compose.go b/cmd/compose/compose.go
index 2db045017..c247bef15 100644
--- a/cmd/compose/compose.go
+++ b/cmd/compose/compose.go
@@ -159,15 +159,15 @@ func (o *projectOptions) toProject(services []string, po ...cli.ProjectOptionsFn
 		return nil, compose.WrapComposeError(err)
 	}
 
-	if o.Compatibility || utils.StringToBool(options.Environment["COMPOSE_COMPATIBILITY"]) {
-		api.Separator = "_"
-	}
-
 	project, err := cli.ProjectFromOptions(options)
 	if err != nil {
 		return nil, compose.WrapComposeError(err)
 	}
 
+	if o.Compatibility || utils.StringToBool(project.Environment["COMPOSE_COMPATIBILITY"]) {
+		compose.Separator = "_"
+	}
+
 	ef := o.EnvFile
 	if ef != "" && !filepath.IsAbs(ef) {
 		ef, err = filepath.Abs(ef)
@@ -354,8 +354,10 @@ func setEnvWithDotEnv(prjOpts *projectOptions) error {
 		return err
 	}
 	for k, v := range envFromFile {
-		if err := os.Setenv(k, v); err != nil { // overwrite the process env with merged OS + env file results
-			return err
+		if _, ok := os.LookupEnv(k); !ok {
+			if err := os.Setenv(k, v); err != nil {
+				return err
+			}
 		}
 	}
 	return nil
diff --git a/cmd/compose/create.go b/cmd/compose/create.go
index 50e7a6f79..7ce8a1853 100644
--- a/cmd/compose/create.go
+++ b/cmd/compose/create.go
@@ -30,7 +30,6 @@ import (
 type createOptions struct {
 	Build         bool
 	noBuild       bool
-	Pull          string
 	removeOrphans bool
 	ignoreOrphans bool
 	forceRecreate bool
@@ -57,7 +56,6 @@ func createCommand(p *projectOptions, backend api.Service) *cobra.Command {
 			return nil
 		}),
 		RunE: p.WithProject(func(ctx context.Context, project *types.Project) error {
-			opts.Apply(project)
 			return backend.Create(ctx, project, api.CreateOptions{
 				RemoveOrphans:        opts.removeOrphans,
 				IgnoreOrphans:        opts.ignoreOrphans,
@@ -73,7 +71,6 @@ func createCommand(p *projectOptions, backend api.Service) *cobra.Command {
 	flags := cmd.Flags()
 	flags.BoolVar(&opts.Build, "build", false, "Build images before starting containers.")
 	flags.BoolVar(&opts.noBuild, "no-build", false, "Don't build an image, even if it's missing.")
-	flags.StringVar(&opts.Pull, "pull", "missing", `Pull image before running ("always"|"missing"|"never")`)
 	flags.BoolVar(&opts.forceRecreate, "force-recreate", false, "Recreate containers even if their configuration and image haven't changed.")
 	flags.BoolVar(&opts.noRecreate, "no-recreate", false, "If containers already exist, don't recreate them. Incompatible with --force-recreate.")
 	return cmd
@@ -108,12 +105,6 @@ func (opts createOptions) GetTimeout() *time.Duration {
 }
 
 func (opts createOptions) Apply(project *types.Project) {
-	if opts.Pull != "" {
-		for i, service := range project.Services {
-			service.PullPolicy = opts.Pull
-			project.Services[i] = service
-		}
-	}
 	if opts.Build {
 		for i, service := range project.Services {
 			if service.Build == nil {
@@ -126,9 +117,6 @@ func (opts createOptions) Apply(project *types.Project) {
 	if opts.noBuild {
 		for i, service := range project.Services {
 			service.Build = nil
-			if service.Image == "" {
-				service.Image = api.GetImageNameOrDefault(service, project.Name)
-			}
 			project.Services[i] = service
 		}
 	}
diff --git a/cmd/compose/list.go b/cmd/compose/list.go
index d4d53b726..618ad03c7 100644
--- a/cmd/compose/list.go
+++ b/cmd/compose/list.go
@@ -46,7 +46,6 @@ func listCommand(backend api.Service) *cobra.Command {
 		RunE: Adapt(func(ctx context.Context, args []string) error {
 			return runList(ctx, backend, lsOpts)
 		}),
-		Args:              cobra.NoArgs,
 		ValidArgsFunction: noCompletion(),
 	}
 	lsCmd.Flags().StringVar(&lsOpts.Format, "format", "pretty", "Format the output. Values: [pretty | json].")
diff --git a/cmd/compose/restart.go b/cmd/compose/restart.go
index f09d6fc83..f691c31fb 100644
--- a/cmd/compose/restart.go
+++ b/cmd/compose/restart.go
@@ -35,8 +35,8 @@ func restartCommand(p *projectOptions, backend api.Service) *cobra.Command {
 		projectOptions: p,
 	}
 	restartCmd := &cobra.Command{
-		Use:   "restart [SERVICE...]",
-		Short: "Restart service containers",
+		Use:   "restart",
+		Short: "Restart containers",
 		RunE: Adapt(func(ctx context.Context, args []string) error {
 			return runRestart(ctx, backend, opts, args)
 		}),
diff --git a/cmd/compose/up.go b/cmd/compose/up.go
index 1cdbff924..145bb7cea 100644
--- a/cmd/compose/up.go
+++ b/cmd/compose/up.go
@@ -115,7 +115,6 @@ func upCommand(p *projectOptions, backend api.Service) *cobra.Command {
 	flags.BoolVarP(&up.Detach, "detach", "d", false, "Detached mode: Run containers in the background")
 	flags.BoolVar(&create.Build, "build", false, "Build images before starting containers.")
 	flags.BoolVar(&create.noBuild, "no-build", false, "Don't build an image, even if it's missing.")
-	flags.StringVar(&create.Pull, "pull", "missing", `Pull image before running ("always"|"missing"|"never")`)
 	flags.BoolVar(&create.removeOrphans, "remove-orphans", false, "Remove containers for services not defined in the Compose file.")
 	flags.StringArrayVar(&up.scale, "scale", []string{}, "Scale SERVICE to NUM instances. Overrides the `scale` setting in the Compose file if present.")
 	flags.BoolVar(&up.noColor, "no-color", false, "Produce monochrome output.")
diff --git a/cmd/compose/version.go b/cmd/compose/version.go
index 06aff04d9..8a85e356a 100644
--- a/cmd/compose/version.go
+++ b/cmd/compose/version.go
@@ -37,11 +37,16 @@ func versionCommand() *cobra.Command {
 	cmd := &cobra.Command{
 		Use:   "version",
 		Short: "Show the Docker Compose version information",
-		Args:  cobra.NoArgs,
+		Args:  cobra.MaximumNArgs(0),
 		RunE: func(cmd *cobra.Command, _ []string) error {
 			runVersion(opts)
 			return nil
 		},
+		PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
+			// overwrite parent PersistentPreRunE to avoid trying to load
+			// compose file on version command if COMPOSE_FILE is set
+			return nil
+		},
 	}
 	// define flags for backward compatibility with com.docker.cli
 	flags := cmd.Flags()
diff --git a/docs/reference/compose.md b/docs/reference/compose.md
index e1b2c1fd0..46d3a1a72 100644
--- a/docs/reference/compose.md
+++ b/docs/reference/compose.md
@@ -23,7 +23,7 @@ Docker Compose
 | [`ps`](compose_ps.md) | List containers |
 | [`pull`](compose_pull.md) | Pull service images |
 | [`push`](compose_push.md) | Push service images |
-| [`restart`](compose_restart.md) | Restart service containers |
+| [`restart`](compose_restart.md) | Restart containers |
 | [`rm`](compose_rm.md) | Removes stopped service containers |
 | [`run`](compose_run.md) | Run a one-off command on a service. |
 | [`start`](compose_start.md) | Start services |
diff --git a/docs/reference/compose_create.md b/docs/reference/compose_create.md
index 843d4235b..00123ba78 100644
--- a/docs/reference/compose_create.md
+++ b/docs/reference/compose_create.md
@@ -11,7 +11,6 @@ Creates containers for a service.
 | `--force-recreate` |  |  | Recreate containers even if their configuration and image haven't changed. |
 | `--no-build` |  |  | Don't build an image, even if it's missing. |
 | `--no-recreate` |  |  | If containers already exist, don't recreate them. Incompatible with --force-recreate. |
-| `--pull` | `string` | `missing` | Pull image before running ("always"\|"missing"\|"never") |
 
 
 <!---MARKER_GEN_END-->
diff --git a/docs/reference/compose_restart.md b/docs/reference/compose_restart.md
index cc152b562..12326662b 100644
--- a/docs/reference/compose_restart.md
+++ b/docs/reference/compose_restart.md
@@ -1,7 +1,7 @@
 # docker compose restart
 
 <!---MARKER_GEN_START-->
-Restart service containers
+Restart containers
 
 ### Options
 
@@ -14,7 +14,7 @@ Restart service containers
 
 ## Description
 
-Restarts all stopped and running services, or the specified services only.
+Restarts all stopped and running services.
 
 If you make changes to your `compose.yml` configuration, these changes are not reflected
 after running this command. For example, changes to environment variables (which are added
diff --git a/docs/reference/compose_up.md b/docs/reference/compose_up.md
index 2a883c530..1a110f3f9 100644
--- a/docs/reference/compose_up.md
+++ b/docs/reference/compose_up.md
@@ -21,7 +21,6 @@ Create and start containers
 | `--no-log-prefix` |  |  | Don't print prefix in logs. |
 | `--no-recreate` |  |  | If containers already exist, don't recreate them. Incompatible with --force-recreate. |
 | `--no-start` |  |  | Don't start the services after creating them. |
-| `--pull` | `string` | `missing` | Pull image before running ("always"\|"missing"\|"never") |
 | `--quiet-pull` |  |  | Pull without printing progress information. |
 | `--remove-orphans` |  |  | Remove containers for services not defined in the Compose file. |
 | `-V`, `--renew-anon-volumes` |  |  | Recreate anonymous volumes instead of retrieving data from the previous containers. |
diff --git a/docs/reference/docker_compose_create.yaml b/docs/reference/docker_compose_create.yaml
index 176e695c1..35d76a3d6 100644
--- a/docs/reference/docker_compose_create.yaml
+++ b/docs/reference/docker_compose_create.yaml
@@ -47,16 +47,6 @@ options:
       experimentalcli: false
       kubernetes: false
       swarm: false
-    - option: pull
-      value_type: string
-      default_value: missing
-      description: Pull image before running ("always"|"missing"|"never")
-      deprecated: false
-      hidden: false
-      experimental: false
-      experimentalcli: false
-      kubernetes: false
-      swarm: false
 deprecated: false
 experimental: false
 experimentalcli: false
diff --git a/docs/reference/docker_compose_restart.yaml b/docs/reference/docker_compose_restart.yaml
index 733c3b271..8864aabdd 100644
--- a/docs/reference/docker_compose_restart.yaml
+++ b/docs/reference/docker_compose_restart.yaml
@@ -1,7 +1,7 @@
 command: docker compose restart
-short: Restart service containers
+short: Restart containers
 long: |-
-    Restarts all stopped and running services, or the specified services only.
+    Restarts all stopped and running services.
 
     If you make changes to your `compose.yml` configuration, these changes are not reflected
     after running this command. For example, changes to environment variables (which are added
@@ -11,7 +11,7 @@ long: |-
     If you are looking to configure a service's restart policy, please refer to
     [restart](https://github.com/compose-spec/compose-spec/blob/master/spec.md#restart)
     or [restart_policy](https://github.com/compose-spec/compose-spec/blob/master/deploy.md#restart_policy).
-usage: docker compose restart [SERVICE...]
+usage: docker compose restart
 pname: docker compose
 plink: docker_compose.yaml
 options:
diff --git a/docs/reference/docker_compose_up.yaml b/docs/reference/docker_compose_up.yaml
index 9ab0681ef..ef41c951f 100644
--- a/docs/reference/docker_compose_up.yaml
+++ b/docs/reference/docker_compose_up.yaml
@@ -165,16 +165,6 @@ options:
       experimentalcli: false
       kubernetes: false
       swarm: false
-    - option: pull
-      value_type: string
-      default_value: missing
-      description: Pull image before running ("always"|"missing"|"never")
-      deprecated: false
-      hidden: false
-      experimental: false
-      experimentalcli: false
-      kubernetes: false
-      swarm: false
     - option: quiet-pull
       value_type: bool
       default_value: "false"
diff --git a/go.mod b/go.mod
index 290971b8b..e5023f44f 100644
--- a/go.mod
+++ b/go.mod
@@ -6,10 +6,10 @@ require (
 	github.com/AlecAivazis/survey/v2 v2.3.5
 	github.com/buger/goterm v1.0.4
 	github.com/cnabio/cnab-to-oci v0.3.5
-	github.com/compose-spec/compose-go v1.3.0
+	github.com/compose-spec/compose-go v1.2.9
 	github.com/containerd/console v1.0.3
 	github.com/containerd/containerd v1.6.6
-	github.com/distribution/distribution/v3 v3.0.0-20220725133111-4bf3547399eb
+	github.com/distribution/distribution/v3 v3.0.0-20210316161203-a01c71e2477e
 	github.com/docker/buildx v0.8.2 // when updating, also update the replace rules accordingly
 	github.com/docker/cli v20.10.17+incompatible
 	github.com/docker/cli-docs-tool v0.5.0
@@ -33,7 +33,7 @@ require (
 	github.com/spf13/pflag v1.0.5
 	github.com/stretchr/testify v1.8.0
 	github.com/theupdateframework/notary v0.7.0
-	golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4
+	golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
 	gotest.tools v2.2.0+incompatible
 	gotest.tools/v3 v3.3.0
 )
@@ -61,7 +61,7 @@ require (
 	github.com/gogo/googleapis v1.4.1 // indirect
 	github.com/gogo/protobuf v1.3.2 // indirect
 	github.com/golang/protobuf v1.5.2 // indirect
-	github.com/google/go-cmp v0.5.8 // indirect
+	github.com/google/go-cmp v0.5.7 // indirect
 	github.com/google/gofuzz v1.2.0 // indirect
 	github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
 	github.com/gorilla/mux v1.8.0 // indirect
diff --git a/go.sum b/go.sum
index 14a72377b..fd54a183a 100644
--- a/go.sum
+++ b/go.sum
@@ -286,8 +286,8 @@ github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoC
 github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI=
 github.com/codahale/hdrhistogram v0.0.0-20160425231609-f8ad88b59a58/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
 github.com/compose-spec/compose-go v1.2.1/go.mod h1:pAy7Mikpeft4pxkFU565/DRHEbDfR84G6AQuiL+Hdg8=
-github.com/compose-spec/compose-go v1.3.0 h1:n5fSOUXQsfnCpn/lZBgNM3qEu1PDhvcbWrWXVBlUNmA=
-github.com/compose-spec/compose-go v1.3.0/go.mod h1:l7RUULbFFLzlQHuxtJr7SVLyWdqEpbJEGTWCgcu6Eqw=
+github.com/compose-spec/compose-go v1.2.9 h1:+7q2X8gCd16qUX+FU5EPtepK9lWZSGfc8Xe2cGmZqDc=
+github.com/compose-spec/compose-go v1.2.9/go.mod h1:rGaQw1U8uhZhmANQHIocMnQ+qu6ER2+1OwhWjRqQEPI=
 github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE=
 github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU=
 github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU=
@@ -447,9 +447,8 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
 github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
 github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
 github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=
+github.com/distribution/distribution/v3 v3.0.0-20210316161203-a01c71e2477e h1:n81KvOMrLZa+VWHwST7dun9f0G98X3zREHS1ztYzZKU=
 github.com/distribution/distribution/v3 v3.0.0-20210316161203-a01c71e2477e/go.mod h1:xpWTC2KnJMiDLkoawhsPQcXjvwATEBcbq0xevG2YR9M=
-github.com/distribution/distribution/v3 v3.0.0-20220725133111-4bf3547399eb h1:oCCuuU3kMO3sjZH/p7LamvQNW9SWoT4yQuMGcdSxGAE=
-github.com/distribution/distribution/v3 v3.0.0-20220725133111-4bf3547399eb/go.mod h1:28YO/VJk9/64+sTGNuYaBjWxrXTPrj0C0XmgTIOjxX4=
 github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
 github.com/docker/buildx v0.8.2 h1:dsd3F0hhmUydFX/KFrvbK81JvlTA4T3Iy0lwDJt4PsU=
 github.com/docker/buildx v0.8.2/go.mod h1:5sMOfNwOmO2jy/MxBL4ySk2LoLIG1tQFu2EU8wbKa34=
@@ -608,8 +607,8 @@ github.com/gofrs/flock v0.0.0-20190320160742-5135e617513b/go.mod h1:F1TvTiK9OcQq
 github.com/gofrs/flock v0.7.3/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
 github.com/gofrs/flock v0.8.0 h1:MSdYClljsF3PbENUUEx85nkWfJSGfzYI9yEBZOJz6CY=
 github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
+github.com/gofrs/uuid v3.3.0+incompatible h1:8K4tyRfvU1CYPgJsveYFQMhpFd/wXNM7iK6rR7UHz84=
 github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
-github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
 github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU=
 github.com/gogo/googleapis v1.3.2/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c=
 github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c=
@@ -706,9 +705,8 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
 github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
 github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
-github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
-github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 github.com/google/go-containerregistry v0.0.0-20191010200024-a3d713f9b7f8/go.mod h1:KyKXa9ciM8+lgMXwOVsXi7UxGrsf9mM61Mzs+xKUrKE=
 github.com/google/go-containerregistry v0.1.2/go.mod h1:GPivBPgdAyd2SU+vf6EpsgOtWDuPqjW0hJZt4rNdTZ4=
 github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0=
@@ -1677,9 +1675,8 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=
-golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -1915,6 +1912,7 @@ golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0=
 gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
diff --git a/pkg/api/api.go b/pkg/api/api.go
index 30b1ac06e..08f6433d8 100644
--- a/pkg/api/api.go
+++ b/pkg/api/api.go
@@ -445,15 +445,3 @@ const (
 	// UserCancel user cancelled compose up, we are stopping containers
 	UserCancel
 )
-
-// Separator is used for naming components
-var Separator = "-"
-
-// GetImageNameOrDefault computes the default image name for a service, used to tag built images
-func GetImageNameOrDefault(service types.ServiceConfig, projectName string) string {
-	imageName := service.Image
-	if imageName == "" {
-		imageName = projectName + Separator + service.Name
-	}
-	return imageName
-}
diff --git a/pkg/compose/build.go b/pkg/compose/build.go
index 41c85c587..7581a664d 100644
--- a/pkg/compose/build.go
+++ b/pkg/compose/build.go
@@ -64,7 +64,7 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti
 		if service.Build == nil {
 			continue
 		}
-		imageName := api.GetImageNameOrDefault(service, project.Name)
+		imageName := getImageName(service, project.Name)
 		imagesToBuild = append(imagesToBuild, imageName)
 		buildOptions, err := s.toBuildOptions(project, service, imageName, options.SSHs)
 		if err != nil {
@@ -135,13 +135,14 @@ func (s *composeService) ensureImagesExists(ctx context.Context, project *types.
 	}
 	// set digest as com.docker.compose.image label so we can detect outdated containers
 	for i, service := range project.Services {
-		image := api.GetImageNameOrDefault(service, project.Name)
+		image := getImageName(service, project.Name)
 		digest, ok := images[image]
 		if ok {
 			if project.Services[i].Labels == nil {
 				project.Services[i].Labels = types.Labels{}
 			}
 			project.Services[i].CustomLabels[api.ImageDigestLabel] = digest
+			project.Services[i].Image = image
 		}
 	}
 	return nil
@@ -153,7 +154,7 @@ func (s *composeService) getBuildOptions(project *types.Project, images map[stri
 		if service.Image == "" && service.Build == nil {
 			return nil, fmt.Errorf("invalid service %q. Must specify either image or build", service.Name)
 		}
-		imageName := api.GetImageNameOrDefault(service, project.Name)
+		imageName := getImageName(service, project.Name)
 		_, localImagePresent := images[imageName]
 
 		if service.Build != nil {
@@ -175,7 +176,7 @@ func (s *composeService) getBuildOptions(project *types.Project, images map[stri
 func (s *composeService) getLocalImagesDigests(ctx context.Context, project *types.Project) (map[string]string, error) {
 	var imageNames []string
 	for _, s := range project.Services {
-		imgName := api.GetImageNameOrDefault(s, project.Name)
+		imgName := getImageName(s, project.Name)
 		if !utils.StringContains(imageNames, imgName) {
 			imageNames = append(imageNames, imgName)
 		}
@@ -190,7 +191,7 @@ func (s *composeService) getLocalImagesDigests(ctx context.Context, project *typ
 	}
 
 	for i := range project.Services {
-		imgName := api.GetImageNameOrDefault(project.Services[i], project.Name)
+		imgName := getImageName(project.Services[i], project.Name)
 		digest, ok := images[imgName]
 		if ok {
 			project.Services[i].CustomLabels.Add(api.ImageDigestLabel, digest)
diff --git a/pkg/compose/build_classic.go b/pkg/compose/build_classic.go
index dc88dee3f..db5d948e3 100644
--- a/pkg/compose/build_classic.go
+++ b/pkg/compose/build_classic.go
@@ -29,7 +29,6 @@ import (
 	"github.com/compose-spec/compose-go/types"
 	buildx "github.com/docker/buildx/build"
 	"github.com/docker/cli/cli/command/image/build"
-	"github.com/docker/compose/v2/pkg/api"
 	dockertypes "github.com/docker/docker/api/types"
 	"github.com/docker/docker/cli"
 	"github.com/docker/docker/pkg/archive"
@@ -46,7 +45,7 @@ func (s *composeService) doBuildClassic(ctx context.Context, project *types.Proj
 	var nameDigests = make(map[string]string)
 	var errs error
 	err := project.WithServices(nil, func(service types.ServiceConfig) error {
-		imageName := api.GetImageNameOrDefault(service, project.Name)
+		imageName := getImageName(service, project.Name)
 		o, ok := opts[imageName]
 		if !ok {
 			return nil
diff --git a/pkg/compose/compose.go b/pkg/compose/compose.go
index bfd4bdbf1..5f7446e08 100644
--- a/pkg/compose/compose.go
+++ b/pkg/compose/compose.go
@@ -36,6 +36,9 @@ import (
 	"github.com/sanathkr/go-yaml"
 )
 
+// Separator is used for naming components
+var Separator = "-"
+
 // NewComposeService create a local implementation of the compose.Service API
 func NewComposeService(dockerCli command.Cli) api.Service {
 	return &composeService{
diff --git a/pkg/compose/convergence.go b/pkg/compose/convergence.go
index 4489cd2fd..25b021cd8 100644
--- a/pkg/compose/convergence.go
+++ b/pkg/compose/convergence.go
@@ -261,7 +261,7 @@ func mustRecreate(expected types.ServiceConfig, actual moby.Container, policy st
 }
 
 func getContainerName(projectName string, service types.ServiceConfig, number int) string {
-	name := strings.Join([]string{projectName, service.Name, strconv.Itoa(number)}, api.Separator)
+	name := strings.Join([]string{projectName, service.Name, strconv.Itoa(number)}, Separator)
 	if service.ContainerName != "" {
 		name = service.ContainerName
 	}
@@ -553,8 +553,8 @@ func (s composeService) getLinks(ctx context.Context, projectName string, servic
 			containerName := getCanonicalContainerName(c)
 			links = append(links,
 				format(containerName, linkName),
-				format(containerName, linkServiceName+api.Separator+strconv.Itoa(number)),
-				format(containerName, strings.Join([]string{projectName, linkServiceName, strconv.Itoa(number)}, api.Separator)),
+				format(containerName, linkServiceName+Separator+strconv.Itoa(number)),
+				format(containerName, strings.Join([]string{projectName, linkServiceName, strconv.Itoa(number)}, Separator)),
 			)
 		}
 	}
@@ -568,7 +568,7 @@ func (s composeService) getLinks(ctx context.Context, projectName string, servic
 			containerName := getCanonicalContainerName(c)
 			links = append(links,
 				format(containerName, service.Name),
-				format(containerName, strings.TrimPrefix(containerName, projectName+api.Separator)),
+				format(containerName, strings.TrimPrefix(containerName, projectName+Separator)),
 				format(containerName, containerName),
 			)
 		}
diff --git a/pkg/compose/create.go b/pkg/compose/create.go
index 7bc16777c..e0789d1fb 100644
--- a/pkg/compose/create.go
+++ b/pkg/compose/create.go
@@ -227,6 +227,14 @@ func (s *composeService) ensureProjectVolumes(ctx context.Context, project *type
 	return nil
 }
 
+func getImageName(service types.ServiceConfig, projectName string) string {
+	imageName := service.Image
+	if imageName == "" {
+		imageName = projectName + "_" + service.Name
+	}
+	return imageName
+}
+
 func (s *composeService) getCreateOptions(ctx context.Context, p *types.Project, service types.ServiceConfig,
 	number int, inherit *moby.Container, autoRemove bool, attachStdin bool) (*container.Config, *container.HostConfig, *network.NetworkingConfig, error) {
 
@@ -271,7 +279,7 @@ func (s *composeService) getCreateOptions(ctx context.Context, p *types.Project,
 		AttachStderr:    true,
 		AttachStdout:    true,
 		Cmd:             runCmd,
-		Image:           api.GetImageNameOrDefault(service, p.Name),
+		Image:           getImageName(service, p.Name),
 		WorkingDir:      service.WorkingDir,
 		Entrypoint:      entrypoint,
 		NetworkDisabled: service.NetworkMode == "disabled",
@@ -704,7 +712,7 @@ func (s *composeService) buildContainerVolumes(ctx context.Context, p types.Proj
 	inherit *moby.Container) (map[string]struct{}, []string, []mount.Mount, error) {
 	var mounts = []mount.Mount{}
 
-	image := api.GetImageNameOrDefault(service, p.Name)
+	image := getImageName(service, p.Name)
 	imgInspect, _, err := s.apiClient().ImageInspectWithRaw(ctx, image)
 	if err != nil {
 		return nil, nil, nil, err
@@ -719,12 +727,8 @@ func (s *composeService) buildContainerVolumes(ctx context.Context, p types.Proj
 	binds := []string{}
 MOUNTS:
 	for _, m := range mountOptions {
-		if m.Type == mount.TypeNamedPipe {
-			mounts = append(mounts, m)
-			continue
-		}
 		volumeMounts[m.Target] = struct{}{}
-		if m.Type == mount.TypeBind {
+		if m.Type == mount.TypeBind || m.Type == mount.TypeNamedPipe {
 			// `Mount` is preferred but does not offer option to created host path if missing
 			// so `Bind` API is used here with raw volume string
 			// see https://github.com/moby/moby/issues/43483
diff --git a/pkg/compose/down.go b/pkg/compose/down.go
index 4251a8dc1..1ea7b4dcb 100644
--- a/pkg/compose/down.go
+++ b/pkg/compose/down.go
@@ -195,7 +195,7 @@ func (s *composeService) getServiceImages(options api.DownOptions, project *type
 			continue
 		}
 		if image == "" {
-			image = api.GetImageNameOrDefault(service, project.Name)
+			image = getImageName(service, project.Name)
 		}
 		images[image] = struct{}{}
 	}
diff --git a/pkg/compose/run.go b/pkg/compose/run.go
index 93db7bc9d..7b1295ab4 100644
--- a/pkg/compose/run.go
+++ b/pkg/compose/run.go
@@ -114,12 +114,15 @@ func applyRunOptions(project *types.Project, service *types.ServiceConfig, opts
 		service.Entrypoint = opts.Entrypoint
 	}
 	if len(opts.Environment) > 0 {
-		cmdEnv := types.NewMappingWithEquals(opts.Environment)
-		serviceOverrideEnv := cmdEnv.Resolve(func(s string) (string, bool) {
+		env := types.NewMappingWithEquals(opts.Environment)
+		projectEnv := env.Resolve(func(s string) (string, bool) {
+			if _, ok := service.Environment[s]; ok {
+				return "", false
+			}
 			v, ok := project.Environment[s]
 			return v, ok
 		}).RemoveEmpty()
-		service.Environment.OverrideBy(serviceOverrideEnv)
+		service.Environment.OverrideBy(projectEnv)
 	}
 	for k, v := range opts.Labels {
 		service.Labels = service.Labels.Add(k, v)
diff --git a/scripts/validate/fileheader b/scripts/validate/fileheader
index abb30b03f..8b503df36 100755
--- a/scripts/validate/fileheader
+++ b/scripts/validate/fileheader
@@ -1,6 +1,6 @@
 #!/usr/bin/env sh
 
-#   Copyright 2020,2022 Docker Compose CLI authors
+#   Copyright 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.
@@ -16,12 +16,12 @@
 
 set -eu -o pipefail
 
-if ! command -v addlicense; then
-    >&2 echo "ERROR: addlicense not found. Install with:"
-    >&2 echo "    go install -u github.com/google/addlicense@latest"
+if ! command -v ltag; then
+    >&2 echo "ERROR: ltag not found. Install with:"
+    >&2 echo "    go get -u github.com/kunalkushwaha/ltag"
     exit 1
 fi
 
 BASEPATH="${1-}"
 
-find . -regex '.*\.sh' -o -regex '.*\.go' -o -regex '.*Makefile' -o -regex '.*Dockerfile' | xargs addlicense -check -l apache -c 'Docker Compose CLI authors' -ignore validate -ignore testdata -ignore resolvepath -v 1>&2
\ No newline at end of file
+ltag -t "${BASEPATH}scripts/validate/template" -excludes "validate testdata resolvepath" --check -v
\ No newline at end of file


Test patch:
diff --git a/pkg/compose/create_test.go b/pkg/compose/create_test.go
index 4b6140460..7a0e95c6f 100644
--- a/pkg/compose/create_test.go
+++ b/pkg/compose/create_test.go
@@ -22,12 +22,10 @@ import (
 	"sort"
 	"testing"
 
-	"github.com/docker/compose/v2/pkg/api"
-
 	composetypes "github.com/compose-spec/compose-go/types"
+	"github.com/docker/compose/v2/pkg/api"
 	moby "github.com/docker/docker/api/types"
 	mountTypes "github.com/docker/docker/api/types/mount"
-
 	"gotest.tools/v3/assert"
 )
 
@@ -46,18 +44,6 @@ func TestBuildBindMount(t *testing.T) {
 	assert.Equal(t, mount.Type, mountTypes.TypeBind)
 }
 
-func TestBuildNamedPipeMount(t *testing.T) {
-	project := composetypes.Project{}
-	volume := composetypes.ServiceVolumeConfig{
-		Type:   composetypes.VolumeTypeNamedPipe,
-		Source: "\\\\.\\pipe\\docker_engine_windows",
-		Target: "\\\\.\\pipe\\docker_engine",
-	}
-	mount, err := buildMount(project, volume)
-	assert.NilError(t, err)
-	assert.Equal(t, mount.Type, mountTypes.TypeNamedPipe)
-}
-
 func TestBuildVolumeMount(t *testing.T) {
 	project := composetypes.Project{
 		Name: "myProject",
@@ -79,8 +65,8 @@ func TestBuildVolumeMount(t *testing.T) {
 }
 
 func TestServiceImageName(t *testing.T) {
-	assert.Equal(t, api.GetImageNameOrDefault(composetypes.ServiceConfig{Image: "myImage"}, "myProject"), "myImage")
-	assert.Equal(t, api.GetImageNameOrDefault(composetypes.ServiceConfig{Name: "aService"}, "myProject"), "myProject-aService")
+	assert.Equal(t, getImageName(composetypes.ServiceConfig{Image: "myImage"}, "myProject"), "myImage")
+	assert.Equal(t, getImageName(composetypes.ServiceConfig{Name: "aService"}, "myProject"), "myProject_aService")
 }
 
 func TestPrepareNetworkLabels(t *testing.T) {
@@ -111,11 +97,6 @@ func TestBuildContainerMountOptions(t *testing.T) {
 						Type:   composetypes.VolumeTypeVolume,
 						Target: "/var/myvolume2",
 					},
-					{
-						Type:   composetypes.VolumeTypeNamedPipe,
-						Source: "\\\\.\\pipe\\docker_engine_windows",
-						Target: "\\\\.\\pipe\\docker_engine",
-					},
 				},
 			},
 		},
@@ -147,20 +128,18 @@ func TestBuildContainerMountOptions(t *testing.T) {
 		return mounts[i].Target < mounts[j].Target
 	})
 	assert.NilError(t, err)
-	assert.Assert(t, len(mounts) == 3)
+	assert.Assert(t, len(mounts) == 2)
 	assert.Equal(t, mounts[0].Target, "/var/myvolume1")
 	assert.Equal(t, mounts[1].Target, "/var/myvolume2")
-	assert.Equal(t, mounts[2].Target, "\\\\.\\pipe\\docker_engine")
 
 	mounts, err = buildContainerMountOptions(project, project.Services[0], moby.ImageInspect{}, inherit)
 	sort.Slice(mounts, func(i, j int) bool {
 		return mounts[i].Target < mounts[j].Target
 	})
 	assert.NilError(t, err)
-	assert.Assert(t, len(mounts) == 3)
+	assert.Assert(t, len(mounts) == 2)
 	assert.Equal(t, mounts[0].Target, "/var/myvolume1")
 	assert.Equal(t, mounts[1].Target, "/var/myvolume2")
-	assert.Equal(t, mounts[2].Target, "\\\\.\\pipe\\docker_engine")
 }
 
 func TestGetDefaultNetworkMode(t *testing.T) {
diff --git a/pkg/e2e/build_test.go b/pkg/e2e/build_test.go
index 178ed7f9b..154a7e3e1 100644
--- a/pkg/e2e/build_test.go
+++ b/pkg/e2e/build_test.go
@@ -31,30 +31,30 @@ func TestLocalComposeBuild(t *testing.T) {
 
 	t.Run("build named and unnamed images", func(t *testing.T) {
 		// ensure local test run does not reuse previously build image
-		c.RunDockerOrExitError(t, "rmi", "build-test-nginx")
+		c.RunDockerOrExitError(t, "rmi", "build-test_nginx")
 		c.RunDockerOrExitError(t, "rmi", "custom-nginx")
 
 		res := c.RunDockerComposeCmd(t, "--project-directory", "fixtures/build-test", "build")
 
 		res.Assert(t, icmd.Expected{Out: "COPY static /usr/share/nginx/html"})
-		c.RunDockerCmd(t, "image", "inspect", "build-test-nginx")
+		c.RunDockerCmd(t, "image", "inspect", "build-test_nginx")
 		c.RunDockerCmd(t, "image", "inspect", "custom-nginx")
 	})
 
 	t.Run("build with build-arg", func(t *testing.T) {
 		// ensure local test run does not reuse previously build image
-		c.RunDockerOrExitError(t, "rmi", "build-test-nginx")
+		c.RunDockerOrExitError(t, "rmi", "build-test_nginx")
 		c.RunDockerOrExitError(t, "rmi", "custom-nginx")
 
 		c.RunDockerComposeCmd(t, "--project-directory", "fixtures/build-test", "build", "--build-arg", "FOO=BAR")
 
-		res := c.RunDockerCmd(t, "image", "inspect", "build-test-nginx")
+		res := c.RunDockerCmd(t, "image", "inspect", "build-test_nginx")
 		res.Assert(t, icmd.Expected{Out: `"FOO": "BAR"`})
 	})
 
 	t.Run("build with build-arg set by env", func(t *testing.T) {
 		// ensure local test run does not reuse previously build image
-		c.RunDockerOrExitError(t, "rmi", "build-test-nginx")
+		c.RunDockerOrExitError(t, "rmi", "build-test_nginx")
 		c.RunDockerOrExitError(t, "rmi", "custom-nginx")
 
 		icmd.RunCmd(c.NewDockerComposeCmd(t,
@@ -67,20 +67,20 @@ func TestLocalComposeBuild(t *testing.T) {
 				cmd.Env = append(cmd.Env, "FOO=BAR")
 			})
 
-		res := c.RunDockerCmd(t, "image", "inspect", "build-test-nginx")
+		res := c.RunDockerCmd(t, "image", "inspect", "build-test_nginx")
 		res.Assert(t, icmd.Expected{Out: `"FOO": "BAR"`})
 	})
 
 	t.Run("build with multiple build-args ", func(t *testing.T) {
 		// ensure local test run does not reuse previously build image
-		c.RunDockerOrExitError(t, "rmi", "-f", "multi-args-multiargs")
+		c.RunDockerOrExitError(t, "rmi", "-f", "multi-args_multiargs")
 		cmd := c.NewDockerComposeCmd(t, "--project-directory", "fixtures/build-test/multi-args", "build")
 
 		icmd.RunCmd(cmd, func(cmd *icmd.Cmd) {
 			cmd.Env = append(cmd.Env, "DOCKER_BUILDKIT=0")
 		})
 
-		res := c.RunDockerCmd(t, "image", "inspect", "multi-args-multiargs")
+		res := c.RunDockerCmd(t, "image", "inspect", "multi-args_multiargs")
 		res.Assert(t, icmd.Expected{Out: `"RESULT": "SUCCESS"`})
 	})
 
@@ -131,7 +131,7 @@ func TestLocalComposeBuild(t *testing.T) {
 	})
 
 	t.Run("build as part of up", func(t *testing.T) {
-		c.RunDockerOrExitError(t, "rmi", "build-test-nginx")
+		c.RunDockerOrExitError(t, "rmi", "build-test_nginx")
 		c.RunDockerOrExitError(t, "rmi", "custom-nginx")
 
 		res := c.RunDockerComposeCmd(t, "--project-directory", "fixtures/build-test", "up", "-d")
@@ -145,7 +145,7 @@ func TestLocalComposeBuild(t *testing.T) {
 		output := HTTPGetWithRetry(t, "http://localhost:8070", http.StatusOK, 2*time.Second, 20*time.Second)
 		assert.Assert(t, strings.Contains(output, "Hello from Nginx container"))
 
-		c.RunDockerCmd(t, "image", "inspect", "build-test-nginx")
+		c.RunDockerCmd(t, "image", "inspect", "build-test_nginx")
 		c.RunDockerCmd(t, "image", "inspect", "custom-nginx")
 	})
 
@@ -164,7 +164,7 @@ func TestLocalComposeBuild(t *testing.T) {
 
 	t.Run("cleanup build project", func(t *testing.T) {
 		c.RunDockerComposeCmd(t, "--project-directory", "fixtures/build-test", "down")
-		c.RunDockerCmd(t, "rmi", "build-test-nginx")
+		c.RunDockerCmd(t, "rmi", "build-test_nginx")
 		c.RunDockerCmd(t, "rmi", "custom-nginx")
 	})
 }
@@ -216,10 +216,10 @@ func TestBuildImageDependencies(t *testing.T) {
 		t.Cleanup(resetState)
 
 		// the image should NOT exist now
-		res := cli.RunDockerOrExitError(t, "image", "inspect", "build-dependencies-service")
+		res := cli.RunDockerOrExitError(t, "image", "inspect", "build-dependencies_service")
 		res.Assert(t, icmd.Expected{
 			ExitCode: 1,
-			Err:      "Error: No such image: build-dependencies-service",
+			Err:      "Error: No such image: build-dependencies_service",
 		})
 
 		res = cli.RunDockerComposeCmd(t, "build")
@@ -227,8 +227,8 @@ func TestBuildImageDependencies(t *testing.T) {
 
 		res = cli.RunDockerCmd(t,
 			"image", "inspect", "--format={{ index .RepoTags 0 }}",
-			"build-dependencies-service")
-		res.Assert(t, icmd.Expected{Out: "build-dependencies-service:latest"})
+			"build-dependencies_service")
+		res.Assert(t, icmd.Expected{Out: "build-dependencies_service:latest"})
 	}
 
 	t.Run("ClassicBuilder", func(t *testing.T) {
diff --git a/pkg/e2e/compose_environment_test.go b/pkg/e2e/compose_environment_test.go
index c57b58077..3314617c7 100644
--- a/pkg/e2e/compose_environment_test.go
+++ b/pkg/e2e/compose_environment_test.go
@@ -27,196 +27,137 @@ import (
 func TestEnvPriority(t *testing.T) {
 	c := NewParallelCLI(t)
 
+	projectDir := "./fixtures/environment/env-priority"
+
 	t.Run("up", func(t *testing.T) {
 		c.RunDockerOrExitError(t, "rmi", "env-compose-priority")
 		c.RunDockerComposeCmd(t, "-f", "./fixtures/environment/env-priority/compose-with-env.yaml",
-			"up", "-d", "--build")
+			"--project-directory", projectDir, "up", "-d", "--build")
 	})
 
 	// Full options activated
-	// 1. Command Line (docker compose run --env <KEY[=VAL]>)  <-- Result expected (From environment patched by --env-file)
-	// 2. Compose File (service::environment section)
-	// 3. Compose File (service::env_file section file)
-	// 4. Container Image ENV directive
+	// 1. Compose file <-- Result expected
+	// 2. Shell environment variables
+	// 3. Environment file
+	// 4. Dockerfile
 	// 5. Variable is not defined
 	t.Run("compose file priority", func(t *testing.T) {
 		cmd := c.NewDockerComposeCmd(t, "-f", "./fixtures/environment/env-priority/compose-with-env.yaml",
-			"--env-file", "./fixtures/environment/env-priority/.env.override",
-			"run", "--rm", "-e", "WHEREAMI", "env-compose-priority")
+			"--project-directory", projectDir, "--env-file", "./fixtures/environment/env-priority/.env.override", "run",
+			"--rm", "-e", "WHEREAMI", "env-compose-priority")
 		cmd.Env = append(cmd.Env, "WHEREAMI=shell")
 		res := icmd.RunCmd(cmd)
-		assert.Equal(t, strings.TrimSpace(res.Stdout()), "override")
-	})
-
-	// Full options activated
-	// 1. Command Line (docker compose run --env <KEY[=VAL]>)  <-- Result expected
-	// 2. Compose File (service::environment section)
-	// 3. Compose File (service::env_file section file)
-	// 4. Container Image ENV directive
-	// 5. Variable is not defined
-	t.Run("compose file priority", func(t *testing.T) {
-		cmd := c.NewDockerComposeCmd(t, "-f", "./fixtures/environment/env-priority/compose-with-env.yaml",
-			"--env-file", "./fixtures/environment/env-priority/.env.override",
-			"run", "--rm", "-e", "WHEREAMI=shell", "env-compose-priority")
-		res := icmd.RunCmd(cmd)
-		assert.Equal(t, strings.TrimSpace(res.Stdout()), "shell")
+		assert.Equal(t, strings.TrimSpace(res.Stdout()), "Compose File")
 	})
 
 	// No Compose file, all other options
-	// 1. Command Line (docker compose run --env <KEY[=VAL]>)  <-- Result expected (From environment patched by --env-file)
-	// 2. Compose File (service::environment section)
-	// 3. Compose File (service::env_file section file)
-	// 4. Container Image ENV directive
+	// 1. Compose file
+	// 2. Shell environment variables <-- Result expected
+	// 3. Environment file
+	// 4. Dockerfile
 	// 5. Variable is not defined
 	t.Run("shell priority", func(t *testing.T) {
-		cmd := c.NewDockerComposeCmd(t, "-f", "./fixtures/environment/env-priority/compose.yaml",
-			"--env-file", "./fixtures/environment/env-priority/.env.override",
-			"run", "--rm", "-e", "WHEREAMI", "env-compose-priority")
-		cmd.Env = append(cmd.Env, "WHEREAMI=shell")
-		res := icmd.RunCmd(cmd)
-		assert.Equal(t, strings.TrimSpace(res.Stdout()), "override")
-	})
-
-	// No Compose file, all other options with env variable from OS environment
-	// 1. Command Line (docker compose run --env <KEY[=VAL]>)  <-- Result expected (From environment)
-	// 2. Compose File (service::environment section)
-	// 3. Compose File (service::env_file section file)
-	// 4. Container Image ENV directive
-	// 5. Variable is not defined
-	t.Run("shell priority file with default value", func(t *testing.T) {
-		cmd := c.NewDockerComposeCmd(t, "-f", "./fixtures/environment/env-priority/compose.yaml",
-			"--env-file", "./fixtures/environment/env-priority/.env.override.with.default",
-			"run", "--rm", "-e", "WHEREAMI", "env-compose-priority")
+		cmd := c.NewDockerComposeCmd(t, "-f", "./fixtures/environment/env-priority/compose.yaml", "--project-directory",
+			projectDir, "--env-file", "./fixtures/environment/env-priority/.env.override", "run", "--rm", "-e",
+			"WHEREAMI", "env-compose-priority")
 		cmd.Env = append(cmd.Env, "WHEREAMI=shell")
 		res := icmd.RunCmd(cmd)
 		assert.Equal(t, strings.TrimSpace(res.Stdout()), "shell")
 	})
 
-	// No Compose file, all other options with env variable from OS environment
-	// 1. Command Line (docker compose run --env <KEY[=VAL]>)  <-- Result expected (From environment default value from file in --env-file)
-	// 2. Compose File (service::environment section)
-	// 3. Compose File (service::env_file section file)
-	// 4. Container Image ENV directive
-	// 5. Variable is not defined
-	t.Run("shell priority implicitly set", func(t *testing.T) {
-		cmd := c.NewDockerComposeCmd(t, "-f", "./fixtures/environment/env-priority/compose.yaml",
-			"--env-file", "./fixtures/environment/env-priority/.env.override.with.default",
-			"run", "--rm", "-e", "WHEREAMI", "env-compose-priority")
-		res := icmd.RunCmd(cmd)
-		assert.Equal(t, strings.TrimSpace(res.Stdout()), "EnvFileDefaultValue")
-	})
-
-	// No Compose file and env variable pass to the run command
-	// 1. Command Line (docker compose run --env <KEY[=VAL]>)  <-- Result expected
-	// 2. Compose File (service::environment section)
-	// 3. Compose File (service::env_file section file)
-	// 4. Container Image ENV directive
+	//  No Compose file and env variable pass to the run command
+	// 1. Compose file
+	// 2. Shell environment variables <-- Result expected
+	// 3. Environment file
+	// 4. Dockerfile
 	// 5. Variable is not defined
 	t.Run("shell priority from run command", func(t *testing.T) {
-		res := c.RunDockerComposeCmd(t, "-f", "./fixtures/environment/env-priority/compose.yaml",
-			"--env-file", "./fixtures/environment/env-priority/.env.override",
-			"run", "--rm", "-e", "WHEREAMI=shell-run", "env-compose-priority")
+		res := c.RunDockerComposeCmd(t, "-f", "./fixtures/environment/env-priority/compose.yaml", "--project-directory",
+			projectDir, "--env-file", "./fixtures/environment/env-priority/.env.override", "run", "--rm", "-e",
+			"WHEREAMI=shell-run", "env-compose-priority")
 		assert.Equal(t, strings.TrimSpace(res.Stdout()), "shell-run")
 	})
 
-	// No Compose file & no env variable but override env file
-	// 1. Command Line (docker compose run --env <KEY[=VAL]>)  <-- Result expected (From environment patched by .env as a default --env-file value)
-	// 2. Compose File (service::environment section)
-	// 3. Compose File (service::env_file section file)
-	// 4. Container Image ENV directive
-	// 5. Variable is not defined
-	t.Run("override env file from compose", func(t *testing.T) {
-		res := c.RunDockerComposeCmd(t, "-f", "./fixtures/environment/env-priority/compose-with-env-file.yaml",
-			"run", "--rm", "-e", "WHEREAMI", "env-compose-priority")
-		assert.Equal(t, strings.TrimSpace(res.Stdout()), "Env File")
-	})
-
-	// No Compose file & no env variable but override by default env file
-	// 1. Command Line (docker compose run --env <KEY[=VAL]>)  <-- Result expected (From environment patched by --env-file value)
-	// 2. Compose File (service::environment section)
-	// 3. Compose File (service::env_file section file)
-	// 4. Container Image ENV directive
+	//  No Compose file & no env variable but override env file
+	// 1. Compose file
+	// 2. Shell environment variables
+	// 3. Environment file <-- Result expected
+	// 4. Dockerfile
 	// 5. Variable is not defined
 	t.Run("override env file", func(t *testing.T) {
-		res := c.RunDockerComposeCmd(t, "-f", "./fixtures/environment/env-priority/compose.yaml",
-			"--env-file", "./fixtures/environment/env-priority/.env.override",
-			"run", "--rm", "-e", "WHEREAMI", "env-compose-priority")
+		res := c.RunDockerComposeCmd(t, "-f", "./fixtures/environment/env-priority/compose.yaml", "--project-directory",
+			projectDir, "--env-file", "./fixtures/environment/env-priority/.env.override", "run", "--rm", "-e",
+			"WHEREAMI", "env-compose-priority")
 		assert.Equal(t, strings.TrimSpace(res.Stdout()), "override")
 	})
 
-	// No Compose file & no env variable but override env file
-	// 1. Command Line (docker compose run --env <KEY[=VAL]>)  <-- Result expected (From environment patched by --env-file value)
-	// 2. Compose File (service::environment section)
-	// 3. Compose File (service::env_file section file)
-	// 4. Container Image ENV directive
+	//  No Compose file & no env variable but override env file
+	// 1. Compose file
+	// 2. Shell environment variables
+	// 3. Environment file <-- Result expected
+	// 4. Dockerfile
 	// 5. Variable is not defined
 	t.Run("env file", func(t *testing.T) {
-		res := c.RunDockerComposeCmd(t, "-f", "./fixtures/environment/env-priority/compose.yaml",
-			"run", "--rm", "-e", "WHEREAMI", "env-compose-priority")
+		res := c.RunDockerComposeCmd(t, "-f", "./fixtures/environment/env-priority/compose.yaml", "--project-directory",
+			projectDir, "run", "--rm", "-e", "WHEREAMI", "env-compose-priority")
 		assert.Equal(t, strings.TrimSpace(res.Stdout()), "Env File")
 	})
 
-	// No Compose file & no env variable, using an empty override env file
-	// 1. Command Line (docker compose run --env <KEY[=VAL]>)
-	// 2. Compose File (service::environment section)
-	// 3. Compose File (service::env_file section file)
-	// 4. Container Image ENV directive <-- Result expected
+	//  No Compose file & no env variable, using an empty override env file
+	// 1. Compose file
+	// 2. Shell environment variables
+	// 3. Environment file
+	// 4. Dockerfile   <-- Result expected
 	// 5. Variable is not defined
 	t.Run("use Dockerfile", func(t *testing.T) {
-		res := c.RunDockerComposeCmd(t, "-f", "./fixtures/environment/env-priority/compose.yaml",
-			"--env-file", "./fixtures/environment/env-priority/.env.empty",
-			"run", "--rm", "-e", "WHEREAMI", "env-compose-priority")
+		res := c.RunDockerComposeCmd(t, "-f", "./fixtures/environment/env-priority/compose.yaml", "--project-directory",
+			projectDir, "--env-file", "./fixtures/environment/env-priority/.env.empty", "run", "--rm", "-e", "WHEREAMI",
+			"env-compose-priority")
 		assert.Equal(t, strings.TrimSpace(res.Stdout()), "Dockerfile")
 	})
 
 	t.Run("down", func(t *testing.T) {
-		c.RunDockerComposeCmd(t, "--project-name", "env-priority", "down")
+		c.RunDockerComposeCmd(t, "--project-directory", projectDir, "down")
 	})
 }
 
 func TestEnvInterpolation(t *testing.T) {
 	c := NewParallelCLI(t)
 
-	// No variable defined in the Compose file and nor env variable pass to the run command
-	// 1. Command Line (docker compose run --env <KEY[=VAL]>)
-	// 2. Compose File (service::environment section) <-- Result expected (From environment patched by .env as a default --env-file value)
-	// 3. Compose File (service::env_file section file)
-	// 4. Container Image ENV directive
+	projectDir := "./fixtures/environment/env-interpolation"
+
+	//  No variable defined in the Compose file and env variable pass to the run command
+	// 1. Compose file
+	// 2. Shell environment variables <-- Result expected
+	// 3. Environment file
+	// 4. Dockerfile
 	// 5. Variable is not defined
 	t.Run("shell priority from run command", func(t *testing.T) {
-		cmd := c.NewDockerComposeCmd(t, "-f", "./fixtures/environment/env-interpolation/compose.yaml", "config")
+		cmd := c.NewDockerComposeCmd(t, "-f", "./fixtures/environment/env-interpolation/compose.yaml",
+			"--project-directory", projectDir, "config")
 		cmd.Env = append(cmd.Env, "WHEREAMI=shell")
 		res := icmd.RunCmd(cmd)
-		res.Assert(t, icmd.Expected{Out: `IMAGE: default_env:EnvFile`})
-	})
-
-	// No variable defined in the Compose file and env variable pass to the run command
-	// 1. Command Line (docker compose run --env <KEY[=VAL]>)
-	// 2. Compose File (service::environment section) <-- Result expected (From environment patched by .env as a default --env-file value.
-	// This variable has a default value in case of an absent variable in the OS environment)
-	// 3. Compose File (service::env_file section file)
-	// 4. Container Image ENV directive
-	// 5. Variable is not defined
-	t.Run("shell priority from run command using default value fallback", func(t *testing.T) {
-		c.RunDockerComposeCmd(t, "-f", "./fixtures/environment/env-interpolation-default-value/compose.yaml", "config").
-			Assert(t, icmd.Expected{Out: `IMAGE: default_env:EnvFileDefaultValue`})
+		res.Assert(t, icmd.Expected{Out: `IMAGE: default_env:shell`})
 	})
 }
 
 func TestCommentsInEnvFile(t *testing.T) {
 	c := NewParallelCLI(t)
 
+	projectDir := "./fixtures/environment/env-file-comments"
+
 	t.Run("comments in env files", func(t *testing.T) {
 		c.RunDockerOrExitError(t, "rmi", "env-file-comments")
 
-		c.RunDockerComposeCmd(t, "-f", "./fixtures/environment/env-file-comments/compose.yaml", "up", "-d", "--build")
+		c.RunDockerComposeCmd(t, "-f", "./fixtures/environment/env-file-comments/compose.yaml", "--project-directory",
+			projectDir, "up", "-d", "--build")
 
 		res := c.RunDockerComposeCmd(t, "-f", "./fixtures/environment/env-file-comments/compose.yaml",
-			"run", "--rm", "-e", "COMMENT", "-e", "NO_COMMENT", "env-file-comments")
+			"--project-directory", projectDir, "run", "--rm", "-e", "COMMENT", "-e", "NO_COMMENT", "env-file-comments")
 
 		res.Assert(t, icmd.Expected{Out: `COMMENT=1234`})
 		res.Assert(t, icmd.Expected{Out: `NO_COMMENT=1234#5`})
 
-		c.RunDockerComposeCmd(t, "--project-name", "env-file-comments", "down", "--rmi", "all")
+		c.RunDockerComposeCmd(t, "--project-directory", projectDir, "down", "--rmi", "all")
 	})
 }
diff --git a/pkg/e2e/compose_test.go b/pkg/e2e/compose_test.go
index 0e591c44b..fd430488d 100644
--- a/pkg/e2e/compose_test.go
+++ b/pkg/e2e/compose_test.go
@@ -49,7 +49,7 @@ func TestLocalComposeUp(t *testing.T) {
 		assert.Assert(t, strings.Contains(output, `"word":`))
 
 		res = c.RunDockerCmd(t, "network", "ls")
-		res.Assert(t, icmd.Expected{Out: projectName + "-default"})
+		res.Assert(t, icmd.Expected{Out: projectName + "_default"})
 	})
 
 	t.Run("top", func(t *testing.T) {
@@ -74,7 +74,7 @@ func TestLocalComposeUp(t *testing.T) {
 		res.Assert(t, icmd.Expected{Out: `"com.docker.compose.service": "web"`})
 		res.Assert(t, icmd.Expected{Out: `"com.docker.compose.version":`})
 
-		res = c.RunDockerCmd(t, "network", "inspect", projectName+"-default")
+		res = c.RunDockerCmd(t, "network", "inspect", projectName+"_default")
 		res.Assert(t, icmd.Expected{Out: `"com.docker.compose.network": "default"`})
 		res.Assert(t, icmd.Expected{Out: `"com.docker.compose.project": `})
 		res.Assert(t, icmd.Expected{Out: `"com.docker.compose.version": `})
@@ -134,7 +134,7 @@ func TestDownComposefileInParentFolder(t *testing.T) {
 
 	tmpFolder, err := os.MkdirTemp("fixtures/simple-composefile", "test-tmp")
 	assert.NilError(t, err)
-	defer os.Remove(tmpFolder) // nolint: errcheck
+	defer os.Remove(tmpFolder) //nolint: errcheck
 	projectName := filepath.Base(tmpFolder)
 
 	res := c.RunDockerComposeCmd(t, "--project-directory", tmpFolder, "up", "-d")
@@ -241,6 +241,6 @@ func TestConvert(t *testing.T) {
       default: null
 networks:
   default:
-    name: compose-e2e-convert-default`, filepath.Join(wd, "fixtures", "simple-build-test", "nginx-build")), ExitCode: 0})
+    name: compose-e2e-convert_default`, filepath.Join(wd, "fixtures", "simple-build-test", "nginx-build")), ExitCode: 0})
 	})
 }
diff --git a/pkg/e2e/fixtures/environment/env-interpolation-default-value/.env b/pkg/e2e/fixtures/environment/env-interpolation-default-value/.env
deleted file mode 100644
index 79a91230a..000000000
--- a/pkg/e2e/fixtures/environment/env-interpolation-default-value/.env
+++ /dev/null
@@ -1,1 +0,0 @@
-IMAGE=default_env:${WHEREAMI:-EnvFileDefaultValue}
diff --git a/pkg/e2e/fixtures/environment/env-interpolation-default-value/compose.yaml b/pkg/e2e/fixtures/environment/env-interpolation-default-value/compose.yaml
deleted file mode 100644
index 4d02fcdaa..000000000
--- a/pkg/e2e/fixtures/environment/env-interpolation-default-value/compose.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-services:
-  env-interpolation:
-    image: bash
-    environment:
-      IMAGE: ${IMAGE}
-    command: echo "$IMAGE"
diff --git a/pkg/e2e/fixtures/environment/env-interpolation/.env b/pkg/e2e/fixtures/environment/env-interpolation/.env
index b3a1dfee3..87bc8ee70 100644
--- a/pkg/e2e/fixtures/environment/env-interpolation/.env
+++ b/pkg/e2e/fixtures/environment/env-interpolation/.env
@@ -1,2 +1,2 @@
-WHEREAMI=EnvFile
-IMAGE=default_env:${WHEREAMI}
+WHEREAMI=Env File
+IMAGE=default_env:${WHEREAMI}
\ No newline at end of file
diff --git a/pkg/e2e/fixtures/environment/env-priority/.env.override.with.default b/pkg/e2e/fixtures/environment/env-priority/.env.override.with.default
deleted file mode 100644
index 35258b20f..000000000
--- a/pkg/e2e/fixtures/environment/env-priority/.env.override.with.default
+++ /dev/null
@@ -1,1 +0,0 @@
-WHEREAMI=${WHEREAMI:-EnvFileDefaultValue}
diff --git a/pkg/e2e/fixtures/environment/env-priority/compose-with-env-file.yaml b/pkg/e2e/fixtures/environment/env-priority/compose-with-env-file.yaml
deleted file mode 100644
index 4659830f2..000000000
--- a/pkg/e2e/fixtures/environment/env-priority/compose-with-env-file.yaml
+++ /dev/null
@@ -1,7 +0,0 @@
-services:
-  env-compose-priority:
-    image: env-compose-priority
-    build:
-      context: .
-    env_file:
-      - .env.override
diff --git a/pkg/e2e/fixtures/project-volume-bind-test/docker-compose.yml b/pkg/e2e/fixtures/project-volume-bind-test/docker-compose.yml
index 7e1795719..aba0bf47e 100644
--- a/pkg/e2e/fixtures/project-volume-bind-test/docker-compose.yml
+++ b/pkg/e2e/fixtures/project-volume-bind-test/docker-compose.yml
@@ -3,10 +3,10 @@ services:
     image: nginx
     container_name: frontend
     volumes:
-      - project-data:/data
+      - project_data:/data
 
 volumes:
-  project-data:
+  project_data:
     driver: local
     driver_opts:
       type: none
diff --git a/pkg/e2e/networks_test.go b/pkg/e2e/networks_test.go
index c7920b417..2fa84bd6b 100644
--- a/pkg/e2e/networks_test.go
+++ b/pkg/e2e/networks_test.go
@@ -17,7 +17,6 @@
 package e2e
 
 import (
-	"fmt"
 	"net/http"
 	"strings"
 	"testing"
@@ -31,10 +30,10 @@ func TestNetworks(t *testing.T) {
 	// fixture is shared with TestNetworkModes and is not safe to run concurrently
 	c := NewCLI(t)
 
-	const projectName = "network-e2e"
+	const projectName = "network_e2e"
 
 	t.Run("ensure we do not reuse previous networks", func(t *testing.T) {
-		c.RunDockerOrExitError(t, "network", "rm", projectName+"-dbnet")
+		c.RunDockerOrExitError(t, "network", "rm", projectName+"_dbnet")
 		c.RunDockerOrExitError(t, "network", "rm", "microservices")
 	})
 
@@ -52,7 +51,7 @@ func TestNetworks(t *testing.T) {
 		assert.Assert(t, strings.Contains(output, `"word":`))
 
 		res = c.RunDockerCmd(t, "network", "ls")
-		res.Assert(t, icmd.Expected{Out: projectName + "-dbnet"})
+		res.Assert(t, icmd.Expected{Out: projectName + "_dbnet"})
 		res.Assert(t, icmd.Expected{Out: "microservices"})
 	})
 
@@ -126,7 +125,7 @@ func TestIPAMConfig(t *testing.T) {
 	const projectName = "ipam_e2e"
 
 	t.Run("ensure we do not reuse previous networks", func(t *testing.T) {
-		c.RunDockerOrExitError(t, "network", "rm", projectName+"-default")
+		c.RunDockerOrExitError(t, "network", "rm", projectName+"_default")
 	})
 
 	t.Run("up", func(t *testing.T) {
@@ -135,7 +134,7 @@ func TestIPAMConfig(t *testing.T) {
 
 	t.Run("ensure service get fixed IP assigned", func(t *testing.T) {
 		res := c.RunDockerCmd(t, "inspect", projectName+"-foo-1", "-f",
-			fmt.Sprintf(`{{ $network := index .NetworkSettings.Networks "%s-default" }}{{ $network.IPAMConfig.IPv4Address }}`, projectName))
+			"{{ .NetworkSettings.Networks."+projectName+"_default.IPAddress }}")
 		res.Assert(t, icmd.Expected{Out: "10.1.0.100"})
 	})
 
diff --git a/pkg/e2e/scan_message_test.go b/pkg/e2e/scan_message_test.go
index 789eda0a6..4204ef3d2 100644
--- a/pkg/e2e/scan_message_test.go
+++ b/pkg/e2e/scan_message_test.go
@@ -37,7 +37,7 @@ func TestDisplayScanMessageAfterBuild(t *testing.T) {
 	t.Run("display on compose build", func(t *testing.T) {
 		res := c.RunDockerComposeCmd(t, "-f", "fixtures/simple-build-test/compose.yaml", "-p",
 			"scan-msg-test-compose-build", "build")
-		defer c.RunDockerOrExitError(t, "rmi", "-f", "scan-msg-test-compose-build-nginx")
+		defer c.RunDockerOrExitError(t, "rmi", "-f", "scan-msg-test-compose-build_nginx")
 		res.Assert(t, icmd.Expected{Err: utils.ScanSuggestMsg})
 	})
 
@@ -45,16 +45,16 @@ func TestDisplayScanMessageAfterBuild(t *testing.T) {
 		res := c.RunDockerComposeCmd(t, "-f", "fixtures/simple-build-test/compose.yaml", "-p", "scan-msg-test-quiet",
 			"build", "--quiet")
 		assert.Assert(t, !strings.Contains(res.Combined(), "docker scan"), res.Combined())
-		res = c.RunDockerCmd(t, "rmi", "-f", "scan-msg-test-quiet-nginx")
+		res = c.RunDockerCmd(t, "rmi", "-f", "scan-msg-test-quiet_nginx")
 		assert.Assert(t, !strings.Contains(res.Combined(), "No such image"))
 
 		res = c.RunDockerComposeCmd(t, "-f", "fixtures/simple-build-test/compose.yaml", "-p", "scan-msg-test-q",
 			"build", "-q")
-		defer c.RunDockerOrExitError(t, "rmi", "-f", "scan-msg-test-q-nginx")
+		defer c.RunDockerOrExitError(t, "rmi", "-f", "scan-msg-test-q_nginx")
 		assert.Assert(t, !strings.Contains(res.Combined(), "docker scan"), res.Combined())
 	})
 
-	_ = c.RunDockerOrExitError(t, "rmi", "scan-msg-test-nginx")
+	_ = c.RunDockerOrExitError(t, "rmi", "scan-msg-test_nginx")
 
 	t.Run("display on compose up if image is built", func(t *testing.T) {
 		res := c.RunDockerComposeCmd(t, "-f", "fixtures/simple-build-test/compose.yaml", "-p", "scan-msg-test", "up",
diff --git a/pkg/e2e/volumes_test.go b/pkg/e2e/volumes_test.go
index fc6cd31c1..c07bfaadb 100644
--- a/pkg/e2e/volumes_test.go
+++ b/pkg/e2e/volumes_test.go
@@ -35,8 +35,8 @@ func TestLocalComposeVolume(t *testing.T) {
 
 	t.Run("up with build and no image name, volume", func(t *testing.T) {
 		// ensure local test run does not reuse previously build image
-		c.RunDockerOrExitError(t, "rmi", "compose-e2e-volume-nginx")
-		c.RunDockerOrExitError(t, "volume", "rm", projectName+"-staticVol")
+		c.RunDockerOrExitError(t, "rmi", "compose-e2e-volume_nginx")
+		c.RunDockerOrExitError(t, "volume", "rm", projectName+"_staticVol")
 		c.RunDockerOrExitError(t, "volume", "rm", "myvolume")
 		c.RunDockerComposeCmd(t, "--project-directory", "fixtures/volume-test", "--project-name", projectName, "up",
 			"-d")
@@ -88,7 +88,7 @@ func TestLocalComposeVolume(t *testing.T) {
 	t.Run("cleanup volume project", func(t *testing.T) {
 		c.RunDockerComposeCmd(t, "--project-name", projectName, "down", "--volumes")
 		ls := c.RunDockerCmd(t, "volume", "ls").Stdout()
-		assert.Assert(t, !strings.Contains(ls, projectName+"-staticVol"))
+		assert.Assert(t, !strings.Contains(ls, projectName+"_staticVol"))
 		assert.Assert(t, !strings.Contains(ls, "myvolume"))
 	})
 }
@@ -107,7 +107,7 @@ func TestProjectVolumeBind(t *testing.T) {
 
 		c.RunDockerComposeCmd(t, "--project-name", projectName, "down")
 
-		c.RunDockerOrExitError(t, "volume", "rm", "-f", projectName+"-project-data").Assert(t, icmd.Success)
+		c.RunDockerOrExitError(t, "volume", "rm", "-f", projectName+"_project_data").Assert(t, icmd.Success)
 		cmd := c.NewCmdWithEnv([]string{"TEST_DIR=" + tmpDir},
 			"docker", "compose", "--project-directory", "fixtures/project-volume-bind-test", "--project-name", projectName, "up", "-d")
 		icmd.RunCmd(cmd).Assert(t, icmd.Success)