diff --git a/api/compose/api.go b/api/compose/api.go
index a144ea546..2c927d6ca 100644
--- a/api/compose/api.go
+++ b/api/compose/api.go
@@ -19,6 +19,7 @@ package compose
 import (
 	"context"
 	"io"
+	"strings"
 	"time"
 
 	"github.com/compose-spec/compose-go/types"
@@ -130,20 +131,38 @@ type RemoveOptions struct {
 
 // RunOptions options to execute compose run
 type RunOptions struct {
-	Service    string
-	Command    []string
-	Detach     bool
-	AutoRemove bool
-	Writer     io.Writer
-	Reader     io.Reader
-
-	// used by exec
+	Name        string
+	Service     string
+	Command     []string
+	Entrypoint  []string
+	Detach      bool
+	AutoRemove  bool
+	Writer      io.Writer
+	Reader      io.Reader
 	Tty         bool
 	WorkingDir  string
 	User        string
 	Environment []string
+	Labels      types.Labels
 	Privileged  bool
-	Index       int
+	// used by exec
+	Index int
+}
+
+// EnvironmentMap return RunOptions.Environment as a MappingWithEquals
+func (opts *RunOptions) EnvironmentMap() types.MappingWithEquals {
+	environment := types.MappingWithEquals{}
+	for _, s := range opts.Environment {
+		parts := strings.SplitN(s, "=", 2)
+		key := parts[0]
+		switch {
+		case len(parts) == 1:
+			environment[key] = nil
+		default:
+			environment[key] = &parts[1]
+		}
+	}
+	return environment
 }
 
 // PsOptions group options of the Ps API
diff --git a/api/compose/api_test.go b/api/compose/api_test.go
new file mode 100644
index 000000000..ddbe25d6a
--- /dev/null
+++ b/api/compose/api_test.go
@@ -0,0 +1,37 @@
+/*
+   Copyright 2020 Docker Compose CLI authors
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+package compose
+
+import (
+	"testing"
+
+	"gotest.tools/v3/assert"
+)
+
+func TestRunOptionsEnvironmentMap(t *testing.T) {
+	opts := RunOptions{
+		Environment: []string{
+			"FOO=BAR",
+			"ZOT=",
+			"QIX",
+		},
+	}
+	env := opts.EnvironmentMap()
+	assert.Equal(t, *env["FOO"], "BAR")
+	assert.Equal(t, *env["ZOT"], "")
+	assert.Check(t, env["QIX"] == nil)
+}
diff --git a/cli/cmd/compose/run.go b/cli/cmd/compose/run.go
index b94bbc948..ea27368ad 100644
--- a/cli/cmd/compose/run.go
+++ b/cli/cmd/compose/run.go
@@ -18,9 +18,12 @@ package compose
 
 import (
 	"context"
+	"fmt"
 	"os"
+	"strings"
 
 	"github.com/compose-spec/compose-go/types"
+	"github.com/mattn/go-shellwords"
 	"github.com/spf13/cobra"
 
 	"github.com/docker/compose-cli/api/client"
@@ -33,9 +36,15 @@ type runOptions struct {
 	*composeOptions
 	Service     string
 	Command     []string
-	Environment []string
+	environment []string
 	Detach      bool
 	Remove      bool
+	noTty       bool
+	user        string
+	workdir     string
+	entrypoint  string
+	labels      []string
+	name        string
 }
 
 func runCommand(p *projectOptions) *cobra.Command {
@@ -44,7 +53,7 @@ func runCommand(p *projectOptions) *cobra.Command {
 			projectOptions: p,
 		},
 	}
-	runCmd := &cobra.Command{
+	cmd := &cobra.Command{
 		Use:   "run [options] [-v VOLUME...] [-p PORT...] [-e KEY=VAL...] [-l KEY=VALUE...] SERVICE [COMMAND] [ARGS...]",
 		Short: "Run a one-off command on a service.",
 		Args:  cobra.MinimumNArgs(1),
@@ -56,12 +65,19 @@ func runCommand(p *projectOptions) *cobra.Command {
 			return runRun(cmd.Context(), opts)
 		},
 	}
-	runCmd.Flags().BoolVarP(&opts.Detach, "detach", "d", false, "Run container in background and print container ID")
-	runCmd.Flags().StringArrayVarP(&opts.Environment, "env", "e", []string{}, "Set environment variables")
-	runCmd.Flags().BoolVar(&opts.Remove, "rm", false, "Automatically remove the container when it exits")
+	flags := cmd.Flags()
+	flags.BoolVarP(&opts.Detach, "detach", "d", false, "Run container in background and print container ID")
+	flags.StringArrayVarP(&opts.environment, "env", "e", []string{}, "Set environment variables")
+	flags.StringArrayVarP(&opts.labels, "labels", "l", []string{}, "Add or override a label")
+	flags.BoolVar(&opts.Remove, "rm", false, "Automatically remove the container when it exits")
+	flags.BoolVarP(&opts.noTty, "no-TTY", "T", false, "Disable pseudo-tty allocation. By default docker compose run allocates a TTY")
+	flags.StringVar(&opts.name, "name", "", " Assign a name to the container")
+	flags.StringVarP(&opts.user, "user", "u", "", "Run as specified username or uid")
+	flags.StringVarP(&opts.workdir, "workdir", "w", "", "Working directory inside the container")
+	flags.StringVar(&opts.entrypoint, "entrypoint", "", "Override the entrypoint of the image")
 
-	runCmd.Flags().SetInterspersed(false)
-	return runCmd
+	flags.SetInterspersed(false)
+	return cmd
 }
 
 func runRun(ctx context.Context, opts runOptions) error {
@@ -77,14 +93,39 @@ func runRun(ctx context.Context, opts runOptions) error {
 		return err
 	}
 
+	var entrypoint []string
+	if opts.entrypoint != "" {
+		entrypoint, err = shellwords.Parse(opts.entrypoint)
+		if err != nil {
+			return err
+		}
+	}
+
+	labels := types.Labels{}
+	for _, s := range opts.labels {
+		parts := strings.SplitN(s, "=", 2)
+		if len(parts) != 2 {
+			return fmt.Errorf("label must be set as KEY=VALUE")
+		}
+		labels[parts[0]] = parts[1]
+	}
+
 	// start container and attach to container streams
 	runOpts := compose.RunOptions{
-		Service:    opts.Service,
-		Command:    opts.Command,
-		Detach:     opts.Detach,
-		AutoRemove: opts.Remove,
-		Writer:     os.Stdout,
-		Reader:     os.Stdin,
+		Name:        opts.name,
+		Service:     opts.Service,
+		Command:     opts.Command,
+		Detach:      opts.Detach,
+		AutoRemove:  opts.Remove,
+		Writer:      os.Stdout,
+		Reader:      os.Stdin,
+		Tty:         !opts.noTty,
+		WorkingDir:  opts.workdir,
+		User:        opts.user,
+		Environment: opts.environment,
+		Entrypoint:  entrypoint,
+		Labels:      labels,
+		Index:       0,
 	}
 	exitCode, err := c.ComposeService().RunOneOffContainer(ctx, project, runOpts)
 	if exitCode != 0 {
diff --git a/go.mod b/go.mod
index 22188f73e..6926a55c0 100644
--- a/go.mod
+++ b/go.mod
@@ -39,6 +39,7 @@ require (
 	github.com/joho/godotenv v1.3.0
 	github.com/labstack/echo v3.3.10+incompatible
 	github.com/labstack/gommon v0.3.0 // indirect
+	github.com/mattn/go-shellwords v1.0.11
 	github.com/moby/buildkit v0.8.1-0.20201205083753-0af7b1b9c693
 	github.com/moby/term v0.0.0-20201110203204-bea5bbe245bf
 	github.com/morikuni/aec v1.0.0
diff --git a/local/compose/run.go b/local/compose/run.go
index bd9c7b9f4..9f093d4de 100644
--- a/local/compose/run.go
+++ b/local/compose/run.go
@@ -30,37 +30,32 @@ import (
 )
 
 func (s *composeService) RunOneOffContainer(ctx context.Context, project *types.Project, opts compose.RunOptions) (int, error) {
-	originalServices := project.Services
-	var requestedService types.ServiceConfig
-	for _, service := range originalServices {
-		if service.Name == opts.Service {
-			requestedService = service
-		}
+	service, err := project.GetService(opts.Service)
+	if err != nil {
+		return 0, err
 	}
 
-	project.Services = originalServices
-	if len(opts.Command) > 0 {
-		requestedService.Command = opts.Command
-	}
-	requestedService.Scale = 1
-	requestedService.Tty = true
-	requestedService.StdinOpen = true
+	applyRunOptions(&service, opts)
 
 	slug := moby.GenerateRandomID()
-	requestedService.ContainerName = fmt.Sprintf("%s_%s_run_%s", project.Name, requestedService.Name, moby.TruncateID(slug))
-	requestedService.Labels = requestedService.Labels.Add(slugLabel, slug)
-	requestedService.Labels = requestedService.Labels.Add(oneoffLabel, "True")
+	if service.ContainerName == "" {
+		service.ContainerName = fmt.Sprintf("%s_%s_run_%s", project.Name, service.Name, moby.TruncateID(slug))
+	}
+	service.Scale = 1
+	service.StdinOpen = true
+	service.Labels = service.Labels.Add(slugLabel, slug)
+	service.Labels = service.Labels.Add(oneoffLabel, "True")
 
-	if err := s.ensureImagesExists(ctx, project); err != nil { // all dependencies already checked, but might miss requestedService img
+	if err := s.ensureImagesExists(ctx, project); err != nil { // all dependencies already checked, but might miss service img
 		return 0, err
 	}
-	if err := s.waitDependencies(ctx, project, requestedService); err != nil {
+	if err := s.waitDependencies(ctx, project, service); err != nil {
 		return 0, err
 	}
-	if err := s.createContainer(ctx, project, requestedService, requestedService.ContainerName, 1, opts.AutoRemove); err != nil {
+	if err := s.createContainer(ctx, project, service, service.ContainerName, 1, opts.AutoRemove); err != nil {
 		return 0, err
 	}
-	containerID := requestedService.ContainerName
+	containerID := service.ContainerName
 
 	if opts.Detach {
 		err := s.apiClient.ContainerStart(ctx, containerID, apitypes.ContainerStartOptions{})
@@ -81,7 +76,7 @@ func (s *composeService) RunOneOffContainer(ctx context.Context, project *types.
 		return 0, err
 	}
 	oneoffContainer := containers[0]
-	err = s.attachContainerStreams(ctx, oneoffContainer, true, opts.Reader, opts.Writer)
+	err = s.attachContainerStreams(ctx, oneoffContainer, service.Tty, opts.Reader, opts.Writer)
 	if err != nil {
 		return 0, err
 	}
@@ -100,3 +95,27 @@ func (s *composeService) RunOneOffContainer(ctx context.Context, project *types.
 	}
 
 }
+
+func applyRunOptions(service *types.ServiceConfig, opts compose.RunOptions) {
+	service.Tty = opts.Tty
+	service.ContainerName = opts.Name
+
+	if len(opts.Command) > 0 {
+		service.Command = opts.Command
+	}
+	if len(opts.User) > 0 {
+		service.User = opts.User
+	}
+	if len(opts.WorkingDir) > 0 {
+		service.WorkingDir = opts.WorkingDir
+	}
+	if len(opts.Entrypoint) > 0 {
+		service.Entrypoint = opts.Entrypoint
+	}
+	if len(opts.Environment) > 0 {
+		service.Environment.OverrideBy(opts.EnvironmentMap())
+	}
+	for k, v := range opts.Labels {
+		service.Labels.Add(k, v)
+	}
+}