feat(entrypoint): allow to override service ENTRYPOINT for run command

This commit is contained in:
Pavel Sviderski
2025-03-18 16:44:15 +10:00
parent e8715fce38
commit 1bbcfa8519
4 changed files with 34 additions and 16 deletions
+21 -8
View File
@@ -13,14 +13,16 @@ import (
) )
type runOptions struct { type runOptions struct {
command []string command []string
image string entrypoint string
machines []string entrypointChanged bool
mode string image string
name string machines []string
publish []string mode string
replicas uint name string
volumes []string publish []string
replicas uint
volumes []string
cluster string cluster string
} }
@@ -35,6 +37,7 @@ func NewRunCommand() *cobra.Command {
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
uncli := cmd.Context().Value("cli").(*cli.CLI) uncli := cmd.Context().Value("cli").(*cli.CLI)
opts.entrypointChanged = cmd.Flag("entrypoint").Changed
opts.image = args[0] opts.image = args[0]
if len(args) > 1 { if len(args) > 1 {
opts.command = args[1:] opts.command = args[1:]
@@ -44,6 +47,8 @@ func NewRunCommand() *cobra.Command {
}, },
} }
cmd.Flags().StringVar(&opts.entrypoint, "entrypoint", "",
"Overwrite the default ENTRYPOINT of the image. Pass an empty string \"\" to reset it.")
cmd.Flags().StringVar(&opts.mode, "mode", api.ServiceModeReplicated, cmd.Flags().StringVar(&opts.mode, "mode", api.ServiceModeReplicated,
fmt.Sprintf("Replication mode of the service: either %q (a specified number of containers across "+ fmt.Sprintf("Replication mode of the service: either %q (a specified number of containers across "+
"the machines) or %q (one container on every machine).", "the machines) or %q (one container on every machine).",
@@ -128,6 +133,14 @@ func run(ctx context.Context, uncli *cli.CLI, opts runOptions) error {
Ports: ports, Ports: ports,
Replicas: opts.replicas, Replicas: opts.replicas,
} }
// Overwrite the default ENTRYPOINT of the image or reset it if an empty string is passed.
if opts.entrypoint != "" {
spec.Container.Entrypoint = []string{opts.entrypoint}
} else if opts.entrypointChanged {
spec.Container.Entrypoint = []string{""}
}
if err := spec.Validate(); err != nil { if err := spec.Validate(); err != nil {
return fmt.Errorf("invalid service configuration: %w", err) return fmt.Errorf("invalid service configuration: %w", err)
} }
+5 -4
View File
@@ -75,10 +75,11 @@ func (c *Container) ServiceSpec() (ServiceSpec, error) {
// is created. Figure out how to get a spec that is equal to the initial spec. // is created. Figure out how to get a spec that is equal to the initial spec.
return ServiceSpec{ return ServiceSpec{
Container: ContainerSpec{ Container: ContainerSpec{
Command: c.Config.Cmd, Command: c.Config.Cmd,
Image: c.Config.Image, Entrypoint: c.Config.Entrypoint,
Init: c.HostConfig.Init, Image: c.Config.Image,
Volumes: c.HostConfig.Binds, Init: c.HostConfig.Init,
Volumes: c.HostConfig.Binds,
}, },
Mode: c.ServiceMode(), Mode: c.ServiceMode(),
Name: c.ServiceName(), Name: c.ServiceName(),
+4 -1
View File
@@ -67,8 +67,11 @@ func ValidateServiceID(id string) bool {
} }
type ContainerSpec struct { type ContainerSpec struct {
// Command overrides the default CMD of the image to be executed when running a container.
Command []string Command []string
Image string // Entrypoint overrides the default ENTRYPOINT of the image.
Entrypoint []string
Image string
// Run a custom init inside the container. If nil, use the daemon's configured settings. // Run a custom init inside the container. If nil, use the daemon's configured settings.
Init *bool Init *bool
// List of volumes to bind mount into the container. // List of volumes to bind mount into the container.
+4 -3
View File
@@ -42,9 +42,10 @@ func (cli *Client) CreateContainer(
// TODO: calculate the spec hash and set it as a label to detect changes in the service spec. // TODO: calculate the spec hash and set it as a label to detect changes in the service spec.
config := &container.Config{ config := &container.Config{
Cmd: spec.Container.Command, Cmd: spec.Container.Command,
Hostname: containerName, Entrypoint: spec.Container.Entrypoint,
Image: spec.Container.Image, Hostname: containerName,
Image: spec.Container.Image,
Labels: map[string]string{ Labels: map[string]string{
api.LabelServiceID: serviceID, api.LabelServiceID: serviceID,
api.LabelServiceName: spec.Name, api.LabelServiceName: spec.Name,