github.com/containerd/nerdctl@v1.7.7/cmd/nerdctl/compose_run.go (about) 1 /* 2 Copyright The containerd Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package main 18 19 import ( 20 "errors" 21 "fmt" 22 23 "github.com/containerd/nerdctl/pkg/clientutil" 24 "github.com/containerd/nerdctl/pkg/cmd/compose" 25 "github.com/containerd/nerdctl/pkg/composer" 26 "github.com/spf13/cobra" 27 ) 28 29 func newComposeRunCommand() *cobra.Command { 30 var composeRunCommand = &cobra.Command{ 31 Use: "run [flags] SERVICE [COMMAND] [ARGS...]", 32 Short: "Run a one-off command on a service", 33 Args: cobra.MinimumNArgs(1), 34 RunE: composeRunAction, 35 SilenceUsage: true, 36 SilenceErrors: true, 37 DisableFlagsInUseLine: true, 38 } 39 composeRunCommand.Flags().SetInterspersed(false) 40 composeRunCommand.Flags().BoolP("detach", "d", false, "Detached mode: Run containers in the background") 41 composeRunCommand.Flags().Bool("no-build", false, "Don't build an image, even if it's missing.") 42 composeRunCommand.Flags().Bool("no-color", false, "Produce monochrome output") 43 composeRunCommand.Flags().Bool("no-log-prefix", false, "Don't print prefix in logs") 44 composeRunCommand.Flags().Bool("build", false, "Build images before starting containers.") 45 composeRunCommand.Flags().Bool("quiet-pull", false, "Pull without printing progress information") 46 composeRunCommand.Flags().Bool("remove-orphans", false, "Remove containers for services not defined in the Compose file.") 47 48 composeRunCommand.Flags().String("name", "", "Assign a name to the container") 49 composeRunCommand.Flags().Bool("no-deps", false, "Don't start dependencies") 50 // TODO: no-TTY flag 51 // In docker-compose's documentation, no-TTY is automatically detected 52 // But, it follows `-i` flag because currently `run` command needs `-it` simultaneously. 53 composeRunCommand.Flags().BoolP("interactive", "i", true, "Keep STDIN open even if not attached") 54 composeRunCommand.Flags().Bool("rm", false, "Automatically remove the container when it exits") 55 composeRunCommand.Flags().StringP("user", "u", "", "Username or UID (format: <name|uid>[:<group|gid>])") 56 composeRunCommand.Flags().StringArrayP("volume", "v", nil, "Bind mount a volume") 57 composeRunCommand.Flags().StringArray("entrypoint", nil, "Overwrite the default ENTRYPOINT of the image") 58 composeRunCommand.Flags().StringArrayP("env", "e", nil, "Set environment variables") 59 composeRunCommand.Flags().StringArrayP("label", "l", nil, "Set metadata on container") 60 composeRunCommand.Flags().StringP("workdir", "w", "", "Working directory inside the container") 61 // FIXME: `-p` conflicts with the `--project-name` in PersistentFlags of parent command `compose` 62 // For docker compatibility, it should be fixed. 63 composeRunCommand.Flags().StringSlice("publish", nil, "Publish a container's port(s) to the host") 64 composeRunCommand.Flags().Bool("service-ports", false, "Run command with the service's ports enabled and mapped to the host") 65 // TODO: use-aliases 66 67 return composeRunCommand 68 } 69 70 func composeRunAction(cmd *cobra.Command, args []string) error { 71 globalOptions, err := processRootCmdFlags(cmd) 72 if err != nil { 73 return err 74 } 75 detach, err := cmd.Flags().GetBool("detach") 76 if err != nil { 77 return err 78 } 79 noBuild, err := cmd.Flags().GetBool("no-build") 80 if err != nil { 81 return err 82 } 83 noColor, err := cmd.Flags().GetBool("no-color") 84 if err != nil { 85 return err 86 } 87 noLogPrefix, err := cmd.Flags().GetBool("no-log-prefix") 88 if err != nil { 89 return err 90 } 91 build, err := cmd.Flags().GetBool("build") 92 if err != nil { 93 return err 94 } 95 if build && noBuild { 96 return errors.New("--build and --no-build can not be combined") 97 } 98 quietPull, err := cmd.Flags().GetBool("quiet-pull") 99 if err != nil { 100 return err 101 } 102 removeOrphans, err := cmd.Flags().GetBool("remove-orphans") 103 if err != nil { 104 return err 105 } 106 107 name, err := cmd.Flags().GetString("name") 108 if err != nil { 109 return err 110 } 111 nodeps, err := cmd.Flags().GetBool("no-deps") 112 if err != nil { 113 return err 114 } 115 116 interactive, err := cmd.Flags().GetBool("interactive") 117 if err != nil { 118 return err 119 } 120 // FIXME : https://github.com/containerd/nerdctl/blob/v0.22.2/cmd/nerdctl/run.go#L100 121 tty := interactive 122 rm, err := cmd.Flags().GetBool("rm") 123 if err != nil { 124 return err 125 } 126 user, err := cmd.Flags().GetString("user") 127 if err != nil { 128 return err 129 } 130 volume, err := cmd.Flags().GetStringArray("volume") 131 if err != nil { 132 return err 133 } 134 entrypoint, err := cmd.Flags().GetStringArray("entrypoint") 135 if err != nil { 136 return err 137 } 138 env, err := cmd.Flags().GetStringArray("env") 139 if err != nil { 140 return err 141 } 142 label, err := cmd.Flags().GetStringArray("label") 143 if err != nil { 144 return err 145 } 146 workdir, err := cmd.Flags().GetString("workdir") 147 if err != nil { 148 return err 149 } 150 publish, err := cmd.Flags().GetStringSlice("publish") 151 if err != nil { 152 return err 153 } 154 servicePorts, err := cmd.Flags().GetBool("service-ports") 155 if err != nil { 156 return err 157 } 158 159 if servicePorts && publish != nil && len(publish) > 0 { 160 return fmt.Errorf("--service-ports and --publish(-p) cannot exist simultaneously") 161 } 162 // https://github.com/containerd/nerdctl/blob/v0.22.2/cmd/nerdctl/run.go#L475 163 if interactive && detach { 164 return errors.New("currently flag -i and -d cannot be specified together (FIXME)") 165 } 166 167 // https://github.com/containerd/nerdctl/blob/v0.22.2/cmd/nerdctl/run.go#L479 168 if tty && detach { 169 return errors.New("currently flag -t and -d cannot be specified together (FIXME)") 170 } 171 172 client, ctx, cancel, err := clientutil.NewClient(cmd.Context(), globalOptions.Namespace, globalOptions.Address) 173 if err != nil { 174 return err 175 } 176 defer cancel() 177 options, err := getComposeOptions(cmd, globalOptions.DebugFull, globalOptions.Experimental) 178 if err != nil { 179 return err 180 } 181 c, err := compose.New(client, globalOptions, options, cmd.OutOrStdout(), cmd.ErrOrStderr()) 182 if err != nil { 183 return err 184 } 185 186 ro := composer.RunOptions{ 187 Detach: detach, 188 NoBuild: noBuild, 189 NoColor: noColor, 190 NoLogPrefix: noLogPrefix, 191 ForceBuild: build, 192 QuietPull: quietPull, 193 RemoveOrphans: removeOrphans, 194 195 ServiceName: args[0], 196 Args: args[1:], 197 198 Name: name, 199 NoDeps: nodeps, 200 Tty: tty, 201 Interactive: interactive, 202 Rm: rm, 203 User: user, 204 Volume: volume, 205 Entrypoint: entrypoint, 206 Env: env, 207 Label: label, 208 WorkDir: workdir, 209 ServicePorts: servicePorts, 210 Publish: publish, 211 } 212 213 return c.Run(ctx, ro) 214 }