in agent/engine/docker_task_engine.go [941:1024]
func (engine *DockerTaskEngine) pullAndUpdateContainerReference(task *apitask.Task, container *apicontainer.Container) dockerapi.DockerContainerMetadata {
// If a task is blocked here for some time, and before it starts pulling image,
// the task's desired status is set to stopped, then don't pull the image
if task.GetDesiredStatus() == apitaskstatus.TaskStopped {
seelog.Infof("Task engine [%s]: task's desired status is stopped, skipping pulling image %s for container %s",
task.Arn, container.Image, container.Name)
container.SetDesiredStatus(apicontainerstatus.ContainerStopped)
return dockerapi.DockerContainerMetadata{Error: TaskStoppedBeforePullBeginError{task.Arn}}
}
// Set the credentials for pull from ECR if necessary
if container.ShouldPullWithExecutionRole() {
executionCredentials, ok := engine.credentialsManager.GetTaskCredentials(task.GetExecutionCredentialsID())
if !ok {
seelog.Errorf("Task engine [%s]: unable to acquire ECR credentials for image %s for container %s",
task.Arn, container.Image, container.Name)
return dockerapi.DockerContainerMetadata{
Error: dockerapi.CannotPullECRContainerError{
FromError: errors.New("engine ecr credentials: not found"),
},
}
}
iamCredentials := executionCredentials.GetIAMRoleCredentials()
container.SetRegistryAuthCredentials(iamCredentials)
// Clean up the ECR pull credentials after pulling
defer container.SetRegistryAuthCredentials(credentials.IAMRoleCredentials{})
}
// Apply registry auth data from ASM if required
if container.ShouldPullWithASMAuth() {
if err := task.PopulateASMAuthData(container); err != nil {
seelog.Errorf("Task engine [%s]: unable to acquire Docker registry credentials for image %s for container %s",
task.Arn, container.Image, container.Name)
return dockerapi.DockerContainerMetadata{
Error: dockerapi.CannotPullContainerAuthError{
FromError: errors.New("engine docker private registry credentials: not found"),
},
}
}
defer container.SetASMDockerAuthConfig(types.AuthConfig{})
}
metadata := engine.client.PullImage(engine.ctx, container.Image, container.RegistryAuthentication, engine.cfg.ImagePullTimeout)
// Don't add internal images(created by ecs-agent) into imagemanger state
if container.IsInternal() {
return metadata
}
pullSucceeded := metadata.Error == nil
findCachedImage := false
if !pullSucceeded {
// If Agent failed to pull an image when
// 1. DependentContainersPullUpfront is enabled
// 2. ImagePullBehavior is not set to always
// search the image in local cached images
if engine.cfg.DependentContainersPullUpfront.Enabled() && engine.cfg.ImagePullBehavior != config.ImagePullAlwaysBehavior {
if _, err := engine.client.InspectImage(container.Image); err != nil {
seelog.Errorf("Task engine [%s]: failed to find cached image %s for container %s",
task.Arn, container.Image, container.Name)
// Stop the task if the container is an essential container,
// and the image is not available in both remote and local caches
if container.IsEssential() {
task.SetDesiredStatus(apitaskstatus.TaskStopped)
engine.emitTaskEvent(task, fmt.Sprintf("%s: %s", metadata.Error.ErrorName(), metadata.Error.Error()))
}
return dockerapi.DockerContainerMetadata{Error: metadata.Error}
}
seelog.Infof("Task engine [%s]: found cached image %s, use it directly for container %s",
task.Arn, container.Image, container.Name)
findCachedImage = true
}
}
if pullSucceeded || findCachedImage {
dockerContainer := &apicontainer.DockerContainer{
Container: container,
}
engine.state.AddPulledContainer(dockerContainer, task)
}
engine.updateContainerReference(pullSucceeded, container, task.Arn)
return metadata
}