Skip to content

Commit

Permalink
feat(deployment): prefix container names with project name
Browse files Browse the repository at this point in the history
BREAKING CHANGE: Container naming convention now includes project prefix
  • Loading branch information
yarlson committed Jan 16, 2025
1 parent 4ad0143 commit 6be316a
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 24 deletions.
14 changes: 9 additions & 5 deletions pkg/deployment/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,19 +127,19 @@ func (d *Deployment) performHealthChecks(container string, healthCheck *config.H
return fmt.Errorf("container failed to become healthy\n\x1b[93mOutput from the container:\x1b[0m\n%s", grayOutput)
}

func (d *Deployment) startContainer(service *config.Service) error {
_, err := d.runCommand(context.Background(), "docker", "start", service.Name)
func (d *Deployment) startContainer(container string) error {
_, err := d.runCommand(context.Background(), "docker", "start", container)
if err != nil {
return fmt.Errorf("failed to start container for %s: %v", service.Name, err)
return fmt.Errorf("failed to start container for %s: %v", container, err)
}

return nil
}

func (d *Deployment) createContainer(project string, service *config.Service, suffix string) error {
svcName := service.Name
container := containerName(project, service.Name, suffix)

args := []string{"run", "-d", "--name", svcName + suffix, "--network", project, "--network-alias", svcName + suffix, "--restart", "unless-stopped"}
args := []string{"run", "-d", "--name", container, "--network", project, "--network-alias", service.Name + suffix, "--restart", "unless-stopped"}

for _, value := range service.Env {
args = append(args, "-e", value)
Expand Down Expand Up @@ -219,3 +219,7 @@ func (d *Deployment) containerShouldBeUpdated(project string, service *config.Se

return containerInfo.Config.Labels["ftl.config-hash"] != hash, nil
}

func containerName(project, service, suffix string) string {
return fmt.Sprintf("%s-%s%s", project, service, suffix)
}
5 changes: 3 additions & 2 deletions pkg/deployment/deployment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,10 +215,11 @@ func (suite *DeploymentTestSuite) TestDeploy() {
fmt.Printf("Total requests: %d\n", requestStats.totalRequests)
fmt.Printf("Failed requests: %d\n", requestStats.failedRequests)

serviceName := "web"
suite.Require().Equal(int32(0), requestStats.failedRequests, "Expected zero failed requests during zero-downtime deployment")

containerInfo := suite.inspectContainer(serviceName)
serviceName := "web"
containerName := containerName(project, serviceName, "")
containerInfo := suite.inspectContainer(containerName)

suite.Run("Updated Container State and Config", func() {
state := containerInfo["State"].(map[string]interface{})
Expand Down
37 changes: 20 additions & 17 deletions pkg/deployment/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ func (d *Deployment) deployService(project string, service *config.Service) erro
}

if containerStatus == ContainerStatusStopped {
if err := d.startContainer(service); err != nil {
container := containerName(project, service.Name, "")
if err := d.startContainer(container); err != nil {
return fmt.Errorf("failed to start container %s: %w", service.Name, err)
}
return nil
Expand All @@ -91,17 +92,17 @@ func (d *Deployment) installService(project string, service *config.Service) err
return fmt.Errorf("failed to start container for %s: %v", service.Image, err)
}

svcName := service.Name
container := containerName(project, service.Name, "")

if err := d.performHealthChecks(svcName, service.HealthCheck); err != nil {
return fmt.Errorf("install failed for %s: container is unhealthy: %w", svcName, err)
if err := d.performHealthChecks(container, service.HealthCheck); err != nil {
return fmt.Errorf("install failed for %s: container is unhealthy: %w", container, err)
}

return nil
}

func (d *Deployment) updateService(project string, service *config.Service) error {
svcName := service.Name
container := containerName(project, service.Name, "")

if service.Recreate {
if err := d.recreateService(project, service); err != nil {
Expand All @@ -111,23 +112,23 @@ func (d *Deployment) updateService(project string, service *config.Service) erro
}

if err := d.createContainer(project, service, newContainerSuffix); err != nil {
return fmt.Errorf("failed to start new container for %s: %v", svcName, err)
return fmt.Errorf("failed to start new container for %s: %v", container, err)
}

if err := d.performHealthChecks(svcName+newContainerSuffix, service.HealthCheck); err != nil {
if _, err := d.runCommand(context.Background(), "docker", "rm", "-f", svcName+newContainerSuffix); err != nil {
return fmt.Errorf("update failed for %s: new container is unhealthy and cleanup failed: %v", svcName, err)
if err := d.performHealthChecks(container+newContainerSuffix, service.HealthCheck); err != nil {
if _, err := d.runCommand(context.Background(), "docker", "rm", "-f", container+newContainerSuffix); err != nil {
return fmt.Errorf("update failed for %s: new container is unhealthy and cleanup failed: %v", container, err)
}
return fmt.Errorf("update failed for %s: new container is unhealthy: %w", svcName, err)
return fmt.Errorf("update failed for %s: new container is unhealthy: %w", container, err)
}

oldContID, err := d.switchTraffic(project, svcName)
oldContID, err := d.switchTraffic(project, service.Name)
if err != nil {
return fmt.Errorf("failed to switch traffic for %s: %v", svcName, err)
return fmt.Errorf("failed to switch traffic for %s: %v", container, err)
}

if err := d.cleanup(oldContID, svcName); err != nil {
return fmt.Errorf("failed to cleanup for %s: %v", svcName, err)
if err := d.cleanup(project, oldContID, service.Name); err != nil {
return fmt.Errorf("failed to cleanup for %s: %v", container, err)
}

return nil
Expand Down Expand Up @@ -162,7 +163,7 @@ func (d *Deployment) recreateService(project string, service *config.Service) er
}

func (d *Deployment) switchTraffic(project, service string) (string, error) {
newContainer := service + newContainerSuffix
newContainer := containerName(project, service, newContainerSuffix)
oldContainer, err := d.getContainerID(project, service)
if err != nil {
return "", fmt.Errorf("failed to get old container ID: %v", err)
Expand Down Expand Up @@ -194,11 +195,13 @@ func (d *Deployment) switchTraffic(project, service string) (string, error) {
return oldContainer, nil
}

func (d *Deployment) cleanup(oldContID, service string) error {
func (d *Deployment) cleanup(project, oldContID, service string) error {
oldContainer := containerName(project, service, newContainerSuffix)
newContainer := containerName(project, service, "")
cmds := [][]string{
{"docker", "stop", oldContID},
{"docker", "rm", oldContID},
{"docker", "rename", service + newContainerSuffix, service},
{"docker", "rename", oldContainer, newContainer},
}

for _, cmd := range cmds {
Expand Down

0 comments on commit 6be316a

Please sign in to comment.