github.com/bshelton229/agent@v3.5.4+incompatible/bootstrap/docker.go (about) 1 package bootstrap 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/buildkite/agent/bootstrap/shell" 8 "github.com/pkg/errors" 9 ) 10 11 var dockerEnv = []string{ 12 `BUILDKITE_DOCKER_COMPOSE_CONTAINER`, 13 `BUILDKITE_DOCKER_COMPOSE_FILE`, 14 `BUILDKITE_DOCKER`, 15 `BUILDKITE_DOCKER_FILE`, 16 `BUILDKITE_DOCKER_COMPOSE_BUILD_ALL`, 17 `BUILDKITE_DOCKER_COMPOSE_LEAVE_VOLUMES`, 18 } 19 20 func hasDeprecatedDockerIntegration(sh *shell.Shell) bool { 21 for _, k := range dockerEnv { 22 if sh.Env.Exists(k) { 23 return true 24 } 25 } 26 return false 27 } 28 29 func runDeprecatedDockerIntegration(sh *shell.Shell, cmd []string) error { 30 var warnNotSet = func(k1, k2 string) { 31 sh.Warningf("%s is set, but without %s, which it requires. You should be able to safely remove this from your pipeline.", k1, k2) 32 } 33 34 switch { 35 case sh.Env.Exists(`BUILDKITE_DOCKER_COMPOSE_CONTAINER`): 36 sh.Warningf("BUILDKITE_DOCKER_COMPOSE_CONTAINER is set, which is deprecated in Agent v3 and will be removed in v4. Consider using the :docker: docker-compose plugin instead at https://github.com/buildkite-plugins/docker-compose-buildkite-plugin.") 37 return runDockerComposeCommand(sh, cmd) 38 39 case sh.Env.Exists(`BUILDKITE_DOCKER`): 40 sh.Warningf("BUILDKITE_DOCKER is set, which is deprecated in Agent v3 and will be removed in v4. Consider using the docker plugin instead at https://github.com/buildkite-plugins/docker-buildkite-plugin.") 41 return runDockerCommand(sh, cmd) 42 43 case sh.Env.Exists(`BUILDKITE_DOCKER_COMPOSE_FILE`): 44 warnNotSet(`BUILDKITE_DOCKER_COMPOSE_FILE`, `BUILDKITE_DOCKER_COMPOSE_CONTAINER`) 45 46 case sh.Env.Exists(`BUILDKITE_DOCKER_COMPOSE_BUILD_ALL`): 47 warnNotSet(`BUILDKITE_DOCKER_COMPOSE_BUILD_ALL`, `BUILDKITE_DOCKER_COMPOSE_CONTAINER`) 48 49 case sh.Env.Exists(`BUILDKITE_DOCKER_COMPOSE_LEAVE_VOLUMES`): 50 warnNotSet(`BUILDKITE_DOCKER_COMPOSE_LEAVE_VOLUMES`, `BUILDKITE_DOCKER_COMPOSE_CONTAINER`) 51 52 case sh.Env.Exists(`BUILDKITE_DOCKER_COMPOSE_LEAVE_VOLUMES`): 53 warnNotSet(`BUILDKITE_DOCKER_COMPOSE_LEAVE_VOLUMES`, `BUILDKITE_DOCKER_COMPOSE_CONTAINER`) 54 } 55 56 return errors.New("Failed to find any docker env") 57 } 58 59 func tearDownDeprecatedDockerIntegration(sh *shell.Shell) error { 60 if container, ok := sh.Env.Get(`DOCKER_CONTAINER`); ok { 61 sh.Printf("~~~ Cleaning up Docker containers") 62 63 if err := sh.Run("docker", "rm", "-f", "-v", container); err != nil { 64 return err 65 } 66 } else if projectName, ok := sh.Env.Get(`COMPOSE_PROJ_NAME`); ok { 67 sh.Printf("~~~ Cleaning up Docker containers") 68 69 // Friendly kill 70 _ = runDockerCompose(sh, projectName, "kill") 71 72 if sh.Env.GetBool(`BUILDKITE_DOCKER_COMPOSE_LEAVE_VOLUMES`, false) { 73 _ = runDockerCompose(sh, projectName, "rm", "--force", "--all") 74 } else { 75 _ = runDockerCompose(sh, projectName, "rm", "--force", "--all", "-v") 76 } 77 78 return runDockerCompose(sh, projectName, "down") 79 } 80 81 return nil 82 } 83 84 // runDockerCommand executes a command inside a docker container that is built as needed 85 // Ported from https://github.com/buildkite/agent/blob/2b8f1d569b659e07de346c0e3ae7090cb98e49ba/templates/bootstrap.sh#L439 86 func runDockerCommand(sh *shell.Shell, cmd []string) error { 87 jobId, _ := sh.Env.Get(`BUILDKITE_JOB_ID`) 88 dockerContainer := fmt.Sprintf("buildkite_%s_container", jobId) 89 dockerImage := fmt.Sprintf("buildkite_%s_image", jobId) 90 91 dockerFile, _ := sh.Env.Get(`BUILDKITE_DOCKER_FILE`) 92 if dockerFile == "" { 93 dockerFile = "Dockerfile" 94 } 95 96 sh.Env.Set(`DOCKER_CONTAINER`, dockerContainer) 97 sh.Env.Set(`DOCKER_IMAGE`, dockerImage) 98 99 sh.Printf("~~~ :docker: Building Docker image %s", dockerImage) 100 if err := sh.Run("docker", "build", "-f", dockerFile, "-t", dockerImage, "."); err != nil { 101 return err 102 } 103 104 sh.Headerf(":docker: Running command (in Docker container)") 105 if err := sh.Run("docker", append([]string{"run", "--name", dockerContainer, dockerImage}, cmd...)...); err != nil { 106 return err 107 } 108 109 return nil 110 } 111 112 // runDockerComposeCommand executes a command with docker-compose 113 // Ported from https://github.com/buildkite/agent/blob/2b8f1d569b659e07de346c0e3ae7090cb98e49ba/templates/bootstrap.sh#L462 114 func runDockerComposeCommand(sh *shell.Shell, cmd []string) error { 115 composeContainer, _ := sh.Env.Get(`BUILDKITE_DOCKER_COMPOSE_CONTAINER`) 116 jobId, _ := sh.Env.Get(`BUILDKITE_JOB_ID`) 117 118 // Compose strips dashes and underscores, so we'll remove them 119 // to match the docker container names 120 projectName := strings.Replace(fmt.Sprintf("buildkite%s", jobId), "-", "", -1) 121 122 sh.Env.Set(`COMPOSE_PROJ_NAME`, projectName) 123 sh.Headerf(":docker: Building Docker images") 124 125 if sh.Env.GetBool(`BUILDKITE_DOCKER_COMPOSE_BUILD_ALL`, false) { 126 if err := runDockerCompose(sh, projectName, "build", "--pull"); err != nil { 127 return err 128 } 129 } else { 130 if err := runDockerCompose(sh, projectName, "build", "--pull", composeContainer); err != nil { 131 return err 132 } 133 } 134 135 sh.Headerf(":docker: Running command (in Docker Compose container)") 136 return runDockerCompose(sh, projectName, append([]string{"run", composeContainer}, cmd...)...) 137 } 138 139 func runDockerCompose(sh *shell.Shell, projectName string, commandArgs ...string) error { 140 args := []string{} 141 142 composeFile, _ := sh.Env.Get(`BUILDKITE_DOCKER_COMPOSE_FILE`) 143 if composeFile == "" { 144 composeFile = "docker-compose.yml" 145 } 146 147 // composeFile might be multiple files, spaces or colons 148 for _, chunk := range strings.Fields(composeFile) { 149 for _, file := range strings.Split(chunk, ":") { 150 args = append(args, "-f", file) 151 } 152 } 153 154 args = append(args, "-p", projectName) 155 156 if sh.Env.GetBool(`BUILDKITE_AGENT_DEBUG`, false) { 157 args = append(args, "--verbose") 158 } 159 160 args = append(args, commandArgs...) 161 return sh.Run("docker-compose", args...) 162 }